diff --git a/BUILD.gn b/BUILD.gn
index acd070c7f87bd500fea227e6f4dea535f72e68a6..107f3da944c0daad128b99111f5d10c9a10da02c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -32,7 +32,7 @@ config("export_dynamic_symbols") {
# -exported_symbols_list is the macOS linker syntax. The different flags
# accept files formatted differently, so we have exported_symbols.sym for GNU
# linker syntax, and exported_symbols_mac.sym for the macOS linker syntax.
- if (is_linux || is_fuchsia) {
+ if (is_ohos|| is_linux || is_fuchsia) {
inputs = [ "//flutter/common/exported_symbols.sym" ]
ldflags = [ "-Wl,--dynamic-list=" + rebase_path(inputs[0], root_build_dir) ]
} else if (is_mac) {
diff --git a/OAT.xml b/OAT.xml
new file mode 100644
index 0000000000000000000000000000000000000000..af9f8562b5e0d50df12cdb4839ed2669ee325dd6
--- /dev/null
+++ b/OAT.xml
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.OpenSource b/README.OpenSource
new file mode 100644
index 0000000000000000000000000000000000000000..4302db9e1a841b6fff69a97551d3b5fe2468a6ba
--- /dev/null
+++ b/README.OpenSource
@@ -0,0 +1,11 @@
+[
+ {
+ "Name": "engine",
+ "License": "BSD 3-Clause License",
+ "License File": "LICENSE",
+ "Version Number": "3.7.12",
+ "Owner": "aibin@openvalley.net",
+ "Upstream URL": "https://flutter.dev/",
+ "Description": "The Flutter Engine is a portable runtime for hosting Flutter applications. It implements Flutter's core libraries, including animation and graphics, file and network I/O, accessibility support, plugin architecture, and a Dart runtime and compile toolchain. Most developers will interact with Flutter via the Flutter Framework, which provides a modern, reactive framework, and a rich set of platform, layout and foundation widgets."
+ }
+]
\ No newline at end of file
diff --git a/README.en.md b/README.en.md
new file mode 100644
index 0000000000000000000000000000000000000000..9b9ebdfa6cd7582597f44fe60bf1070ad3095966
--- /dev/null
+++ b/README.en.md
@@ -0,0 +1,37 @@
+Flutter Engine
+===============
+
+Source of original warehouse: https://github.com/flutter/engine
+
+## Warehouse description:
+This repository is based on the extension of flutter's official engine repository, which can build flutter engine programs that support running on OpenHarmony devices.
+
+## Build instructions:
+
+* Build environment:
+1. Currently only supports building under linux;
+
+2. Please ensure that the current build environment can access the allowed_hosts list configured in DEPS.
+
+* Build steps:
+1. Refer to https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment to configure the build environment under linux;
+
+2. Obtain the source code, create an empty folder engine, create a new .gclient file in the engine, and edit the file:
+```
+solutions = [
+ {
+ "managed": False,
+ "name": "src/flutter",
+ "url": "git@gitee.com:openharmony-sig/flutter_engine.git",
+ "custom_deps": {},
+ "deps_file": "DEPS",
+ "safesync_url": "",
+ },
+]
+```
+
+3. In the engine directory, execute 'gclient sync' command; here, the engine source code, the official packages warehouse, and the ohos_setup task will be executed;
+
+4. From the daily build at http://ci.openharmony.cn/workbench/cicd/dailybuild/dailylist, download ohos-sdk-full, create a new folder 'ndk/4.0' in the engine root directory, and decompress 'ohos-sdk-all' files in the 'native' folder in the full sdk are transferred to the 'ndk/4.0' folder;
+
+5. In the engine directory, execute 'make' command to start building the flutter engine that supports ohos devices.
\ No newline at end of file
diff --git a/README.md b/README.md
index 0f2caad12a80448b06abb62f26de74b8d98b25c5..fd6857e32a687133548ce7d8e0c7da3c37af388d 100644
--- a/README.md
+++ b/README.md
@@ -1,36 +1,38 @@
Flutter Engine
==============
-[](https://api.securityscorecards.dev/projects/github.com/flutter/engine)
-
-Flutter is Google's SDK for crafting beautiful, fast user experiences for
-mobile, web, and desktop from a single codebase. Flutter works with existing
-code, is used by developers and organizations around the world, and is free
-and open source.
-
-The Flutter Engine is a portable runtime for hosting
-[Flutter](https://flutter.dev) applications. It implements Flutter's core
-libraries, including animation and graphics, file and network I/O,
-accessibility support, plugin architecture, and a Dart runtime and compile
-toolchain. Most developers will interact with Flutter via the [Flutter
-Framework](https://github.com/flutter/flutter), which provides a modern,
-reactive framework, and a rich set of platform, layout and foundation widgets.
-
-If you want to run/contribute to Flutter Web engine, more tooling can be
-found at [felt](https://github.com/flutter/engine/tree/main/lib/web_ui#using-felt).
-This is a tool written to make web engine development experience easy.
-
-If you are new to Flutter, then you will find more general information
-on the Flutter project, including tutorials and samples, on our Web
-site at [Flutter.dev](https://flutter.dev). For specific information
-about Flutter's APIs, consider our API reference which can be found at
-the [docs.flutter.dev](https://docs.flutter.dev/).
-
-Flutter is a fully open source project, and we welcome contributions.
-Information on how to get started can be found at our
-[contributor guide](CONTRIBUTING.md).
-
-[Build Status - Cirrus]: https://api.cirrus-ci.com/github/flutter/engine.svg?branch=main
-
-[Build status]: https://cirrus-ci.com/github/flutter/engine
+原始仓来源:https://github.com/flutter/engine
+
+## 仓库说明:
+本仓库是基于flutter官方engine仓库拓展,可构建支持在OpenHarmony设备上运行的flutter engine程序。
+
+## 构建说明:
+
+* 构建环境:
+1. 目前仅支持linux下构建;
+
+2. 请确保当前构建环境,可以访问DEPS中配置的allowed_hosts列表。
+
+* 构建步骤:
+1. 参照https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment 说明,配置好linux下构建环境;
+
+2. 获取源码,创建空文件夹engine,engine内新建.gclient文件,编辑文件:
+```
+solutions = [
+ {
+ "managed": False,
+ "name": "src/flutter",
+ "url": "git@gitee.com:openharmony-sig/flutter_engine.git",
+ "custom_deps": {},
+ "deps_file": "DEPS",
+ "safesync_url": "",
+ },
+]
+```
+
+3. 在engine目录,执行gclient sync;这里会同步engine源码、官方packages仓,还有执行ohos_setup任务;
+
+4. 从 http://ci.openharmony.cn/workbench/cicd/dailybuild/dailylist 每日构建中,下载ohos-sdk-full,在engine根目录下,新建文件夹 ndk/4.0 ,解压ohos-sdk-full sdk中的native文件夹内所有文件到 ndk/4.0文件夹中;
+
+5. engine目录,执行make,既可以开始构建支持ohos设备的flutter engine。
diff --git a/fml/BUILD.gn b/fml/BUILD.gn
index 0b25ea59f8df063b8c6442d89296477f7294bde0..ddcb7cb64b195e140aa02c5fd69c6cd95fce8966 100644
--- a/fml/BUILD.gn
+++ b/fml/BUILD.gn
@@ -97,8 +97,13 @@ source_set("fml") {
"wakeable.h",
]
- if (is_mac || is_linux || is_win || (is_ios && is_debug)) {
- sources += [ "backtrace.cc" ]
+ if( is_ohos){
+ sources += [ "backtrace_stub.cc" ]
+ }else if ( is_linux){
+ sources += [ "backtrace_stub.cc" ]
+ }else if (is_mac || is_linux || is_win || (is_ios && is_debug)) {
+ #sources += [ "backtrace.cc" ]
+ sources += [ "backtrace_stub.cc" ]
} else {
sources += [ "backtrace_stub.cc" ]
}
@@ -183,7 +188,23 @@ source_set("fml") {
]
}
- if (is_linux) {
+ if (is_ohos) {
+ sources += [
+ "platform/ohos/message_loop_ohos.cc",
+ "platform/ohos/message_loop_ohos.h",
+ "platform/ohos/paths_ohos.cc",
+ "platform/ohos/paths_ohos.h",
+ "platform/ohos/timerfd.cc",
+ "platform/ohos/timerfd.h",
+ #"platform/ohos/message_loop_ohos_test.cc",
+ #"platform/ohos/message_loop_ohos_test.h",
+ "platform/ohos/napi_util.h",
+ "platform/ohos/napi_util.cc",
+ ]
+ libs += [ "hilog_ndk.z" ]
+ libs += [ "ace_napi.z" ]
+ libs += [ "uv" ]
+ }else if (is_linux) {
sources += [
"platform/linux/message_loop_linux.cc",
"platform/linux/message_loop_linux.h",
diff --git a/fml/backtrace.cc b/fml/backtrace.cc
index 264fa7d0bcda5099689a42f5d4f5831d18b3a0b9..3a3be765a6e63b33b2c11ae6c92e940f7164ca88 100644
--- a/fml/backtrace.cc
+++ b/fml/backtrace.cc
@@ -17,7 +17,7 @@
#include
#include
#else // FML_OS_WIN
-#include
+//#include
#endif // FML_OS_WIN
namespace fml {
diff --git a/fml/build_config.h b/fml/build_config.h
index 3c7ebc9528d7942066b3176e98a9e683537d0ee2..a43431f1a03266454a84b06d2e7639b78d5b6dfe 100644
--- a/fml/build_config.h
+++ b/fml/build_config.h
@@ -29,6 +29,16 @@
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
#define FML_OS_IOS 1
#endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+
+#elif defined(__OHOS_FAMILY__)
+#define FML_OS_OHOS 1
+// include a system header to pull in features.h for glibc/uclibc macros.
+#include
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
+// we really are using glibc, not uClibc pretending to be glibc
+#define LIBC_GLIBC 1
+#endif
+
#elif defined(__linux__)
#define FML_OS_LINUX 1
// include a system header to pull in features.h for glibc/uclibc macros.
@@ -37,6 +47,8 @@
// we really are using glibc, not uClibc pretending to be glibc
#define LIBC_GLIBC 1
#endif
+
+
#elif defined(_WIN32)
#define FML_OS_WIN 1
#elif defined(__FreeBSD__)
diff --git a/fml/log_level.h b/fml/log_level.h
index 2c9a85305b53d591bfa9dde5b76cadcca3fbd1dd..79316f86b657a66114aab8ff2a926335912f97f7 100644
--- a/fml/log_level.h
+++ b/fml/log_level.h
@@ -15,6 +15,7 @@ constexpr LogSeverity LOG_WARNING = 1;
constexpr LogSeverity LOG_ERROR = 2;
constexpr LogSeverity LOG_FATAL = 3;
constexpr LogSeverity LOG_NUM_SEVERITIES = 4;
+constexpr LogSeverity LOG_DEBUG= 4;
// One of the Windows headers defines ERROR to 0. This makes the token
// concatenation in FML_LOG(ERROR) to resolve to LOG_0. We define this back to
diff --git a/fml/logging.cc b/fml/logging.cc
index 5a0280e0f0c25904988199ffc6233c733f345a79..88c537dab0ad43bed282cb50c509d9e9dba6889f 100644
--- a/fml/logging.cc
+++ b/fml/logging.cc
@@ -18,6 +18,32 @@
#include
#endif
+#ifdef FML_OS_OHOS
+#include
+
+extern "C"{
+#define OHOS_LOG_TYPE_APP 0
+#define HILOG_LOG_DOMAIN 0
+#define HILOG_LOG_TAG "XComFlutterEngine"
+ typedef enum {
+ /** Debug level to be used by {@link OH_LOG_DEBUG} */
+ HILOG_LOG_DEBUG = 3,
+ /** Informational level to be used by {@link OH_LOG_INFO} */
+ HILOG_LOG_INFO = 4,
+ /** Warning level to be used by {@link OH_LOG_WARN} */
+ HILOG_LOG_WARN = 5,
+ /** Error level to be used by {@link OH_LOG_ERROR} */
+ HILOG_LOG_ERROR = 6,
+ /** Fatal level to be used by {@link OH_LOG_FATAL} */
+ HILOG_LOG_FATAL = 7,
+} HiLog_LogLevel;
+int OH_LOG_Print(int type, HiLog_LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) ;
+#define HILOG_LOG(level,...) ((void)OH_LOG_Print(OHOS_LOG_TYPE_APP, (level), HILOG_LOG_DOMAIN, HILOG_LOG_TAG, __VA_ARGS__))
+#define HILOG_DEBUG(...) ((void)OH_LOG_Print(OHOS_LOG_TYPE_APP, HILOG_LOG_DEBUG, HILOG_LOG_DOMAIN, HILOG_LOG_TAG, __VA_ARGS__))
+#define HILOG_ERROR(...) ((void)OH_LOG_Print(OHOS_LOG_TYPE_APP, HILOG_LOG_ERROR, HILOG_LOG_DOMAIN, HILOG_LOG_TAG, __VA_ARGS__))
+#define HILOG_INFO(...) ((void)OH_LOG_Print(OHOS_LOG_TYPE_APP, HILOG_LOG_INFO, HILOG_LOG_DOMAIN, HILOG_LOG_TAG, __VA_ARGS__))
+}
+#endif
namespace fml {
namespace {
@@ -122,6 +148,30 @@ LogMessage::~LogMessage() {
}
fx_logger_log_with_source(fx_log_get_logger(), fx_severity, nullptr, file_,
line_, stream_.str().c_str());
+#elif defined(FML_OS_OHOS)
+ HiLog_LogLevel fx_severity;
+
+ switch (severity_) {
+ case LOG_INFO:
+ fx_severity= HILOG_LOG_INFO;
+ break;
+ case LOG_WARNING:
+ fx_severity = HILOG_LOG_WARN;
+ break;
+ case LOG_ERROR:
+ fx_severity = HILOG_LOG_ERROR;
+ break;
+ case LOG_FATAL:
+ fx_severity = HILOG_LOG_FATAL;
+ break;
+ default:
+ fx_severity = HILOG_LOG_INFO;
+ //fx_severity = HILOG_LOG_DEBUG;
+ }//end switch
+ HILOG_LOG(fx_severity,"Thread:%{public}lu %{public}s",pthread_self(),stream_.str().c_str() );
+
+ std::cerr << stream_.str();
+ std::cerr.flush();
#else
std::cerr << stream_.str();
std::cerr.flush();
@@ -141,7 +191,11 @@ bool ShouldCreateLogMessage(LogSeverity severity) {
}
void KillProcess() {
- abort();
+#ifdef FML_OS_OHOS
+ HILOG_ERROR("FML KILL PROCESS");
+#else
+ abort();
+#endif
}
} // namespace fml
diff --git a/fml/logging.h b/fml/logging.h
index 0b732ee818a0aefef7bc988d8adab86e9805e422..cd07846805dc1ab889320adcfafc785c06f64930 100644
--- a/fml/logging.h
+++ b/fml/logging.h
@@ -43,7 +43,8 @@ int GetVlogVerbosity();
// LOG_FATAL and above is always true.
bool ShouldCreateLogMessage(LogSeverity severity);
-[[noreturn]] void KillProcess();
+//[[noreturn]] void KillProcess();
+ void KillProcess();
} // namespace fml
diff --git a/fml/message_loop.cc b/fml/message_loop.cc
index c1043e664ae0a5b7c2cc33bda9907875edb77571..615165b2f919538081b6fc9ddc08aa857d56635d 100644
--- a/fml/message_loop.cc
+++ b/fml/message_loop.cc
@@ -29,15 +29,23 @@ void MessageLoop::EnsureInitializedForCurrentThread() {
// Already initialized.
return;
}
- tls_message_loop.reset(new MessageLoop());
+ tls_message_loop.reset(new MessageLoop(nullptr));
+}
+
+void MessageLoop::EnsureInitializedForCurrentThread(void* platform_loop) {
+ if (tls_message_loop.get() != nullptr) {
+ // Already initialized.
+ return;
+ }
+ tls_message_loop.reset(new MessageLoop(platform_loop));
}
bool MessageLoop::IsInitializedForCurrentThread() {
return tls_message_loop.get() != nullptr;
}
-MessageLoop::MessageLoop()
- : loop_(MessageLoopImpl::Create()),
+MessageLoop::MessageLoop(void* platform_loop)
+ : loop_(MessageLoopImpl::Create(platform_loop)),
task_runner_(fml::MakeRefCounted(loop_)) {
FML_CHECK(loop_);
FML_CHECK(task_runner_);
diff --git a/fml/message_loop.h b/fml/message_loop.h
index ccc1f70b93b8df4ffe4cb3a382fd9530627e80ae..b33449a4610922c5e1e46ac6cbd54348d6dc6710 100644
--- a/fml/message_loop.h
+++ b/fml/message_loop.h
@@ -46,6 +46,8 @@ class MessageLoop {
static void EnsureInitializedForCurrentThread();
+ static void EnsureInitializedForCurrentThread(void* platform_loop);
+
/// Returns true if \p EnsureInitializedForCurrentThread has been called on
/// this thread already.
static bool IsInitializedForCurrentThread();
@@ -64,7 +66,7 @@ class MessageLoop {
fml::RefPtr loop_;
fml::RefPtr task_runner_;
- MessageLoop();
+ MessageLoop(void* platform_loop);
fml::RefPtr GetLoopImpl() const;
diff --git a/fml/message_loop_impl.cc b/fml/message_loop_impl.cc
index 01f4d58d769f487f6326649b97d7c4b829bfdf21..8562284afbc7393ea9adb0a5c2dcf5b29d756472 100644
--- a/fml/message_loop_impl.cc
+++ b/fml/message_loop_impl.cc
@@ -18,6 +18,8 @@
#include "flutter/fml/platform/android/message_loop_android.h"
#elif OS_FUCHSIA
#include "flutter/fml/platform/fuchsia/message_loop_fuchsia.h"
+#elif FML_OS_OHOS
+#include "flutter/fml/platform/ohos/message_loop_ohos.h"
#elif FML_OS_LINUX
#include "flutter/fml/platform/linux/message_loop_linux.h"
#elif FML_OS_WIN
@@ -26,13 +28,15 @@
namespace fml {
-fml::RefPtr MessageLoopImpl::Create() {
+fml::RefPtr MessageLoopImpl::Create(void* platform_loop) {
#if FML_OS_MACOSX
return fml::MakeRefCounted();
#elif FML_OS_ANDROID
return fml::MakeRefCounted();
#elif OS_FUCHSIA
return fml::MakeRefCounted();
+#elif FML_OS_OHOS
+return fml::MakeRefCounted(platform_loop);
#elif FML_OS_LINUX
return fml::MakeRefCounted();
#elif FML_OS_WIN
diff --git a/fml/message_loop_impl.h b/fml/message_loop_impl.h
index 270cc3c86a9ade6627e79df23dcb91c502e42bbb..865ffb43ebe3e1667e268faeb830ea5ea0d122ca 100644
--- a/fml/message_loop_impl.h
+++ b/fml/message_loop_impl.h
@@ -31,7 +31,7 @@ namespace fml {
class MessageLoopImpl : public Wakeable,
public fml::RefCountedThreadSafe {
public:
- static fml::RefPtr Create();
+ static fml::RefPtr Create(void* platform_loop);
virtual ~MessageLoopImpl();
diff --git a/fml/platform/ohos/message_loop_ohos.cc b/fml/platform/ohos/message_loop_ohos.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9a0f7b52bf4c7918a5e5863ae654df691bbf0fab
--- /dev/null
+++ b/fml/platform/ohos/message_loop_ohos.cc
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flutter/fml/platform/ohos/message_loop_ohos.h"
+
+#include
+#include
+
+#include "flutter/fml/eintr_wrapper.h"
+#include "flutter/fml/logging.h"
+#include "flutter/fml/platform/ohos/timerfd.h"
+
+namespace fml {
+
+static constexpr int kClockType = CLOCK_MONOTONIC;
+
+void MessageLoopOhos::OnPollCallback(uv_poll_t* handle,
+ int status,
+ int events) {
+ if (status < 0) {
+ FML_DLOG(ERROR) << "Poll error:" << uv_strerror(status);
+ return;
+ }
+
+ if (events & UV_READABLE) {
+ reinterpret_cast(handle->data)->OnEventFired();
+ }
+}
+
+MessageLoopOhos::MessageLoopOhos(void* platform_loop)
+ : timer_fd_(::timerfd_create(kClockType, TFD_NONBLOCK | TFD_CLOEXEC)),
+ running_(false) {
+ if (platform_loop != nullptr) {
+ uv_loop_t* loop = reinterpret_cast(platform_loop);
+ uv_poll_init(loop, &poll_handle_, timer_fd_.get());
+ } else {
+ uv_loop_init(&loop_);
+ uv_poll_init(&loop_, &poll_handle_, timer_fd_.get());
+ }
+ poll_handle_.data = this;
+ uv_poll_start(&poll_handle_, UV_READABLE, OnPollCallback);
+ FML_CHECK(timer_fd_.is_valid());
+}
+
+MessageLoopOhos::~MessageLoopOhos() {
+ uv_poll_stop(&poll_handle_);
+ if (uv_loop_alive(&loop_)) {
+ uv_loop_close(&loop_);
+ }
+}
+
+// |fml::MessageLoopImpl|
+void MessageLoopOhos::Run() {
+ running_ = true;
+ uv_run(&loop_, UV_RUN_DEFAULT);
+}
+
+// |fml::MessageLoopImpl|
+void MessageLoopOhos::Terminate() {
+ running_ = false;
+ WakeUp(fml::TimePoint::Now());
+}
+
+// |fml::MessageLoopImpl|
+void MessageLoopOhos::WakeUp(fml::TimePoint time_point) {
+ bool result = TimerRearm(timer_fd_.get(), time_point);
+ (void)result;
+ FML_DCHECK(result);
+}
+
+void MessageLoopOhos::OnEventFired() {
+ if (TimerDrain(timer_fd_.get())) {
+ RunExpiredTasksNow();
+ }
+}
+
+} // namespace fml
diff --git a/fml/platform/ohos/message_loop_ohos.h b/fml/platform/ohos/message_loop_ohos.h
new file mode 100644
index 0000000000000000000000000000000000000000..448a2bf67990d3e7974e4e9e2c10ace7010c7317
--- /dev/null
+++ b/fml/platform/ohos/message_loop_ohos.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLUTTER_FML_PLATFORM_OHOS_MESSAGE_LOOP_OHOS_H_
+#define FLUTTER_FML_PLATFORM_OHOS_MESSAGE_LOOP_OHOS_H_
+
+#include
+
+#include
+#include "flutter/fml/macros.h"
+#include "flutter/fml/message_loop_impl.h"
+#include "flutter/fml/unique_fd.h"
+
+namespace fml {
+
+class MessageLoopOhos : public MessageLoopImpl {
+ private:
+ uv_poll_t poll_handle_;
+ uv_loop_t loop_;
+ fml::UniqueFD timer_fd_;
+ bool running_;
+
+ MessageLoopOhos(void* platform_loop);
+
+ ~MessageLoopOhos() override;
+
+ // |fml::MessageLoopImpl|
+ void Run() override;
+
+ // |fml::MessageLoopImpl|
+ void Terminate() override;
+
+ // |fml::MessageLoopImpl|
+ void WakeUp(fml::TimePoint time_point) override;
+
+ void OnEventFired();
+
+ FML_FRIEND_MAKE_REF_COUNTED(MessageLoopOhos);
+ FML_FRIEND_REF_COUNTED_THREAD_SAFE(MessageLoopOhos);
+ FML_DISALLOW_COPY_AND_ASSIGN(MessageLoopOhos);
+
+ public:
+ static void OnPollCallback(uv_poll_t* handle, int status, int events);
+};
+
+} // namespace fml
+
+#endif // FLUTTER_FML_PLATFORM_OHOS_MESSAGE_LOOP_OHOS_H_
diff --git a/fml/platform/ohos/message_loop_ohos_test.cc b/fml/platform/ohos/message_loop_ohos_test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1aa1db255e040ed052207884bf55782ec751987a
--- /dev/null
+++ b/fml/platform/ohos/message_loop_ohos_test.cc
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flutter/fml/message_loop.h"
+
+#include
+#include
+
+#include "flutter/fml/build_config.h"
+#include "flutter/fml/concurrent_message_loop.h"
+#include "flutter/fml/synchronization/count_down_latch.h"
+#include "flutter/fml/synchronization/waitable_event.h"
+#include "flutter/fml/task_runner.h"
+#include "flutter/fml/time/chrono_timestamp_provider.h"
+#include "gtest/gtest.h"
+
+namespace fml {
+namespace message_loop_test {
+
+#define PLATFORM_SPECIFIC_CAPTURE(...) [__VA_ARGS__]
+
+/**
+ * breif: 注册异步任务
+ *
+ */
+void MessageLoopTestPostTask(void) {
+ bool started = false;
+ bool terminated = false;
+ std::thread thread([&started, &terminated]() {
+ fml::MessageLoop::EnsureInitializedForCurrentThread();
+ auto& loop = fml::MessageLoop::GetCurrent();
+ ASSERT_TRUE(loop.GetTaskRunner());
+ loop.GetTaskRunner()->PostTask([&terminated]() {
+ std::cout << "MessageLoopTestPostTask running ..." << std::endl;
+ fml::MessageLoop::GetCurrent().Terminate();
+ terminated = true;
+ });
+ loop.Run();
+ started = true;
+ });
+ thread.join();
+ ASSERT_TRUE(started);
+ ASSERT_TRUE(terminated);
+}
+
+/**
+ * breif:
+ * 进行观察者测试,注册25个任务后,添加观察者,在回调中增加观察者回调打印
+ *
+ */
+void MessageLoopTestObserverFire(void) {
+ bool started = false;
+ bool terminated = false;
+ std::thread thread([&started, &terminated]() {
+ fml::MessageLoop::EnsureInitializedForCurrentThread();
+ const size_t count = 25;
+ auto& loop = fml::MessageLoop::GetCurrent();
+ size_t task_count = 0;
+ size_t obs_count = 0;
+ auto obs = PLATFORM_SPECIFIC_CAPTURE(&obs_count)() {
+ obs_count++;
+ std::cout << "MessageLoopTestObserverFire obs_count" << obs_count
+ << std::endl;
+ };
+ for (size_t i = 0; i < count; i++) {
+ loop.GetTaskRunner()->PostTask(
+ PLATFORM_SPECIFIC_CAPTURE(&terminated, i, &task_count)() {
+ ASSERT_EQ(task_count, i);
+ task_count++;
+ if (count == i + 1) {
+ fml::MessageLoop::GetCurrent().Terminate();
+ terminated = true;
+ }
+ });
+ }
+ loop.AddTaskObserver(0, obs);
+ loop.Run();
+ ASSERT_EQ(task_count, count);
+ ASSERT_EQ(obs_count, count);
+ started = true;
+ });
+ thread.join();
+ ASSERT_TRUE(started);
+ ASSERT_TRUE(terminated);
+}
+
+} // namespace message_loop_test
+} // namespace fml
\ No newline at end of file
diff --git a/fml/platform/ohos/message_loop_ohos_test.h b/fml/platform/ohos/message_loop_ohos_test.h
new file mode 100644
index 0000000000000000000000000000000000000000..f0e74721e39d4d9bc2b0dd634c175256363b1681
--- /dev/null
+++ b/fml/platform/ohos/message_loop_ohos_test.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLUTTER_FML_PLATFORM_OHOS_LOOP_TEST_H_
+#define FLUTTER_FML_PLATFORM_OHOS_LOOP_TEST_H_
+
+namespace fml {
+namespace message_loop_test {
+
+void MessageLoopTestPostTask(void);
+void MessageLoopTestObserverFire(void);
+
+} // namespace message_loop_test
+} // namespace fml
+
+#endif // FLUTTER_FML_PLATFORM_OHOS_LOOP_TEST_H_
diff --git a/fml/platform/ohos/napi_util.cc b/fml/platform/ohos/napi_util.cc
new file mode 100644
index 0000000000000000000000000000000000000000..87a32b2554dba578e431091e6aa6e6cb13dff9d4
--- /dev/null
+++ b/fml/platform/ohos/napi_util.cc
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flutter/fml/platform/ohos/napi_util.h"
+#include
+#include
+#include
+
+namespace fml {
+namespace napi {
+
+bool NapiIsNull(napi_env env, napi_value value) {
+ return value == nullptr || NapiIsType(env, value, napi_null);
+}
+bool NapiIsNotType(napi_env env, napi_value value, napi_valuetype type) {
+ return !NapiIsType(env, value, type);
+}
+std::string NapiGetLastError(napi_env env, napi_status status) {
+ std::string ret("Napi Error:");
+ ret += status;
+
+ const napi_extended_error_info* error_info;
+ napi_get_last_error_info(env, &error_info);
+ ret += error_info->error_message;
+ return ret;
+}
+bool NapiIsType(napi_env env, napi_value value, napi_valuetype type) {
+ napi_status status;
+ napi_valuetype argType;
+ status = napi_typeof(env, value, &argType);
+ return status == napi_ok && type == argType;
+}
+bool NapiIsAnyType(napi_env env, napi_value value, ...) {
+ napi_status status;
+ napi_valuetype argType;
+ status = napi_typeof(env, value, &argType);
+
+ if (status != napi_ok) {
+ return false;
+ }
+
+ bool matched = false;
+ {
+ va_list types;
+ va_start(types, value);
+ napi_valuetype cur;
+ while (!matched) {
+ cur = va_arg(types, napi_valuetype);
+ matched = (cur == argType);
+ }
+ va_end(types);
+ }
+ return matched;
+}
+void NapiPrintValueTypes(napi_env env, int argc, napi_value* args) {
+ FML_DLOG(INFO) << "argc: " << argc;
+ for (int i = 0; i < argc; i++) {
+ napi_value cur = args[i];
+ FML_DLOG(INFO) << "arg: " << i << ",null?" << (cur == nullptr);
+ if (cur != nullptr) {
+ NapiPrintValueType(env, cur);
+ }
+ }
+}
+
+bool IsArrayBuffer(napi_env env, napi_value value) {
+ napi_status status;
+ bool result;
+
+ // Check if the value is an ArrayBuffer
+ status = napi_is_arraybuffer(env, value, &result);
+ if (status != napi_ok) {
+ FML_DLOG(INFO) << "napi_is_arraybuffer: failed:" << status;
+ return false;
+ }
+
+ // If it's not an ArrayBuffer, check if it's an Array
+ if (!result) {
+ status = napi_is_array(env, value, &result);
+ if (status != napi_ok) {
+ FML_DLOG(INFO) << "napi_is_array: failed:"
+ << NapiGetLastError(env, status);
+ return false;
+ }
+ }
+ return true;
+}
+
+void NapiPrintValueType(napi_env env, napi_value cur) {
+ napi_status status;
+ napi_valuetype argType;
+ int i = 0;
+ status = napi_typeof(env, cur, &argType);
+ if (status != napi_ok) {
+ FML_DLOG(INFO) << "args,gettype: failed:" << status;
+ return;
+ }
+ if (argType == napi_number) {
+ FML_DLOG(INFO) << "args,type: " << argType << " number";
+ } else if (argType == napi_string) {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_string";
+ } else if (argType == napi_boolean) {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_boolean ";
+ } else if (argType == napi_object) {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_object";
+ } else if (argType == napi_function) {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_function";
+ } else if (argType == napi_null) {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_null ";
+ } else if (argType == napi_symbol) {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_symbol";
+ } else if (argType == napi_external) {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_external";
+ } else if (argType == napi_bigint) {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " napi_bigint";
+ } else {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " number";
+ }
+ bool ok = false;
+ napi_is_array(env, cur, &ok);
+ if (ok) {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " is_array ";
+ }
+ //(env,cur,&ok);
+ if (IsArrayBuffer(env, cur)) {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType
+ << " is_arraybuffer ";
+ }
+ napi_is_typedarray(env, cur, &ok);
+ if (ok) {
+ FML_DLOG(INFO) << "args[" << i << "],type: " << argType << " is_typearray";
+ }
+}
+
+int32_t GetString(napi_env env, napi_value arg, std::string& strValue) {
+ napi_status status;
+
+ if (NapiIsType(env, arg, napi_null)) {
+ FML_DLOG(INFO) << "napi_null";
+ strValue = "";
+ return SUCCESS;
+ }
+ if (!NapiIsType(env, arg, napi_string)) {
+ FML_DLOG(ERROR) << "Invalid type:";
+ return ERROR_TYPE;
+ }
+
+ std::vector buff(STRING_MAX_LENGTH);
+ size_t copy_lenth;
+ status = napi_get_value_string_utf8(env, arg, static_cast(buff.data()),
+ STRING_MAX_LENGTH, ©_lenth);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "Error get string:" << status;
+ FML_DLOG(ERROR) << "result size:" << copy_lenth;
+ return status;
+ }
+ strValue.assign(buff.data(), copy_lenth);
+ return SUCCESS;
+}
+
+int32_t GetArrayString(napi_env env,
+ napi_value arg,
+ std::vector& arrayString) {
+ uint32_t arrayLenth;
+ napi_status status = napi_get_array_length(env, arg, &arrayLenth);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "Failed to napi_get_array_length:" << status;
+ return status;
+ }
+ FML_DLOG(INFO) << "GetArrayString length:" << arrayLenth;
+ for (uint32_t i = 0; i < arrayLenth; i++) {
+ napi_value element;
+ napi_get_element(env, arg, i, &element);
+ std::string str;
+ GetString(env, element, str);
+ arrayString.push_back(str);
+ }
+ return SUCCESS;
+}
+int32_t GetArrayBuffer(napi_env env,
+ napi_value arg,
+ void** message,
+ size_t* lenth) {
+ napi_status status;
+ // bool ok = false ;
+ if (NapiIsType(env, arg, napi_null)) {
+ FML_DLOG(ERROR) << "GetArrayBuffer value is null :";
+ return ERROR_NULL;
+ }
+
+ // if( napi_ok != (status = napi_is_arraybuffer(env,arg,& ok )) ){
+ if (!IsArrayBuffer(env, arg)) {
+ // FML_DLOG(ERROR)<<"GetArrayBuffer valueType is Not arraybuffer
+ // status:"<
+#include
+#include
+#include
+#include "flutter/fml/logging.h"
+#include "napi/native_api.h"
+
+namespace fml {
+namespace napi {
+enum {
+ SUCCESS = 0,
+ ERROR_TYPE = -100,
+ ERROR_NULL,
+};
+const int32_t STRING_MAX_LENGTH = 512;
+int32_t GetString(napi_env env, napi_value arg, std::string& strValue);
+int32_t GetArrayString(napi_env env,
+ napi_value arg,
+ std::vector& arrayString);
+int32_t GetArrayBuffer(napi_env env,
+ napi_value arg,
+ void** message,
+ size_t* lenth);
+
+/**
+ * 打印napi_value @args 的类型信息
+ */
+void NapiPrintValueTypes(napi_env env, int argc, napi_value* argv);
+/**
+ * 打印napi_value @cur 的类型信息
+ */
+void NapiPrintValueType(napi_env env, napi_value cur);
+
+/**
+ * 判断napi value 类型
+ */
+bool NapiIsType(napi_env env, napi_value value, napi_valuetype type);
+bool NapiIsNotType(napi_env env, napi_value value, napi_valuetype type);
+/**
+ * 判断napi value类型是否是其中的一种
+ */
+bool NapiIsAnyType(napi_env env, napi_value value, ...);
+/**
+ * 判断值是否为空
+ */
+bool NapiIsNull(napi_env env, napi_value value);
+
+/**
+ * 创建ArrayBuffer
+ */
+napi_value CreateArrayBuffer(napi_env env, void* inputData, size_t dataSize);
+
+/**
+ * 回调JS方法
+ */
+napi_status InvokeJsMethod(napi_env env_,
+ napi_ref ref_napi_obj_,
+ const char* methodName,
+ size_t argc,
+ const napi_value* argv);
+} // namespace napi
+} // namespace fml
+#endif
diff --git a/fml/platform/ohos/paths_ohos.cc b/fml/platform/ohos/paths_ohos.cc
new file mode 100644
index 0000000000000000000000000000000000000000..056bdd3770dc917d8aaf0025fc1b548eccd9d9a2
--- /dev/null
+++ b/fml/platform/ohos/paths_ohos.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flutter/fml/platform/ohos/paths_ohos.h"
+
+#include "flutter/fml/file.h"
+
+namespace fml {
+namespace paths {
+
+std::pair GetExecutablePath() {
+ return {false, ""};
+}
+
+static std::string gCachesPath;
+
+void InitializeOhosCachesPath(std::string caches_path) {
+ gCachesPath = std::move(caches_path);
+}
+
+fml::UniqueFD GetCachesDirectory() {
+ // If the caches path is not initialized, the FD will be invalid and caching
+ // will be disabled throughout the system.
+ return OpenDirectory(gCachesPath.c_str(), false, fml::FilePermission::kRead);
+}
+
+} // namespace paths
+} // namespace fml
diff --git a/fml/platform/ohos/paths_ohos.h b/fml/platform/ohos/paths_ohos.h
new file mode 100644
index 0000000000000000000000000000000000000000..494d1516a128955d749d18317ee627b872d33f02
--- /dev/null
+++ b/fml/platform/ohos/paths_ohos.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLUTTER_FML_PLATFORM_OHOS_PATHS_OHOS_H_
+#define FLUTTER_FML_PLATFORM_OHOS_PATHS_OHOS_H_
+
+#include "flutter/fml/macros.h"
+#include "flutter/fml/paths.h"
+
+namespace fml {
+namespace paths {
+
+void InitializeOhosCachesPath(std::string caches_path);
+
+} // namespace paths
+} // namespace fml
+
+#endif // FLUTTER_FML_PLATFORM_OHOS_PATHS_OHOS_H_
diff --git a/fml/platform/ohos/timerfd.cc b/fml/platform/ohos/timerfd.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c15e4eaa991a1604c1e142ee26d6545ca1b9a9bc
--- /dev/null
+++ b/fml/platform/ohos/timerfd.cc
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flutter/fml/platform/ohos/timerfd.h"
+
+#include
+#include
+#include
+
+#include "flutter/fml/eintr_wrapper.h"
+#include "flutter/fml/logging.h"
+
+#if FML_TIMERFD_AVAILABLE == 0
+
+#include
+#include
+
+int timerfd_create(int clockid, int flags) {
+ return syscall(__NR_timerfd_create, clockid, flags);
+}
+
+int timerfd_settime(int ufc,
+ int flags,
+ const struct itimerspec* utmr,
+ struct itimerspec* otmr) {
+ return syscall(__NR_timerfd_settime, ufc, flags, utmr, otmr);
+}
+
+#endif // FML_TIMERFD_AVAILABLE == 0
+
+namespace fml {
+
+#ifndef NSEC_PER_SEC
+#define NSEC_PER_SEC 1000000000
+#endif
+
+bool TimerRearm(int fd, fml::TimePoint time_point) {
+ uint64_t nano_secs = time_point.ToEpochDelta().ToNanoseconds();
+
+ // "0" will disarm the timer, desired behavior is to immediately
+ // trigger the timer.
+ if (nano_secs < 1) {
+ nano_secs = 1;
+ }
+
+ struct itimerspec spec = {};
+ spec.it_value.tv_sec = static_cast(nano_secs / NSEC_PER_SEC);
+ spec.it_value.tv_nsec = nano_secs % NSEC_PER_SEC;
+ spec.it_interval = spec.it_value; // single expiry.
+
+ int result = ::timerfd_settime(fd, TFD_TIMER_ABSTIME, &spec, nullptr);
+ if (result != 0) {
+ FML_DLOG(ERROR) << "timerfd_settime err:" << strerror(errno);
+ }
+ return result == 0;
+}
+
+bool TimerDrain(int fd) {
+ // 8 bytes must be read from a signaled timer file descriptor when signaled.
+ uint64_t fire_count = 0;
+ ssize_t size = FML_HANDLE_EINTR(::read(fd, &fire_count, sizeof(uint64_t)));
+ if (size != sizeof(uint64_t)) {
+ return false;
+ }
+ return fire_count > 0;
+}
+
+} // namespace fml
diff --git a/fml/platform/ohos/timerfd.h b/fml/platform/ohos/timerfd.h
new file mode 100644
index 0000000000000000000000000000000000000000..b2715d83f63faf46136f2abc506dcf046e5b8467
--- /dev/null
+++ b/fml/platform/ohos/timerfd.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLUTTER_FML_PLATFORM_OHOS_TIMER_FD_H_
+#define FLUTTER_FML_PLATFORM_OHOS_TIMER_FD_H_
+
+#include "flutter/fml/time/time_point.h"
+
+// clang-format off
+#if __has_include() && \
+ (!defined(__ANDROID_API__) || __ANDROID_API__ >= 19)
+ // sys/timerfd.h is always present in Android NDK due to unified headers,
+ // but timerfd functions are only available on API 19 or later.
+// clang-format on
+
+#include
+
+#define FML_TIMERFD_AVAILABLE 1
+
+#else // __has_include()
+
+#define FML_TIMERFD_AVAILABLE 0
+
+#include
+// Must come after sys/types
+#include
+
+#define TFD_TIMER_ABSTIME (1 << 0)
+#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
+
+#define TFD_CLOEXEC O_CLOEXEC
+#define TFD_NONBLOCK O_NONBLOCK
+
+int timerfd_create(int clockid, int flags);
+
+int timerfd_settime(int ufc,
+ int flags,
+ const struct itimerspec* utmr,
+ struct itimerspec* otmr);
+
+#endif // __has_include()
+
+namespace fml {
+
+/// Rearms the timer to expire at the given time point.
+bool TimerRearm(int fd, fml::TimePoint time_point);
+
+/// Drains the timer FD and returns true if it has expired. This may be false in
+/// case the timer read is non-blocking and this routine was called before the
+/// timer expiry.
+bool TimerDrain(int fd);
+
+} // namespace fml
+
+#endif // FLUTTER_FML_PLATFORM_OHOS_TIMER_FD_H_
diff --git a/fml/thread.cc b/fml/thread.cc
index a905fd071eaa9a86935e7c854c4bf035d5a30a46..e74e8ab5b41f88bb2f1d2658f6bcc60e0698ac33 100644
--- a/fml/thread.cc
+++ b/fml/thread.cc
@@ -13,6 +13,7 @@
#include "flutter/fml/build_config.h"
#include "flutter/fml/message_loop.h"
#include "flutter/fml/synchronization/waitable_event.h"
+#include "flutter/fml/logging.h"
#if defined(FML_OS_WIN)
#include
@@ -42,8 +43,9 @@ void SetThreadName(const std::string& name) {
}
#if defined(FML_OS_MACOSX)
pthread_setname_np(name.c_str());
-#elif defined(FML_OS_LINUX) || defined(FML_OS_ANDROID)
+#elif defined(FML_OS_LINUX) || defined(FML_OS_ANDROID) || defined(FML_OS_OHOS)
pthread_setname_np(pthread_self(), name.c_str());
+ FML_DLOG(INFO) << "set the thread name to '" << name;
#elif defined(FML_OS_WIN)
THREADNAME_INFO info;
info.dwType = 0x1000;
diff --git a/fml/thread_local.h b/fml/thread_local.h
index 010c0ff643dd33a7516bee5c52c55cb3d8894f39..a5f3ba08e2d31ca357ee76e21979bca092cdc723 100644
--- a/fml/thread_local.h
+++ b/fml/thread_local.h
@@ -11,7 +11,7 @@
#include "flutter/fml/macros.h"
#define FML_THREAD_LOCAL_PTHREADS \
- FML_OS_MACOSX || FML_OS_LINUX || FML_OS_ANDROID
+ FML_OS_MACOSX || FML_OS_LINUX || FML_OS_ANDROID || FML_OS_OHOS
#if FML_THREAD_LOCAL_PTHREADS
#include
diff --git a/fml/thread_unittests.cc b/fml/thread_unittests.cc
index 65479762823fc1d325b75849bcd58db827005311..095fc2dad42537ef5798495dbb4235a98081f1e6 100644
--- a/fml/thread_unittests.cc
+++ b/fml/thread_unittests.cc
@@ -4,7 +4,7 @@
#include "flutter/fml/thread.h"
-#if defined(FML_OS_MACOSX) || defined(FML_OS_LINUX) || defined(FML_OS_ANDROID)
+#if defined(FML_OS_MACOSX) || defined(FML_OS_LINUX) || defined(FML_OS_ANDROID) || defined(FML_OS_OHOS)
#define FLUTTER_PTHREAD_SUPPORTED 1
#else
#define FLUTTER_PTHREAD_SUPPORTED 0
diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc
index 687d19f4012b576059e9b41a8c36ece4fee61a45..3215629734e60a3726d56fe2e0de3e04aa5d6516 100644
--- a/impeller/entity/contents/filters/blend_filter_contents.cc
+++ b/impeller/entity/contents/filters/blend_filter_contents.cc
@@ -341,6 +341,8 @@ std::optional BlendFilterContents::RenderFilter(
foreground_color_, GetAbsorbOpacity());
}
FML_UNREACHABLE();
+ std::optional ret;
+ return ret;
}
} // namespace impeller
diff --git a/impeller/entity/contents/filters/inputs/filter_input.cc b/impeller/entity/contents/filters/inputs/filter_input.cc
index 4f61ba49fa9d5d4edb3e2b1a32227e06e1f762d5..b19ac60bbb4c6c2feabf3112b17679e4f1f8ca12 100644
--- a/impeller/entity/contents/filters/inputs/filter_input.cc
+++ b/impeller/entity/contents/filters/inputs/filter_input.cc
@@ -33,6 +33,7 @@ FilterInput::Ref FilterInput::Make(Variant input) {
}
FML_UNREACHABLE();
+ return std::shared_ptr();
}
FilterInput::Ref FilterInput::Make(std::shared_ptr texture,
diff --git a/impeller/entity/entity_pass_delegate.cc b/impeller/entity/entity_pass_delegate.cc
index 529c8698f68bd31f3126dda56e72823a0aef9aa5..8455f1adf0f25f5f324bd03bb171c2f8a81103a2 100644
--- a/impeller/entity/entity_pass_delegate.cc
+++ b/impeller/entity/entity_pass_delegate.cc
@@ -31,7 +31,9 @@ class DefaultEntityPassDelegate final : public EntityPassDelegate {
std::shared_ptr target,
const Matrix& effect_transform) override {
// Not possible since this pass always collapses into its parent.
+ std::shared_ptr ret;
FML_UNREACHABLE();
+ return ret;
}
private:
diff --git a/impeller/toolkit/egl/display.h b/impeller/toolkit/egl/display.h
index 07f5d251291894e01980f035edf6b7b40ded9f63..420d143697b0157fd36f7b47c798ebb83d94e51a 100644
--- a/impeller/toolkit/egl/display.h
+++ b/impeller/toolkit/egl/display.h
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
+#ifndef EGL_DISPLAY_H
+#define EGL_DISPLAY_H
#include
#include
@@ -45,3 +46,5 @@ class Display {
} // namespace egl
} // namespace impeller
+
+#endif
diff --git a/impeller/tools/impeller.gni b/impeller/tools/impeller.gni
index e6e71edfbeae63aed315fe5266701a90c5bd3af8..2badbbff65bb32ef21d102be5582d5efaef9e653 100644
--- a/impeller/tools/impeller.gni
+++ b/impeller/tools/impeller.gni
@@ -14,10 +14,11 @@ declare_args() {
impeller_enable_metal = is_mac || is_ios
# Whether the OpenGLES backend is enabled.
- impeller_enable_opengles = is_mac || is_linux || is_win || is_android
+ impeller_enable_opengles = is_mac || is_linux || is_win || is_android ||is_ohos
# Whether the Vulkan backend is enabled.
- impeller_enable_vulkan = is_linux || is_android
+ #impeller_enable_vulkan = is_mac || is_linux || is_win || is_android
+ impeller_enable_vulkan = is_mac || is_win || is_android
# Whether to use a prebuilt impellerc.
# If this is the empty string, impellerc will be built.
diff --git a/lib/ui/painting/canvas.cc b/lib/ui/painting/canvas.cc
index 733b8a2903e7132197f6365c36528465ca44664a..9cd15cd4ead378eea37465e7bf7e8fa83b62b9af 100644
--- a/lib/ui/painting/canvas.cc
+++ b/lib/ui/painting/canvas.cc
@@ -25,6 +25,8 @@
#include "third_party/tonic/dart_binding_macros.h"
#include "third_party/tonic/dart_library_natives.h"
+#include "flutter/fml/logging.h"
+
using tonic::ToDart;
namespace flutter {
@@ -249,7 +251,7 @@ void Canvas::drawLine(double x1,
void Canvas::drawPaint(Dart_Handle paint_objects, Dart_Handle paint_data) {
Paint paint(paint_objects, paint_data);
-
+ FML_DLOG(INFO)<<"drawPaint:" <<(int64_t)paint_objects ;
FML_DCHECK(paint.isNotNull());
if (display_list_recorder_) {
paint.sync_to(builder(), kDrawPaintFlags);
diff --git a/lib/ui/painting/paint.cc b/lib/ui/painting/paint.cc
index 2849526ca00a4c639a8e0b2fdb720c3c06365531..e7daf2a3375e035e255992090c67eec5ff3fcc13 100644
--- a/lib/ui/painting/paint.cc
+++ b/lib/ui/painting/paint.cc
@@ -74,7 +74,7 @@ const SkPaint* Paint::paint(SkPaint& paint) const {
return nullptr;
}
FML_DCHECK(paint == SkPaint());
-
+ FML_DLOG(INFO) << " Paint::paint " ;
tonic::DartByteData byte_data(paint_data_);
FML_CHECK(byte_data.length_in_bytes() == kDataByteCount);
@@ -336,6 +336,7 @@ void Paint::toDlPaint(DlPaint& paint) const {
return;
}
FML_DCHECK(paint == DlPaint());
+ FML_DLOG(INFO) << " Paint::toDlPaint" ;
tonic::DartByteData byte_data(paint_data_);
FML_CHECK(byte_data.length_in_bytes() == kDataByteCount);
diff --git a/lib/ui/platform_dispatcher.dart b/lib/ui/platform_dispatcher.dart
index 20349ded2fe43785f7d1ac1d3c936cc1fc5d7867..03bcc662c3026f0b81593e0a06075d7c4913f66a 100644
--- a/lib/ui/platform_dispatcher.dart
+++ b/lib/ui/platform_dispatcher.dart
@@ -335,6 +335,7 @@ class PlatformDispatcher {
// Called from the engine, via hooks.dart
void _drawFrame() {
+ print("platform_dispatcher::drawFrame..${_onDrawFrame}") ;
_invoke(onDrawFrame, _onDrawFrameZone);
}
diff --git a/lib/ui/window/platform_configuration.cc b/lib/ui/window/platform_configuration.cc
index d3d56c13f1029d0ceb59ff07d98a020d1f954df6..d4333231d468b28e8cf140f89519dc287940ed4f 100644
--- a/lib/ui/window/platform_configuration.cc
+++ b/lib/ui/window/platform_configuration.cc
@@ -143,6 +143,10 @@ void PlatformConfiguration::DispatchPlatformMessage(
std::unique_ptr message) {
std::shared_ptr dart_state =
dispatch_platform_message_.dart_state().lock();
+
+ FML_DLOG(INFO)
+ << "DispatchPlatformMessage channel: "
+ << message->channel();
if (!dart_state) {
FML_DLOG(WARNING)
<< "Dropping platform message for lack of DartState on channel: "
@@ -176,6 +180,9 @@ void PlatformConfiguration::DispatchSemanticsAction(int32_t id,
fml::MallocMapping args) {
std::shared_ptr dart_state =
dispatch_semantics_action_.dart_state().lock();
+ FML_DLOG(INFO)
+ << "DispatchSemanticsAction : "
+ << id ;
if (!dart_state) {
return;
}
@@ -350,6 +357,7 @@ Dart_Handle PlatformConfigurationNativeApi::SendPortPlatformMessage(
void PlatformConfigurationNativeApi::RespondToPlatformMessage(
int response_id,
const tonic::DartByteData& data) {
+ FML_DLOG(INFO)<<"PlatformConfigurationNativeApi::RespondToPlatformMessage:" << response_id;
if (Dart_IsNull(data.dart_handle())) {
UIDartState::Current()
->platform_configuration()
diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc
index 0f819ef9981c11e5d9515702f184eed4d4245e19..56c6ed15bbbf1721fe805ac08c5db68a858b9ffc 100644
--- a/runtime/dart_isolate.cc
+++ b/runtime/dart_isolate.cc
@@ -805,8 +805,10 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
settings.observatory_host, // server IP address
settings.observatory_port, // server observatory port
tonic::DartState::HandleLibraryTag, // embedder library tag handler
- false, // disable websocket origin check
- settings.disable_service_auth_codes, // disable VM service auth codes
+ true,
+ //false, // disable websocket origin check
+ true, // disable VM service auth codes
+ //settings.disable_service_auth_codes, // disable VM service auth codes
settings.enable_service_port_fallback, // enable fallback to port 0
// when bind fails.
error // error (out)
diff --git a/runtime/dart_service_isolate.cc b/runtime/dart_service_isolate.cc
index 18b51a32a6f1a33fa538a14bd39c74b7aa80ea71..17fa47d1baa3f67e1e7d6569890cc217b248f7ba 100644
--- a/runtime/dart_service_isolate.cc
+++ b/runtime/dart_service_isolate.cc
@@ -180,11 +180,13 @@ bool DartServiceIsolate::Startup(const std::string& server_ip,
SHUTDOWN_ON_ERROR(result);
result =
Dart_SetField(library, Dart_NewStringFromCString("_originCheckDisabled"),
- Dart_NewBoolean(disable_origin_check));
+ Dart_NewBoolean(true));
+ //Dart_NewBoolean(disable_origin_check));
SHUTDOWN_ON_ERROR(result);
result =
Dart_SetField(library, Dart_NewStringFromCString("_authCodesDisabled"),
- Dart_NewBoolean(disable_service_auth_codes));
+ Dart_NewBoolean(true));
+ //Dart_NewBoolean(disable_service_auth_codes));
SHUTDOWN_ON_ERROR(result);
result = Dart_SetField(
library, Dart_NewStringFromCString("_enableServicePortFallback"),
diff --git a/runtime/dart_snapshot.cc b/runtime/dart_snapshot.cc
index 5943524aa9f8066ae8738b028f1c42c595bb6200..cb92670b8997b59ec6ab77cd2bda3413e07ed5cb 100644
--- a/runtime/dart_snapshot.cc
+++ b/runtime/dart_snapshot.cc
@@ -9,6 +9,7 @@
#include "flutter/fml/native_library.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/trace_event.h"
+#include "flutter/fml/logging.h"
#include "flutter/lib/snapshot/snapshot.h"
#include "flutter/runtime/dart_vm.h"
#include "third_party/dart/runtime/include/dart_api.h"
@@ -56,6 +57,7 @@ static std::shared_ptr SearchMapping(
const std::vector& native_library_path,
const char* native_library_symbol_name,
bool is_executable) {
+ FML_LOG(INFO)<<"SearchMapping file:"< SearchMapping(
static std::shared_ptr ResolveVMData(
const Settings& settings) {
#if DART_SNAPSHOT_STATIC_LINK
+ FML_LOG(ERROR)<<"ResolveVMData: NonOwnedMapping" ;
return std::make_unique(kDartVmSnapshotData,
0, // size
nullptr, // release_func
diff --git a/shell/common/animator.cc b/shell/common/animator.cc
index b396b0a4e2da08093ff3ccf74a716a0808d7da3d..07963bf190de9d0a801faa7c366eb447ba75c693 100644
--- a/shell/common/animator.cc
+++ b/shell/common/animator.cc
@@ -8,6 +8,7 @@
#include "flutter/fml/time/time_point.h"
#include "flutter/fml/trace_event.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"
+#include "flutter/fml/logging.h"
namespace flutter {
@@ -111,6 +112,7 @@ void Animator::BeginFrame(
// time to start doing GC work.
task_runners_.GetUITaskRunner()->PostDelayedTask(
[self = weak_factory_.GetWeakPtr()]() {
+
if (!self) {
return;
}
diff --git a/shell/common/engine.cc b/shell/common/engine.cc
index 7d2a63d57cad2ae43ab0295cc2cdbdd71fdae77f..bbdf61cac7194f7b779497f4e7d85ee76d0a8b14 100644
--- a/shell/common/engine.cc
+++ b/shell/common/engine.cc
@@ -443,15 +443,24 @@ void Engine::ScheduleFrame(bool regenerate_layer_tree) {
void Engine::Render(std::shared_ptr layer_tree) {
if (!layer_tree) {
+ FML_DLOG(ERROR) << "Render layer_tree IS NULL";
return;
}
+ if (layer_tree->frame_size().isEmpty()){
+ FML_DLOG(INFO) << "engin Render frame_size is empty";
+ }
+
+ if (layer_tree->device_pixel_ratio() <= 0.0f){
+ FML_DLOG(INFO) << "engin Render device_pixel_ratio <= 0";
+ }
+
// Ensure frame dimensions are sane.
if (layer_tree->frame_size().isEmpty() ||
layer_tree->device_pixel_ratio() <= 0.0f) {
+ FML_DLOG(INFO) << "engin layer_tree isEmpty";
return;
}
-
animator_->Render(std::move(layer_tree));
}
diff --git a/shell/common/platform_view.cc b/shell/common/platform_view.cc
index ce2b22009f8211cc230da3f49b42eb7324e9428f..03523f5682a26398b99ca4c660939274a96d57dc 100644
--- a/shell/common/platform_view.cc
+++ b/shell/common/platform_view.cc
@@ -14,7 +14,9 @@
namespace flutter {
PlatformView::PlatformView(Delegate& delegate, const TaskRunners& task_runners)
- : delegate_(delegate), task_runners_(task_runners), weak_factory_(this) {}
+ : delegate_(delegate), task_runners_(task_runners), weak_factory_(this) {
+ FML_LOG(INFO)<<"PlatformView";
+ }
PlatformView::~PlatformView() = default;
diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc
index 479988440a6cc91b5b87c92b25958f7dff7ec320..78a42915e1244d08a09060700aa505bfe6a6e9c9 100644
--- a/shell/common/rasterizer.cc
+++ b/shell/common/rasterizer.cc
@@ -22,6 +22,8 @@
#include "third_party/skia/include/core/SkSurfaceCharacterization.h"
#include "third_party/skia/include/utils/SkBase64.h"
+#include "flutter/fml/logging.h"
+
namespace flutter {
// The rasterizer will tell Skia to purge cached resources that have not been
@@ -158,6 +160,7 @@ flutter::LayerTree* Rasterizer::GetLastLayerTree() {
void Rasterizer::DrawLastLayerTree(
std::unique_ptr frame_timings_recorder) {
if (!last_layer_tree_ || !surface_) {
+ FML_DLOG(ERROR)<<"DrawLastLayerTree last_layer_tree_ or surface_ is nullptr " ;
return;
}
RasterStatus raster_status =
@@ -490,7 +493,7 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe(
FrameTimingsRecorder& frame_timings_recorder,
flutter::LayerTree& layer_tree) {
FML_DCHECK(surface_);
-
+
compositor_context_->ui_time().SetLapTime(
frame_timings_recorder.GetBuildDuration());
@@ -603,8 +606,11 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe(
}
compositor_context_->raster_cache().EndFrame();
+
frame_timings_recorder.RecordRasterEnd(
&compositor_context_->raster_cache());
+
+
FireNextFrameCallbackIfPresent();
if (surface_->GetContext()) {
diff --git a/shell/common/shell.cc b/shell/common/shell.cc
index 693d36a14336690323ee8b2cfa87cf77f2b249c2..b0bf51ae5d5cc87e53aeb2f9544b01fc6a8e5bd0 100644
--- a/shell/common/shell.cc
+++ b/shell/common/shell.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include
#define RAPIDJSON_HAS_STDSTRING 1
#include "flutter/shell/common/shell.h"
@@ -76,13 +77,12 @@ std::unique_ptr CreateEngine(
// that cause shell initialization failures will still lead to some of their
// settings being applied.
void PerformInitializationTasks(Settings& settings) {
- {
+/* {
fml::LogSettings log_settings;
log_settings.min_log_level =
settings.verbose_logging ? fml::LOG_INFO : fml::LOG_ERROR;
fml::SetLogSettings(log_settings);
- }
-
+ } */
static std::once_flag gShellSettingsInitialization = {};
std::call_once(gShellSettingsInitialization, [&settings] {
tonic::SetLogHandler(
@@ -98,8 +98,6 @@ void PerformInitializationTasks(Settings& settings) {
if (!settings.skia_deterministic_rendering_on_cpu) {
SkGraphics::Init();
- } else {
- FML_DLOG(INFO) << "Skia deterministic rendering is enabled.";
}
if (settings.icu_initialization_required) {
@@ -112,7 +110,6 @@ void PerformInitializationTasks(Settings& settings) {
}
}
});
-
PersistentCache::SetCacheSkSL(settings.cache_sksl);
}
@@ -301,6 +298,7 @@ std::unique_ptr Shell::CreateShellOnPlatformThread(
shell->volatile_path_tracker_));
}));
+
if (!shell->Setup(std::move(platform_view), //
engine_future.get(), //
rasterizer_future.get(), //
@@ -336,7 +334,6 @@ std::unique_ptr Shell::CreateWithSnapshot(
if (!task_runners.IsValid() || !callbacks_valid) {
return nullptr;
}
-
fml::AutoResetWaitableEvent latch;
std::unique_ptr shell;
auto platform_task_runner = task_runners.GetPlatformTaskRunner();
@@ -521,6 +518,7 @@ std::unique_ptr Shell::Spawn(
fml::SyncSwitch::Handlers()
.SetIfFalse([&is_gpu_disabled] { is_gpu_disabled = false; })
.SetIfTrue([&is_gpu_disabled] { is_gpu_disabled = true; }));
+
std::unique_ptr result = CreateWithSnapshot(
PlatformData{}, task_runners_, rasterizer_->GetRasterThreadMerger(),
io_manager_, resource_cache_limit_calculator_, GetSettings(), vm_,
@@ -536,6 +534,7 @@ std::unique_ptr Shell::Spawn(
const fml::RefPtr& unref_queue,
fml::TaskRunnerAffineWeakPtr snapshot_delegate,
const std::shared_ptr& volatile_path_tracker) {
+
return engine->Spawn(
/*delegate=*/delegate,
/*dispatcher_maker=*/dispatcher_maker,
@@ -585,7 +584,9 @@ void Shell::RunEngine(
return;
}
platform_runner->PostTask(
- [result_callback, run_result]() { result_callback(run_result); });
+ [result_callback, run_result]() {
+ result_callback(run_result);
+ });
};
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
@@ -746,7 +747,6 @@ DartVM* Shell::GetDartVM() {
// |PlatformView::Delegate|
void Shell::OnPlatformViewCreated(std::unique_ptr surface) {
- TRACE_EVENT0("flutter", "Shell::OnPlatformViewCreated");
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
diff --git a/shell/common/snapshot_controller_impeller.cc b/shell/common/snapshot_controller_impeller.cc
index 5e7317805812d11e90ad57bc0c7d060f4df28cf7..b115b06c0f03e1ac34a4f5158e9c131d81f20dcc 100644
--- a/shell/common/snapshot_controller_impeller.cc
+++ b/shell/common/snapshot_controller_impeller.cc
@@ -75,6 +75,8 @@ sk_sp SnapshotControllerImpeller::DoMakeRasterSnapshot(
sk_sp SnapshotControllerImpeller::ConvertToRasterImage(
sk_sp image) {
FML_UNREACHABLE();
+ sk_sp result;
+ return result;
}
} // namespace flutter
diff --git a/shell/common/switches.cc b/shell/common/switches.cc
index 1d518824aa8199f4e67b8cc6b95efff7cde1b066..0cb341d0d6577ba05ee0141752b83d0fa688d9af 100644
--- a/shell/common/switches.cc
+++ b/shell/common/switches.cc
@@ -76,7 +76,7 @@ static const std::string kAllowedDartFlags[] = {
// Define symbols for the ICU data that is linked into the Flutter library on
// Android. This is a workaround for crashes seen when doing dynamic lookups
// of the engine's own symbols on some older versions of Android.
-#if FML_OS_ANDROID
+#if FML_OS_ANDROID
extern uint8_t _binary_icudtl_dat_start[];
extern uint8_t _binary_icudtl_dat_end[];
@@ -406,7 +406,7 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) {
command_line.GetOptionValue(FlagForSwitch(Switch::ICUNativeLibPath),
&native_lib_path);
-#if FML_OS_ANDROID
+#if FML_OS_ANDROID
settings.icu_mapper = GetICUStaticMapping;
#else
settings.icu_mapper = [icu_symbol_prefix, native_lib_path] {
diff --git a/shell/common/vsync_waiter.h b/shell/common/vsync_waiter.h
index df70342c399e49af8bdd7454a9f05750524232fa..cfce4524df4d7a59c90ff8a1fb3ce459b61ca9c9 100644
--- a/shell/common/vsync_waiter.h
+++ b/shell/common/vsync_waiter.h
@@ -37,6 +37,7 @@ class VsyncWaiter : public std::enable_shared_from_this {
// method.
friend class VsyncWaiterAndroid;
friend class VsyncWaiterEmbedder;
+ friend class VsyncWaiterOHOS;
const TaskRunners task_runners_;
diff --git a/shell/gpu/gpu_surface_software.cc b/shell/gpu/gpu_surface_software.cc
index 862cb7d3e96946ff6af8c7f29ea28ad9e231c73e..78b28e0545ffa74f62cb7b5bb1077f6fb86869dd 100644
--- a/shell/gpu/gpu_surface_software.cc
+++ b/shell/gpu/gpu_surface_software.cc
@@ -28,6 +28,7 @@ std::unique_ptr GPUSurfaceSoftware::AcquireFrame(
SurfaceFrame::FramebufferInfo framebuffer_info;
framebuffer_info.supports_readback = true;
+ FML_DLOG(INFO) <<"AcquireFrame" ;
// TODO(38466): Refactor GPU surface APIs take into account the fact that an
// external view embedder may want to render to the root surface.
if (!render_to_surface_) {
@@ -47,11 +48,14 @@ std::unique_ptr GPUSurfaceSoftware::AcquireFrame(
sk_sp backing_store = delegate_->AcquireBackingStore(size);
+FML_DLOG(INFO) << "AcquireFrame";
if (backing_store == nullptr) {
+ FML_DLOG(INFO) <<"AcquireFrame ... backing_store is null" ;
return nullptr;
}
if (size != SkISize::Make(backing_store->width(), backing_store->height())) {
+ FML_DLOG(INFO) <<"AcquireFrame ... backing_store size not matched" ;
return nullptr;
}
@@ -61,19 +65,26 @@ std::unique_ptr GPUSurfaceSoftware::AcquireFrame(
SkCanvas* canvas = backing_store->getCanvas();
canvas->resetMatrix();
+FML_DLOG(INFO) << "resetMatrix end";
SurfaceFrame::SubmitCallback on_submit =
[self = weak_factory_.GetWeakPtr()](const SurfaceFrame& surface_frame,
SkCanvas* canvas) -> bool {
+ FML_DLOG(INFO) << "on_submit start";
// If the surface itself went away, there is nothing more to do.
+ FML_DLOG(INFO) <<"AcquireFrame ... on_submit ..." ;
if (!self || !self->IsValid() || canvas == nullptr) {
+ FML_DLOG(INFO) << "on_submit return false";
return false;
}
+ FML_DLOG(INFO) <<"AcquireFrame ... on_submit canvas->flush " ;
canvas->flush();
+ FML_DLOG(INFO) <<"AcquireFrame ... delegate_-->PresentBackingStore" ;
return self->delegate_->PresentBackingStore(surface_frame.SkiaSurface());
};
+FML_DLOG(INFO) << "return SurfaceFrame";
return std::make_unique(backing_store, framebuffer_info,
on_submit, logical_size);
}
diff --git a/shell/platform/BUILD.gn b/shell/platform/BUILD.gn
index 66baf0e887fe1d71a73ecd7d6c765062607ad9d4..8af1e768590fd9303dcc0cbc83ac7c0bfc1fb619 100644
--- a/shell/platform/BUILD.gn
+++ b/shell/platform/BUILD.gn
@@ -10,6 +10,8 @@ group("platform") {
deps = [ "darwin" ]
} else if (is_android) {
deps = [ "android" ]
+ }else if ( is_ohos){
+ deps = [ "ohos" ]
} else if (is_linux) {
deps = []
if (enable_desktop_embeddings) {
diff --git a/shell/platform/embedder/BUILD.gn b/shell/platform/embedder/BUILD.gn
index 83d62c610d1cb872ba32e5d3c49463b15a1cb616..56335f45afd715add78c6f571d03c3d1239f4886 100644
--- a/shell/platform/embedder/BUILD.gn
+++ b/shell/platform/embedder/BUILD.gn
@@ -115,6 +115,9 @@ template("embedder_source_set") {
"//third_party/dart/runtime/bin:elf_loader",
"//third_party/skia",
]
+ if( is_ohos ){
+ #libs +=["hilog_ndk.z"]
+ }
if (embedder_enable_metal) {
sources += [
@@ -381,7 +384,7 @@ shared_library("flutter_engine_library") {
if (is_mac && !embedder_for_target) {
ldflags += [ "-Wl,-install_name,@rpath/FlutterEmbedder.framework/$_framework_binary_subpath" ]
}
- if (is_linux) {
+ if (is_ohos || is_linux) {
ldflags += [ "-Wl,--version-script=" + rebase_path("embedder_exports.lst") ]
}
diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc
index 6240bc9efcf808a3c0dce551c2957c85d4a3dc1f..2161b4a8b8ae3e2297dd5f42162f3d98f2a87fd3 100644
--- a/shell/platform/embedder/embedder.cc
+++ b/shell/platform/embedder/embedder.cc
@@ -68,6 +68,24 @@ extern const intptr_t kPlatformStrongDillSize;
#include "flutter/shell/platform/embedder/embedder_surface_metal.h"
#endif
+#ifdef FML_OS_OHOS
+extern "C"{
+ typedef enum {
+ /** Debug level to be used by {@link OH_LOG_DEBUG} */
+ HILOG_LOG_DEBUG = 3,
+ /** Informational level to be used by {@link OH_LOG_INFO} */
+ HILOG_LOG_INFO = 4,
+ /** Warning level to be used by {@link OH_LOG_WARN} */
+ HILOG_LOG_WARN = 5,
+ /** Error level to be used by {@link OH_LOG_ERROR} */
+ HILOG_LOG_ERROR = 6,
+ /** Fatal level to be used by {@link OH_LOG_FATAL} */
+ HILOG_LOG_FATAL = 7,
+} HiLog_LogLevel;
+int OH_LOG_Print(int type, HiLog_LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) ;
+}
+#endif
+
const int32_t kFlutterSemanticsNodeIdBatchEnd = -1;
const int32_t kFlutterSemanticsCustomActionIdBatchEnd = -1;
@@ -111,6 +129,15 @@ static FlutterEngineResult LogEmbedderError(FlutterEngineResult code,
"%s (%d): '%s' returned '%s'. %s", file_base, line, function,
code_name, reason);
std::cerr << error << std::endl;
+
+
+#if defined(FML_OS_OHOS)
+#define OHOS_LOG_TYPE_APP 0
+#define HILOG_LOG_DOMAIN 0
+#define HILOG_LOG_TAG "XcomFlutterEmbedder"
+ HiLog_LogLevel fx_severity = HILOG_LOG_ERROR;
+ (void ) OH_LOG_Print(0,fx_severity,HILOG_LOG_DOMAIN, HILOG_LOG_TAG,"%s",error );
+#endif
return code;
}
diff --git a/shell/platform/ohos/BUILD.gn b/shell/platform/ohos/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..8c65f55f4ab5927416d7ea07d0edc2cf003e423b
--- /dev/null
+++ b/shell/platform/ohos/BUILD.gn
@@ -0,0 +1,266 @@
+# Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+assert(is_ohos)
+
+import("//flutter/build/zip_bundle.gni")
+import("//flutter/shell/platform/glfw/config.gni")
+import("//flutter/testing/testing.gni")
+import("//build/config/ohos/pkg_config.gni")
+import("//flutter/shell/gpu/gpu.gni")
+
+group("ohos") {
+ deps = [
+ ":flutter",
+ #":publish_headers_ohos",
+ ]
+}
+shell_gpu_configuration("ohos_gpu_configuration") {
+ enable_software = true
+ enable_gl = true
+ enable_vulkan = false
+ enable_metal = false
+}
+# Temporary workaround for the issue describe in
+# https://github.com/flutter/flutter/issues/14509 and
+# https://github.com/flutter/flutter/issues/14438
+# Remove once the build infrastructure moves to Ubuntu 18.04 or newer, where
+# the underlying issue is fixed.
+config("disable_fatal_link_warnings") {
+ visibility = [ ":*" ]
+ ldflags = [ "-Wl,--no-fatal-warnings" ]
+}
+
+_public_headers = [
+ #"public/flutter_ohos/fl_view.h",
+ # "napi_common.h",
+ #"platform_view_ohos.h",
+]
+
+config("relative_flutter_ohos_headers") {
+ include_dirs = [ "public",
+
+ ]
+}
+
+source_set("flutter_ohos_sources") {
+ public = _public_headers + [
+ "napi_common.h",
+ "ohos_xcomponent_adapter.h",
+ "./napi/platform_view_ohos_napi.h",
+ "ohos_shell_holder.h",
+ "platform_view_ohos.h",
+ "platform_message_response_ohos.h",
+ "platform_message_handler_ohos.h",
+ "vsync_waiter_ohos.h",
+ "ohos_logger.h" ,
+ "ohos_display.h",
+ "ohos_surface_software.h",
+ "./context/ohos_context.h",
+ "./surface/ohos_native_window.h",
+ "./surface/ohos_surface.h",
+ "ohos_touch_processor.h",
+ "ohos_context_gl_skia.h",
+ "ohos_egl_surface.h",
+ "ohos_environment_gl.h",
+ "ohos_surface_gl_skia.h",
+ ]
+
+ #configs += [ "//flutter/shell/platform/ohos/config:gtk" ]
+
+ sources = [
+ "library_loader.cpp" ,
+ "ohos_xcomponent_adapter.cpp",
+ "./napi/platform_view_ohos_napi.cpp",
+ "ohos_shell_holder.cpp",
+ "platform_view_ohos.cpp",
+ "ohos_display.cpp",
+ "ohos_surface_software.cpp",
+ "platform_message_handler_ohos.cpp",
+ "platform_message_response_ohos.cpp",
+ "vsync_waiter_ohos.cpp",
+ "./surface/ohos_native_window.cpp",
+ "./surface/ohos_surface.cpp",
+ "./context/ohos_context.cpp",
+ "ohos_asset_provider.cpp",
+ "ohos_touch_processor.cpp",
+ "ohos_main.cpp" ,
+ "ohos_logger.c" ,
+ "ohos_context_gl_impeller.cpp",
+ "ohos_surface_gl_impeller.cpp",
+ # "//flutter/impeller/toolkit/egl/display.cc",
+ "ohos_context_gl_skia.cpp" ,
+ "ohos_egl_surface.cpp" ,
+ "ohos_environment_gl.cpp",
+ "ohos_surface_gl_skia.cpp",
+ "ohos_image_generator.cpp",
+ "ohos_external_texture_gl.cpp",
+ "./surface/ohos_snapshot_surface_producer.cpp",
+ ]
+
+ # Set flag to stop headers being directly included (library users should not do this)
+ defines = [
+ "FLUTTER_LINUX_COMPILATION",
+ "FLUTTER_ENGINE_NO_PROTOTYPES",
+ "OHOS_PLATFORM" ,
+ "__MUSL__",
+ ]
+
+ deps = [
+ "//flutter/shell/platform/common:common_cpp_input",
+ "//flutter/shell/platform/common:common_cpp_switches",
+ "//flutter/shell/platform/embedder:embedder_headers",
+ "//third_party/rapidjson",
+ ]
+
+ public_deps = [
+ ":ohos_gpu_configuration",
+ "//flutter/assets",
+ "//flutter/common",
+ "//flutter/common/graphics",
+ "//flutter/flow",
+ "//flutter/fml",
+ "//flutter/impeller",
+ "//flutter/impeller/toolkit/egl",
+ "//flutter/lib/ui",
+ "//flutter/runtime",
+ "//flutter/runtime:libdart",
+ "//flutter/shell/common",
+ #"//flutter/vulkan",
+ "//third_party/skia",
+ "//flutter/shell/gpu:gpu_surface_gl",
+
+
+ ]
+
+}
+
+source_set("flutter_ohos_src") {
+ configs += [
+ #"//flutter/shell/platform/ohos/config:gtk",
+ #"//flutter/shell/platform/ohos/config:epoxy",
+ ]
+
+ defines = [ "FLUTTER_ENGINE_NO_PROTOTYPES" ]
+
+ public_deps = [ ":flutter_ohos_sources"]
+
+ deps = [ "//flutter/shell/platform/embedder:embedder_as_internal_library" ]
+}
+
+test_fixtures("flutter_ohos_fixtures") {
+ fixtures = []
+}
+
+
+executable("flutter_ohos_unittests") {
+ testonly = true
+
+ sources = [
+ #"testing/mock_texture_registrar.cc",
+ ]
+
+ public_configs = [ "//flutter:config" ]
+
+
+ defines = [
+ "FLUTTER_ENGINE_NO_PROTOTYPES",
+
+ # Set flag to allow public headers to be directly included
+ # (library users should not do this)
+ "FLUTTER_LINUX_COMPILATION",
+ ]
+
+ deps = [
+ ":flutter_ohos_fixtures",
+ ":flutter_ohos_sources",
+ "//flutter/runtime:libdart",
+ "//flutter/shell/platform/embedder:embedder_headers",
+ "//flutter/shell/platform/embedder:embedder_test_utils",
+ "//flutter/testing",
+ ]
+}
+
+shared_library("flutter") {
+ deps = [ ":flutter_ohos_src" ]
+
+ ldflags = ["--rtlib=compiler-rt",
+ "-fuse-ld=lld",
+ "-static-libstdc++",
+# "-Wl", "--build-id=sha1",
+# "-Wl,","--warn-shared-textrel",
+# "-Wl,","--fatal-warnings -lunwind",
+# "-Wl,","--no-undefined -Qunused-arguments",
+# "-Wl,","-z,noexecstack"
+ ]
+
+ #ldflags = [ "-Wl,-rpath,\$ORIGIN" ]
+ #ldflags += ["-L{$OHOS_NDK_LIB}","-lnative_window"]
+ ldflags += ["-lnative_window"]
+ ldflags += ["-lnative_vsync"]
+ ldflags += ["-lace_napi.z"]
+ ldflags += ["-lace_ndk.z"]
+ ldflags += ["-lhilog_ndk.z"]
+ ldflags += ["-luv"]
+ ldflags += ["-lrawfile.z"]
+ ldflags += ["-lEGL"]
+ ldflags += ["-lGLESv3"]
+
+ ldflags += ["-lc++_shared"]
+ ldflags += ["-lm"]
+ ldflags += ["-lpthread"]
+ ldflags += ["-lpixelmap_ndk.z"]
+
+
+ public_configs = [ "//flutter:config" ]
+}
+
+#copy("publish_headers_ohos") {
+# sources = _public_headers
+# outputs = [ "$root_out_dir/flutter_ohos/{{source_file_part}}" ]
+#}
+
+#zip_bundle("flutter_gtk") {
+# prefix = "$full_target_platform_name/"
+# if (flutter_runtime_mode != "debug" ||
+# (flutter_runtime_mode == "debug" && target_cpu != "x64")) {
+# prefix = "$full_target_platform_name-$flutter_runtime_mode/"
+# }
+# output = "${prefix}${full_target_platform_name}-flutter-gtk.zip"
+# deps = [
+# ":flutter_ohos_gtk",
+# ":publish_headers_ohos",
+# "//third_party/dart/runtime/bin:gen_snapshot",
+# ]
+# sources = get_target_outputs(":publish_headers_ohos")
+# tmp_files = []
+# foreach(source, sources) {
+# tmp_files += [
+# {
+# source = source
+# destination = rebase_path(source, "$root_build_dir")
+# },
+# ]
+# }
+# tmp_files += [
+# {
+# source = "$root_build_dir/libflutter_${host_os}_gtk.so"
+# destination = "libflutter_${host_os}_gtk.so"
+# },
+# {
+# source = "$root_build_dir/gen_snapshot"
+# destination = "gen_snapshot"
+# },
+# ]
+# files = tmp_files
+#}
diff --git a/shell/platform/ohos/config/BUILD.gn b/shell/platform/ohos/config/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..d8a2dd87c9a984b7392d1658c1fb80b0df9b6c68
--- /dev/null
+++ b/shell/platform/ohos/config/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#import("//build/config/linux/pkg_config.gni")
+import("//flutter/shell/platform/glfw/config.gni")
diff --git a/shell/platform/ohos/context/ohos_context.cpp b/shell/platform/ohos/context/ohos_context.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e436459390a0f9e7a2af97d33822c1026cd5f056
--- /dev/null
+++ b/shell/platform/ohos/context/ohos_context.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flutter/shell/platform/ohos/context/ohos_context.h"
+
+namespace flutter {
+
+OHOSContext::OHOSContext(OHOSRenderingAPI rendering_api)
+ : rendering_api_(rendering_api) {}
+
+OHOSContext::~OHOSContext() {
+ if (main_context_) {
+ main_context_->releaseResourcesAndAbandonContext();
+ }
+}
+
+OHOSRenderingAPI OHOSContext::RenderingApi() const {
+ return rendering_api_;
+}
+
+bool OHOSContext::IsValid() const {
+ return true;
+}
+
+void OHOSContext::SetMainSkiaContext(
+ const sk_sp& main_context) {
+ main_context_ = main_context;
+}
+
+sk_sp OHOSContext::GetMainSkiaContext() const {
+ return main_context_;
+}
+
+} // namespace flutter
\ No newline at end of file
diff --git a/shell/platform/ohos/context/ohos_context.h b/shell/platform/ohos/context/ohos_context.h
new file mode 100644
index 0000000000000000000000000000000000000000..84cdeb5820f055aab74deaaf36f7981878110468
--- /dev/null
+++ b/shell/platform/ohos/context/ohos_context.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OHOS_CONTEXT_H
+#define OHOS_CONTEXT_H
+
+#include "flutter/fml/macros.h"
+#include "flutter/fml/task_runner.h"
+#include "third_party/skia/include/gpu/GrDirectContext.h"
+
+namespace flutter {
+
+enum class OHOSRenderingAPI {
+ kSoftware,
+ kOpenGLES,
+};
+
+class OHOSContext {
+ public:
+ explicit OHOSContext(OHOSRenderingAPI rendering_api);
+
+ virtual ~OHOSContext();
+
+ OHOSRenderingAPI RenderingApi() const;
+
+ virtual bool IsValid() const;
+
+ void SetMainSkiaContext(const sk_sp& main_context);
+
+ sk_sp GetMainSkiaContext() const;
+
+ private:
+ const OHOSRenderingAPI rendering_api_;
+
+ // This is the Skia context used for on-screen rendering.
+ sk_sp main_context_;
+
+ FML_DISALLOW_COPY_AND_ASSIGN(OHOSContext);
+};
+
+} // namespace flutter
+#endif
\ No newline at end of file
diff --git a/shell/platform/ohos/library_loader.cpp b/shell/platform/ohos/library_loader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ef39c7ca82fc970e14ee3802ddd42d4a3de3674a
--- /dev/null
+++ b/shell/platform/ohos/library_loader.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h"
+#include "flutter/shell/platform/ohos/ohos_main.h"
+#include "napi/native_api.h"
+#include "napi_common.h"
+#include "ohos_xcomponent_adapter.h"
+
+// namespace flutter {
+
+EXTERN_C_START
+static napi_value Init(napi_env env, napi_value exports) {
+ FML_DLOG(INFO) << "Flutter Init NAPI";
+ napi_property_descriptor desc[] = {
+ // TODO:1 ArcTS import so库的时候应该先初始化shell
+ // Holder,然后再初始化XComponent
+ DECLARE_NAPI_FUNCTION("nativeInit", flutter::OhosMain::NativeInit),
+ DECLARE_NAPI_FUNCTION(
+ "nativeImageDecodeCallback",
+ flutter::OHOSImageGenerator::NativeImageDecodeCallback),
+ DECLARE_NAPI_FUNCTION(
+ "nativeUpdateRefreshRate",
+ flutter::PlatformViewOHOSNapi::nativeUpdateRefreshRate),
+ DECLARE_NAPI_FUNCTION(
+ "nativeRunBundleAndSnapshotFromLibrary",
+ flutter::PlatformViewOHOSNapi::nativeRunBundleAndSnapshotFromLibrary),
+ DECLARE_NAPI_FUNCTION(
+ "nativePrefetchDefaultFontManager",
+ flutter::PlatformViewOHOSNapi::nativePrefetchDefaultFontManager),
+ DECLARE_NAPI_FUNCTION(
+ "nativeGetIsSoftwareRenderingEnabled",
+ flutter::PlatformViewOHOSNapi::nativeGetIsSoftwareRenderingEnabled),
+ DECLARE_NAPI_FUNCTION("nativeAttach",
+ flutter::PlatformViewOHOSNapi::nativeAttach),
+ DECLARE_NAPI_FUNCTION("nativeSpawn",
+ flutter::PlatformViewOHOSNapi::nativeSpawn),
+ DECLARE_NAPI_FUNCTION("nativeDestroy",
+ flutter::PlatformViewOHOSNapi::nativeDestroy),
+ DECLARE_NAPI_FUNCTION(
+ "nativeSetViewportMetrics",
+ flutter::PlatformViewOHOSNapi::nativeSetViewportMetrics),
+ DECLARE_NAPI_FUNCTION(
+ "nativeSetAccessibilityFeatures",
+ flutter::PlatformViewOHOSNapi::nativeSetAccessibilityFeatures),
+ DECLARE_NAPI_FUNCTION(
+ "nativeCleanupMessageData",
+ flutter::PlatformViewOHOSNapi::nativeCleanupMessageData),
+ DECLARE_NAPI_FUNCTION(
+ "nativeDispatchEmptyPlatformMessage",
+ flutter::PlatformViewOHOSNapi::nativeDispatchEmptyPlatformMessage),
+ DECLARE_NAPI_FUNCTION(
+ "nativeDispatchPlatformMessage",
+ flutter::PlatformViewOHOSNapi::nativeDispatchPlatformMessage),
+ DECLARE_NAPI_FUNCTION(
+ "nativeInvokePlatformMessageEmptyResponseCallback",
+ flutter::PlatformViewOHOSNapi::
+ nativeInvokePlatformMessageEmptyResponseCallback),
+ DECLARE_NAPI_FUNCTION("nativeInvokePlatformMessageResponseCallback",
+ flutter::PlatformViewOHOSNapi::
+ nativeInvokePlatformMessageResponseCallback),
+ DECLARE_NAPI_FUNCTION(
+ "nativeLoadDartDeferredLibrary",
+ flutter::PlatformViewOHOSNapi::nativeLoadDartDeferredLibrary),
+ DECLARE_NAPI_FUNCTION(
+ "nativeUpdateOhosAssetManager",
+ flutter::PlatformViewOHOSNapi::nativeUpdateOhosAssetManager),
+ DECLARE_NAPI_FUNCTION(
+ "nativeDeferredComponentInstallFailure",
+ flutter::PlatformViewOHOSNapi::nativeDeferredComponentInstallFailure),
+ DECLARE_NAPI_FUNCTION("nativeGetPixelMap",
+ flutter::PlatformViewOHOSNapi::nativeGetPixelMap),
+ DECLARE_NAPI_FUNCTION(
+ "nativeNotifyLowMemoryWarning",
+ flutter::PlatformViewOHOSNapi::nativeNotifyLowMemoryWarning),
+ DECLARE_NAPI_FUNCTION(
+ "nativeFlutterTextUtilsIsEmoji",
+ flutter::PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmoji),
+ DECLARE_NAPI_FUNCTION(
+ "nativeFlutterTextUtilsIsEmojiModifier",
+ flutter::PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmojiModifier),
+ DECLARE_NAPI_FUNCTION("nativeFlutterTextUtilsIsEmojiModifierBase",
+ flutter::PlatformViewOHOSNapi::
+ nativeFlutterTextUtilsIsEmojiModifierBase),
+ DECLARE_NAPI_FUNCTION("nativeFlutterTextUtilsIsVariationSelector",
+ flutter::PlatformViewOHOSNapi::
+ nativeFlutterTextUtilsIsVariationSelector),
+ DECLARE_NAPI_FUNCTION("nativeFlutterTextUtilsIsRegionalIndicator",
+ flutter::PlatformViewOHOSNapi::
+ nativeFlutterTextUtilsIsRegionalIndicator),
+ DECLARE_NAPI_FUNCTION(
+ "nativeGetSystemLanguages",
+ flutter::PlatformViewOHOSNapi::nativeGetSystemLanguages),
+
+ };
+ napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
+ bool ret = flutter::XComponentAdapter::GetInstance()->Export(env, exports);
+ if (!ret) {
+ FML_DLOG(INFO) << "Flutter Init Failed";
+ }
+ return exports;
+}
+EXTERN_C_END
+
+static napi_module flutterModule = {
+ .nm_version = 1,
+ .nm_flags = 0,
+ .nm_filename = nullptr,
+ .nm_register_func = Init,
+ .nm_modname = "flutter",
+ .nm_priv = ((void*)0),
+ .reserved = {0},
+};
+
+extern "C" __attribute__((constructor)) void RegisterEntryModule(void) {
+ napi_module_register(&flutterModule);
+}
+
+//}
diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.cpp b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6eec795900517d524e82fb5e92a25d2e223f72fd
--- /dev/null
+++ b/shell/platform/ohos/napi/platform_view_ohos_napi.cpp
@@ -0,0 +1,1398 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "platform_view_ohos_napi.h"
+#include
+#include
+#include
+#include
+#include
+#include "flutter/fml/make_copyable.h"
+#include "flutter/fml/platform/ohos/napi_util.h"
+#include "flutter/shell/platform/ohos/ohos_main.h"
+#include "flutter/shell/platform/ohos/ohos_shell_holder.h"
+#include "flutter/shell/platform/ohos/surface/ohos_native_window.h"
+#include "unicode/uchar.h"
+
+#define OHOS_SHELL_HOLDER (reinterpret_cast(shell_holder))
+namespace flutter {
+
+int64_t PlatformViewOHOSNapi::shell_holder;
+napi_env PlatformViewOHOSNapi::env_;
+napi_ref PlatformViewOHOSNapi::ref_napi_obj_;
+std::vector PlatformViewOHOSNapi::system_languages;
+
+/**
+ * @brief send empty PlatformMessage
+ * @note
+ * @param nativeShellHolderId: number,channel: string,responseId: number
+ * @return void
+ */
+napi_value PlatformViewOHOSNapi::nativeDispatchEmptyPlatformMessage(
+ napi_env env,
+ napi_callback_info info) {
+ FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeDispatchEmptyPlatformMessage";
+ napi_status ret;
+ size_t argc = 3;
+ napi_value args[3] = {nullptr};
+ napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ int64_t shell_holder, responseId;
+ std::string channel;
+ ret = napi_get_value_int64(env, args[0], &shell_holder);
+ if (ret != napi_ok) {
+ LOGE("nativeDispatchEmptyPlatformMessage napi get shell_holder error");
+ return nullptr;
+ }
+ fml::napi::GetString(env, args[1], channel);
+ FML_DLOG(INFO) << "nativeDispatchEmptyPlatformMessage channel:" << channel;
+ ret = napi_get_value_int64(env, args[2], &responseId);
+ if (ret != napi_ok) {
+ LOGE("nativeDispatchEmptyPlatformMessage napi get responseId error");
+ return nullptr;
+ }
+ FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeDispatchEmptyPlatformMessage "
+ "DispatchEmptyPlatformMessage";
+ OHOS_SHELL_HOLDER->GetPlatformView()->DispatchEmptyPlatformMessage(
+ channel, responseId);
+ return nullptr;
+}
+
+/**
+ * @brief send PlatformMessage
+ * @note
+ * @param nativeShellHolderId: number,channel: string,message:
+ * ArrayBuffer,position: number,responseId: number
+ * @return void
+ */
+napi_value PlatformViewOHOSNapi::nativeDispatchPlatformMessage(
+ napi_env env,
+ napi_callback_info info) {
+ FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeDispatchPlatformMessage";
+ napi_status ret;
+ napi_value thisArg;
+ size_t argc = 5;
+ napi_value args[5] = {nullptr};
+ int64_t shell_holder, responseId, position;
+ std::string channel;
+ void* message = nullptr;
+ size_t message_lenth = 0;
+
+ int32_t status;
+
+ // flutter.nativeDispatchPlatformMessage(this.nativeShellHolderId, channel,
+ // message, position, responseId);
+ //
+ ret = napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr);
+ if (argc < 5 || ret != napi_ok) {
+ FML_DLOG(ERROR) << "nativeDispatchPlatformMessage napi get argc ,argc="
+ << argc << "<5,error:" << ret;
+ napi_throw_type_error(env, nullptr, "Wrong number of arguments");
+ return nullptr;
+ }
+ // #ifndef NDEBUG
+ fml::napi::NapiPrintValueTypes(env, argc, args);
+ // #endif
+
+ napi_value napiShellHolder = args[0];
+ napi_value napiChannel = args[1];
+ napi_value napiMessage = args[2];
+ napi_value napiPos = args[3];
+ napi_value napiResponseId = args[4];
+
+ ret = napi_get_value_int64(env, napiShellHolder, &shell_holder);
+ if (ret != napi_ok) {
+ LOGE("nativeDispatchPlatformMessage napi get shell_holder error");
+ return nullptr;
+ }
+ FML_DLOG(INFO) << "nativeDispatchPlatformMessage:shell_holder:"
+ << shell_holder;
+
+ if (0 != (status = fml::napi::GetString(env, napiChannel, channel))) {
+ FML_DLOG(ERROR) << "nativeDispatchPlatformMessage napi get channel error:"
+ << status;
+ return nullptr;
+ }
+ FML_DLOG(INFO) << "nativeDispatchEmptyPlatformMessage channel:" << channel;
+
+ if (0 != (status = fml::napi::GetArrayBuffer(env, napiMessage, &message,
+ &message_lenth))) {
+ FML_DLOG(ERROR) << "nativeDispatchPlatformMessage napi get message error:"
+ << status;
+ return nullptr;
+ }
+ if (message == nullptr) {
+ FML_LOG(ERROR)
+ << "nativeInvokePlatformMessageResponseCallback message null";
+ return nullptr;
+ }
+ ret = napi_get_value_int64(env, napiPos, &position);
+ if (ret != napi_ok) {
+ LOGE("nativeDispatchPlatformMessage napi get position error");
+ return nullptr;
+ }
+ ret = napi_get_value_int64(env, napiResponseId, &responseId);
+ if (ret != napi_ok) {
+ LOGE("nativeDispatchPlatformMessage napi get responseId error");
+ return nullptr;
+ }
+ FML_DLOG(INFO) << "DispatchPlatformMessage,channel:" << channel
+ << ",message:" << message << ",position:" << position
+ << ",responseId:" << responseId;
+
+ OHOS_SHELL_HOLDER->GetPlatformView()->DispatchPlatformMessage(
+ channel, message, position, responseId);
+ return nullptr;
+}
+/**
+ * @brief
+ * @note
+ * @param nativeShellHolderId: number,responseId: number
+ * @return void
+ */
+napi_value
+PlatformViewOHOSNapi::nativeInvokePlatformMessageEmptyResponseCallback(
+ napi_env env,
+ napi_callback_info info) {
+ FML_DLOG(INFO) << "nativeInvokePlatformMessageEmptyResponseCallback";
+ napi_status ret;
+ size_t argc = 2;
+ napi_value args[2] = {nullptr};
+ napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ int64_t shell_holder, responseId;
+ ret = napi_get_value_int64(env, args[0], &shell_holder);
+ if (ret != napi_ok) {
+ LOGE(
+ "nativeInvokePlatformMessageEmptyResponseCallback napi get "
+ "shell_holder error");
+ return nullptr;
+ }
+ ret = napi_get_value_int64(env, args[1], &responseId);
+ if (ret != napi_ok) {
+ LOGE(" napi get responseId error");
+ return nullptr;
+ }
+ FML_DLOG(INFO) << "InvokePlatformMessageEmptyResponseCallback";
+ OHOS_SHELL_HOLDER->GetPlatformMessageHandler()
+ ->InvokePlatformMessageEmptyResponseCallback(responseId);
+ return nullptr;
+}
+/**
+ * @brief
+ * @note
+ * @param nativeShellHolderId: number, responseId: number, message:
+ * ArrayBuffer,position: number
+ * @return void
+ */
+napi_value PlatformViewOHOSNapi::nativeInvokePlatformMessageResponseCallback(
+ napi_env env,
+ napi_callback_info info) {
+ FML_DLOG(INFO) << "nativeInvokePlatformMessageResponseCallback";
+ napi_status ret;
+ size_t argc = 4;
+ napi_value args[4] = {nullptr};
+ napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ int64_t shell_holder, responseId, position;
+ void* message = nullptr;
+ size_t message_lenth = 0;
+ ret = napi_get_value_int64(env, args[0], &shell_holder);
+ if (ret != napi_ok) {
+ LOGE(" napi get shell_holdererror");
+ return nullptr;
+ }
+ ret = napi_get_value_int64(env, args[1], &responseId);
+ if (ret != napi_ok) {
+ LOGE(" napi get responseId error");
+ return nullptr;
+ }
+ int32_t result =
+ fml::napi::GetArrayBuffer(env, args[2], &message, &message_lenth);
+ if (result != 0) {
+ FML_DLOG(ERROR)
+ << "nativeInvokePlatformMessageResponseCallback GetArrayBuffer error "
+ << result;
+ }
+ if (message == nullptr) {
+ FML_LOG(ERROR)
+ << "nativeInvokePlatformMessageResponseCallback message null";
+ return nullptr;
+ }
+ ret = napi_get_value_int64(env, args[3], &position);
+ if (ret != napi_ok) {
+ LOGE("nativeInvokePlatformMessageResponseCallback napi get position error");
+ return nullptr;
+ }
+
+ uint8_t* response_data = static_cast(message);
+ FML_DCHECK(response_data != nullptr);
+ auto mapping = std::make_unique(
+ fml::MallocMapping::Copy(response_data, response_data + position));
+ FML_DLOG(INFO) << "InvokePlatformMessageResponseCallback";
+ OHOS_SHELL_HOLDER->GetPlatformMessageHandler()
+ ->InvokePlatformMessageResponseCallback(responseId, std::move(mapping));
+ return nullptr;
+}
+
+/* void PlatformViewOHOSNapi::FlutterViewHandlePlatformMessageResponse(
+ int responseId,
+ std::unique_ptr data) {
+
+}
+ */
+PlatformViewOHOSNapi::PlatformViewOHOSNapi(napi_env env) {}
+
+void PlatformViewOHOSNapi::FlutterViewHandlePlatformMessageResponse(
+ int reponse_id,
+ std::unique_ptr data) {
+ FML_DLOG(INFO) << "FlutterViewHandlePlatformMessageResponse";
+ napi_status status;
+ napi_value callbackParam[2];
+ status = napi_create_int64(env_, reponse_id, callbackParam);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "napi_create_int64 reponse_id fail";
+ }
+
+ if (data == nullptr) {
+ callbackParam[1] = NULL;
+ } else {
+ callbackParam[1] = fml::napi::CreateArrayBuffer(
+ env_, (void*)data->GetMapping(), data->GetSize());
+ }
+
+ status = fml::napi::InvokeJsMethod(
+ env_, ref_napi_obj_, "handlePlatformMessageResponse", 2, callbackParam);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "InvokeJsMethod fail ";
+ }
+}
+
+void PlatformViewOHOSNapi::FlutterViewHandlePlatformMessage(
+ int reponse_id,
+ std::unique_ptr message) {
+ FML_DLOG(INFO) << "FlutterViewHandlePlatformMessage message channal "
+ << message->channel().c_str();
+
+ napi_value callbackParam[4];
+ napi_status status;
+
+ status = napi_create_string_utf8(env_, message->channel().c_str(),
+ message->channel().size(), callbackParam);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "napi_create_string_utf8 err " << status;
+ return;
+ }
+
+ if (message->data().GetSize() > 0) {
+ callbackParam[1] = fml::napi::CreateArrayBuffer(
+ env_, (void*)message->data().GetMapping(), message->data().GetSize());
+
+ status = napi_create_int64(env_, reponse_id, &callbackParam[2]);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "napi_create_int64 err " << status;
+ return;
+ }
+
+ fml::MallocMapping mapping = message->releaseData();
+ char* mapData = (char*)mapping.Release();
+ status = napi_create_string_utf8(env_, mapData, strlen(mapData),
+ &callbackParam[3]);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "napi_create_string_utf8 err " << status;
+ return;
+ }
+
+ if (mapData) {
+ delete mapData;
+ }
+
+ status = fml::napi::InvokeJsMethod(
+ env_, ref_napi_obj_, "handlePlatformMessage", 4, callbackParam);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "InvokeJsMethod fail ";
+ }
+ }
+}
+
+void PlatformViewOHOSNapi::FlutterViewOnFirstFrame() {
+ FML_DLOG(INFO) << "FlutterViewOnFirstFrame";
+ napi_status status = fml::napi::InvokeJsMethod(env_, ref_napi_obj_,
+ "onFirstFrame", 0, nullptr);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "InvokeJsMethod onFirstFrame fail ";
+ }
+}
+
+void PlatformViewOHOSNapi::FlutterViewOnPreEngineRestart() {
+ FML_DLOG(INFO) << "FlutterViewOnPreEngineRestart";
+ napi_status status = fml::napi::InvokeJsMethod(
+ env_, ref_napi_obj_, "onPreEngineRestart", 0, nullptr);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "InvokeJsMethod onPreEngineRestart fail ";
+ }
+}
+
+std::vector splitString(const std::string& input, char delimiter) {
+ std::vector result;
+ std::stringstream ss(input);
+ std::string token;
+
+ while (std::getline(ss, token, delimiter)) {
+ result.push_back(token);
+ }
+
+ return result;
+}
+flutter::locale PlatformViewOHOSNapi::resolveNativeLocale(
+ std::vector supportedLocales) {
+ if (supportedLocales.empty()) {
+ flutter::locale default_locale;
+ default_locale.language = "zh";
+ default_locale.script = "Hans";
+ default_locale.region = "CN";
+ return default_locale;
+ }
+ char delimiter = '-';
+ if (PlatformViewOHOSNapi::system_languages.empty()) {
+ PlatformViewOHOSNapi::system_languages.push_back("zh-Hans");
+ }
+ for (size_t i = 0; i < PlatformViewOHOSNapi::system_languages.size(); i++) {
+ std::string language = PlatformViewOHOSNapi::system_languages
+ [i]; // 格式language-script-region,例如en-Latn-US
+ for (const locale& localeInfo : supportedLocales) {
+ if (language == localeInfo.language + "-" + localeInfo.script + "-" +
+ localeInfo.region) {
+ return localeInfo;
+ }
+ std::vector element = splitString(language, delimiter);
+ if (element[0] + "-" + element[1] ==
+ localeInfo.language + "-" + localeInfo.region) {
+ return localeInfo;
+ }
+ if (element[0] == localeInfo.language) {
+ return localeInfo;
+ }
+ }
+ }
+ return supportedLocales[0];
+}
+
+std::unique_ptr>
+PlatformViewOHOSNapi::FlutterViewComputePlatformResolvedLocales(
+ const std::vector& support_locale_data) {
+ std::vector supportedLocales;
+ std::vector result;
+ const int localeDataLength = 3;
+ flutter::locale mlocale;
+ for (size_t i = 0; i < support_locale_data.size(); i += localeDataLength) {
+ mlocale.language = support_locale_data[i + 0];
+ mlocale.region = support_locale_data[i + 1];
+ mlocale.script = support_locale_data[i + 2];
+ supportedLocales.push_back(mlocale);
+ }
+ mlocale = resolveNativeLocale(supportedLocales);
+ result.push_back(mlocale.language);
+ result.push_back(mlocale.region);
+ result.push_back(mlocale.script);
+ FML_DLOG(INFO) << "resolveNativeLocale result to flutter language: "
+ << result[0] << " region: " << result[1]
+ << " script: " << result[2];
+ return std::make_unique>(std::move(result));
+}
+
+void PlatformViewOHOSNapi::DecodeImage(int64_t imageGeneratorAddress,
+ void* inputData,
+ size_t dataSize) {
+ FML_DLOG(INFO) << "start decodeImage";
+ platform_task_runner_->PostTask(fml::MakeCopyable(
+ [imageGeneratorAddress_ = imageGeneratorAddress,
+ inputData_ = std::move(inputData), dataSize_ = dataSize]() mutable {
+ napi_value callbackParam[2];
+
+ callbackParam[0] =
+ fml::napi::CreateArrayBuffer(env_, inputData_, dataSize_);
+ napi_status status =
+ napi_create_int64(env_, imageGeneratorAddress_, &callbackParam[1]);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "napi_create_int64 decodeImage fail ";
+ }
+ status = fml::napi::InvokeJsMethod(env_, ref_napi_obj_, "decodeImage",
+ 2, callbackParam);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "InvokeJsMethod decodeImage fail ";
+ }
+ }));
+}
+
+/**
+ * attach flutterNapi实例给到 native
+ * engine,这个支持rkts到flutter平台的无关引擎之间的通信 attach只需要执行一次
+ */
+napi_value PlatformViewOHOSNapi::nativeAttach(napi_env env,
+ napi_callback_info info) {
+ FML_DLOG(INFO) << "PlatformViewOHOSNapi::nativeAttach";
+
+ napi_status status;
+ // 获取传入的参数
+ size_t argc = 1;
+ napi_value argv[1];
+ status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "nativeAttach Failed to get napiObjec info";
+ }
+ napi_create_reference(env, argv[0], 1, &ref_napi_obj_);
+
+ std::shared_ptr napi_facade =
+ std::make_shared(env);
+
+ uv_loop_t* platform_loop = nullptr;
+ status = napi_get_uv_event_loop(env, &platform_loop);
+ if (status != napi_ok) {
+ FML_DLOG(ERROR) << "nativeAttach napi_get_uv_event_loop fail";
+ }
+
+ auto shell_holder = std::make_unique(
+ OhosMain::Get().GetSettings(), napi_facade, platform_loop);
+ if (shell_holder->IsValid()) {
+ PlatformViewOHOSNapi::shell_holder =
+ reinterpret_cast(shell_holder.get());
+ FML_DLOG(INFO) << "PlatformViewOHOSNapi shell_holder:"
+ << PlatformViewOHOSNapi::shell_holder;
+ napi_value id;
+ napi_create_int64(env, reinterpret_cast(shell_holder.release()),
+ &id);
+ return id;
+ } else {
+ FML_DLOG(ERROR) << "shell holder inValid";
+ napi_value id;
+ napi_create_int64(env, 0, &id);
+ return id;
+ }
+}
+
+/**
+ * 加载dart工程构建产物
+ */
+napi_value PlatformViewOHOSNapi::nativeRunBundleAndSnapshotFromLibrary(
+ napi_env env,
+ napi_callback_info info) {
+ napi_status ret;
+ size_t argc = 6;
+ napi_value args[6] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeRunBundleAndSnapshotFromLibrary napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t shell_holder;
+ ret = napi_get_value_int64(env, args[0], &shell_holder);
+ if (ret != napi_ok) {
+ LOGE("nativeRunBundleAndSnapshotFromLibrary napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeRunBundleAndSnapshotFromLibrary::shell_holder : %{public}ld",
+ shell_holder);
+
+ std::string bundlePath;
+ if (fml::napi::SUCCESS != fml::napi::GetString(env, args[1], bundlePath)) {
+ LOGE(" napi_get_value_string_utf8 error");
+ return nullptr;
+ }
+ LOGD("nativeRunBundleAndSnapshotFromLibrary: bundlePath: %{public}s",
+ bundlePath.c_str());
+
+ std::string entrypointFunctionName;
+ if (fml::napi::SUCCESS !=
+ fml::napi::GetString(env, args[2], entrypointFunctionName)) {
+ LOGE(" napi_get_value_string_utf8 error");
+ return nullptr;
+ }
+ LOGD("entrypointFunctionName: %{public}s", entrypointFunctionName.c_str());
+
+ std::string pathToEntrypointFunction;
+ if (fml::napi::SUCCESS !=
+ fml::napi::GetString(env, args[3], pathToEntrypointFunction)) {
+ LOGE(" napi_get_value_string_utf8 error");
+ return nullptr;
+ }
+ LOGD(" pathToEntrypointFunction: %{public}s",
+ pathToEntrypointFunction.c_str());
+
+ NativeResourceManager* ResourceManager =
+ OH_ResourceManager_InitNativeResourceManager(env, args[4]);
+
+ std::vector entrypointArgs;
+ if (fml::napi::SUCCESS !=
+ fml::napi::GetArrayString(env, args[5], entrypointArgs)) {
+ LOGE("nativeRunBundleAndSnapshotFromLibrary GetArrayString error");
+ return nullptr;
+ }
+
+ auto ohos_asset_provider = std::make_unique(
+ static_cast(ResourceManager));
+ OHOS_SHELL_HOLDER->Launch(std::move(ohos_asset_provider),
+ entrypointFunctionName, pathToEntrypointFunction,
+ entrypointArgs);
+
+ env_ = env;
+ return nullptr;
+}
+
+/**
+ * 设置ResourceManager和assetBundlePath到engine
+ */
+napi_value PlatformViewOHOSNapi::nativeUpdateOhosAssetManager(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeUpdateOhosAssetManager");
+
+ // TODO:
+ return nullptr;
+}
+
+/**
+ * 从engine获取当前绘制pixelMap
+ */
+napi_value PlatformViewOHOSNapi::nativeGetPixelMap(napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeGetPixelMap");
+
+ // TODO:
+ return nullptr;
+}
+
+/**
+ * 从当前的flutterNapi复制一个新的实例
+ */
+napi_value PlatformViewOHOSNapi::nativeSpawn(napi_env env,
+ napi_callback_info info) {
+ // TODO:
+ return nullptr;
+}
+
+static void LoadLoadingUnitFailure(intptr_t loading_unit_id,
+ const std::string& message,
+ bool transient) {
+ // TODO(garyq): Implement
+ LOGD("LoadLoadingUnitFailure: message %s transient %d", message.c_str(),
+ transient);
+}
+
+/**
+ * load一个合法的.so文件到dart vm
+ */
+napi_value PlatformViewOHOSNapi::nativeLoadDartDeferredLibrary(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeLoadDartDeferredLibrary");
+
+ napi_status ret;
+ size_t argc = 3;
+ napi_value args[3] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeLoadDartDeferredLibrary napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t shell_holder;
+ ret = napi_get_value_int64(env, args[0], &shell_holder);
+ if (ret != napi_ok) {
+ LOGE("nativeLoadDartDeferredLibrary napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeLoadDartDeferredLibrary::shell_holder : %{public}ld",
+ shell_holder);
+
+ int64_t loadingUnitId;
+ ret = napi_get_value_int64(env, args[1], &loadingUnitId);
+ if (ret != napi_ok) {
+ LOGE("nativeLoadDartDeferredLibrary napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeLoadDartDeferredLibrary::loadingUnitId : %{public}ld",
+ loadingUnitId);
+
+ std::vector search_paths;
+ if (fml::napi::SUCCESS !=
+ fml::napi::GetArrayString(env, args[2], search_paths)) {
+ LOGE("nativeLoadDartDeferredLibrary GetArrayString error");
+ return nullptr;
+ }
+
+ LOGD("nativeLoadDartDeferredLibrary::search_paths");
+ for (const std::string& path : search_paths) {
+ LOGD("%{public}s", path.c_str());
+ }
+
+ intptr_t loading_unit_id = static_cast(loadingUnitId);
+ // Use dlopen here to directly check if handle is nullptr before creating a
+ // NativeLibrary.
+ void* handle = nullptr;
+ while (handle == nullptr && !search_paths.empty()) {
+ std::string path = search_paths.back();
+ handle = ::dlopen(path.c_str(), RTLD_NOW);
+ search_paths.pop_back();
+ }
+ if (handle == nullptr) {
+ LoadLoadingUnitFailure(loading_unit_id,
+ "No lib .so found for provided search paths.", true);
+ return nullptr;
+ }
+ fml::RefPtr native_lib =
+ fml::NativeLibrary::CreateWithHandle(handle, false);
+
+ // Resolve symbols.
+ std::unique_ptr data_mapping =
+ std::make_unique(
+ native_lib, DartSnapshot::kIsolateDataSymbol);
+ std::unique_ptr instructions_mapping =
+ std::make_unique(
+ native_lib, DartSnapshot::kIsolateInstructionsSymbol);
+
+ OHOS_SHELL_HOLDER->GetPlatformView()->LoadDartDeferredLibrary(
+ loading_unit_id, std::move(data_mapping),
+ std::move(instructions_mapping));
+
+ return nullptr;
+}
+
+/**
+ * 把物理屏幕参数通知到native
+ */
+napi_value PlatformViewOHOSNapi::nativeSetViewportMetrics(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeSetViewportMetrics");
+
+ napi_status ret;
+ size_t argc = 20;
+ napi_value args[20] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t shell_holder;
+ ret = napi_get_value_int64(env, args[0], &shell_holder);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::shell_holder : %{public}ld", shell_holder);
+
+ int64_t devicePixelRatio;
+ ret = napi_get_value_int64(env, args[1], &devicePixelRatio);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::devicePixelRatio : %{public}ld",
+ devicePixelRatio);
+
+ int64_t physicalWidth;
+ ret = napi_get_value_int64(env, args[2], &physicalWidth);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::physicalWidth : %{public}ld", physicalWidth);
+
+ int64_t physicalHeight;
+ ret = napi_get_value_int64(env, args[3], &physicalHeight);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::physicalHeight : %{public}ld",
+ physicalHeight);
+
+ int64_t physicalPaddingTop;
+ ret = napi_get_value_int64(env, args[4], &physicalPaddingTop);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::physicalPaddingTop : %{public}ld",
+ physicalPaddingTop);
+
+ int64_t physicalPaddingRight;
+ ret = napi_get_value_int64(env, args[5], &physicalPaddingRight);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::physicalPaddingRight : %{public}ld",
+ physicalPaddingRight);
+
+ int64_t physicalPaddingBottom;
+ ret = napi_get_value_int64(env, args[6], &physicalPaddingBottom);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::physicalPaddingBottom : %{public}ld",
+ physicalPaddingBottom);
+
+ int64_t physicalPaddingLeft;
+ ret = napi_get_value_int64(env, args[7], &physicalPaddingLeft);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::physicalPaddingLeft : %{public}ld",
+ physicalPaddingLeft);
+
+ int64_t physicalViewInsetTop;
+ ret = napi_get_value_int64(env, args[8], &physicalViewInsetTop);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::physicalViewInsetTop : %{public}ld",
+ physicalViewInsetTop);
+
+ int64_t physicalViewInsetRight;
+ ret = napi_get_value_int64(env, args[9], &physicalViewInsetRight);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::physicalViewInsetRight : %{public}ld",
+ physicalViewInsetRight);
+
+ int64_t physicalViewInsetBottom;
+ ret = napi_get_value_int64(env, args[10], &physicalViewInsetBottom);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::physicalViewInsetBottom : %{public}ld",
+ physicalViewInsetBottom);
+
+ int64_t physicalViewInsetLeft;
+ ret = napi_get_value_int64(env, args[11], &physicalViewInsetLeft);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::physicalViewInsetLeft : %{public}ld",
+ physicalViewInsetLeft);
+ int64_t systemGestureInsetTop;
+ ret = napi_get_value_int64(env, args[12], &systemGestureInsetTop);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::systemGestureInsetTop : %{public}ld",
+ systemGestureInsetTop);
+ int64_t systemGestureInsetRight;
+ ret = napi_get_value_int64(env, args[13], &systemGestureInsetRight);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::systemGestureInsetRight : %{public}ld",
+ systemGestureInsetRight);
+
+ int64_t systemGestureInsetBottom;
+ ret = napi_get_value_int64(env, args[14], &systemGestureInsetBottom);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::systemGestureInsetBottom : %{public}ld",
+ systemGestureInsetBottom);
+ int64_t systemGestureInsetLeft;
+ ret = napi_get_value_int64(env, args[15], &systemGestureInsetLeft);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::systemGestureInsetLeft : %{public}ld",
+ systemGestureInsetLeft);
+
+ int64_t physicalTouchSlop;
+ ret = napi_get_value_int64(env, args[16], &physicalTouchSlop);
+ if (ret != napi_ok) {
+ LOGE("nativeSetViewportMetrics napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetViewportMetrics::physicalTouchSlop : %{public}ld",
+ physicalTouchSlop);
+
+ std::vector displayFeaturesBounds;
+ napi_value array = args[17];
+ uint32_t length;
+ napi_get_array_length(env, array, &length);
+ displayFeaturesBounds.resize(length);
+ for (uint32_t i = 0; i < length; ++i) {
+ napi_value element;
+ napi_get_element(env, array, i, &element);
+ napi_get_value_double(env, element, &(displayFeaturesBounds[i]));
+ }
+
+ LOGD("nativeSetViewportMetrics::displayFeaturesBounds");
+ for (const uint64_t& bounds : displayFeaturesBounds) {
+ LOGD(" %{public}ld", bounds);
+ }
+
+ std::vector displayFeaturesType;
+ array = args[18];
+ napi_get_array_length(env, array, &length);
+ displayFeaturesType.resize(length);
+ for (uint32_t i = 0; i < length; ++i) {
+ napi_value element;
+ napi_get_element(env, array, i, &element);
+ napi_get_value_int64(env, element, &(displayFeaturesType[i]));
+ }
+
+ LOGD("nativeSetViewportMetrics::displayFeaturesType");
+ for (const uint64_t& featuresType : displayFeaturesType) {
+ LOGD(" %{public}ld", featuresType);
+ }
+
+ std::vector displayFeaturesState;
+ array = args[19];
+ napi_get_array_length(env, array, &length);
+ displayFeaturesState.resize(length);
+ for (uint32_t i = 0; i < length; ++i) {
+ napi_value element;
+ napi_get_element(env, array, i, &element);
+ napi_get_value_int64(env, element, &(displayFeaturesState[i]));
+ }
+
+ LOGD("nativeSetViewportMetrics::displayFeaturesState");
+ for (const uint64_t& featurestate : displayFeaturesState) {
+ LOGD(" %{public}ld", featurestate);
+ }
+
+ const flutter::ViewportMetrics metrics{
+ static_cast(devicePixelRatio),
+ static_cast(physicalWidth),
+ static_cast(physicalHeight),
+ static_cast(physicalPaddingTop),
+ static_cast(physicalPaddingRight),
+ static_cast(physicalPaddingBottom),
+ static_cast(physicalPaddingLeft),
+ static_cast(physicalViewInsetTop),
+ static_cast(physicalViewInsetRight),
+ static_cast(physicalViewInsetBottom),
+ static_cast(physicalViewInsetLeft),
+ static_cast(systemGestureInsetTop),
+ static_cast(systemGestureInsetRight),
+ static_cast(systemGestureInsetBottom),
+ static_cast(systemGestureInsetLeft),
+ static_cast(physicalTouchSlop),
+ displayFeaturesBounds,
+ std::vector(displayFeaturesType.begin(), displayFeaturesType.end()),
+ std::vector(displayFeaturesState.begin(),
+ displayFeaturesState.end()),
+ };
+
+ OHOS_SHELL_HOLDER->GetPlatformView()->SetViewportMetrics(metrics);
+
+ return nullptr;
+}
+
+/**
+ * 清除某个messageData
+ */
+napi_value PlatformViewOHOSNapi::nativeCleanupMessageData(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeCleanupMessageData");
+
+ napi_status ret;
+ size_t argc = 1;
+ napi_value args[1] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeUpdateRefreshRate napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t messageData;
+ ret = napi_get_value_int64(env, args[0], &messageData);
+ if (ret != napi_ok) {
+ LOGE("nativeUpdateRefreshRate napi_get_value_int64 error");
+ return nullptr;
+ }
+
+ LOGD("nativeCleanupMessageData messageData: %{public}ld", messageData);
+ free(reinterpret_cast(messageData));
+ return nullptr;
+}
+
+/**
+ * 设置刷新率
+ */
+napi_value PlatformViewOHOSNapi::nativeUpdateRefreshRate(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeUpdateRefreshRate");
+
+ int64_t refreshRate;
+ napi_status ret;
+ size_t argc = 1;
+ napi_value args[1] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeUpdateRefreshRate napi_get_cb_info error");
+ return nullptr;
+ }
+
+ ret = napi_get_value_int64(env, args[0], &refreshRate);
+ if (ret != napi_ok) {
+ LOGE("nativeUpdateRefreshRate napi_get_value_int64 error");
+ return nullptr;
+ }
+
+ LOGD("PlatformViewOHOSNapi::nativeUpdateRefreshRate: %{public}ld",
+ refreshRate);
+ FML_DCHECK(refreshRate > 0);
+ VsyncWaiterOHOS::OnUpdateRefreshRate(refreshRate);
+ return nullptr;
+}
+
+/**
+ * 初始化SkFontMgr::RefDefault(),skia引擎文字管理初始化
+ */
+napi_value PlatformViewOHOSNapi::nativePrefetchDefaultFontManager(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativePrefetchDefaultFontManager");
+
+ SkFontMgr::RefDefault();
+ return nullptr;
+}
+
+/**
+ * 返回是否支持软件绘制
+ */
+napi_value PlatformViewOHOSNapi::nativeGetIsSoftwareRenderingEnabled(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeGetIsSoftwareRenderingEnabled");
+ napi_value result = nullptr;
+ // TODO: 需要 FlutterMain 初始化
+ napi_status ret = napi_get_boolean(
+ env, OhosMain::Get().GetSettings().enable_software_rendering, &result);
+ if (ret != napi_ok) {
+ LOGE("nativeGetIsSoftwareRenderingEnabled napi_get_boolean error");
+ return nullptr;
+ }
+
+ return result;
+}
+
+/**
+ * Detaches flutterNapi和engine之间的关联
+ */
+napi_value PlatformViewOHOSNapi::nativeDestroy(napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeDestroy");
+
+ napi_status ret;
+ size_t argc = 1;
+ napi_value args[1] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeDestroy napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t shell_holder;
+ ret = napi_get_value_int64(env, args[0], &shell_holder);
+ if (ret != napi_ok) {
+ LOGE("nativeDestroy napi_get_value_int64 error");
+ return nullptr;
+ }
+
+ LOGD("nativeDestroy shell_holder: %{public}ld", shell_holder);
+
+ delete OHOS_SHELL_HOLDER;
+ return nullptr;
+}
+
+/**
+ * 设置能力参数
+ */
+napi_value PlatformViewOHOSNapi::nativeSetAccessibilityFeatures(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("nativeSetAccessibilityFeatures");
+
+ napi_status ret;
+ size_t argc = 2;
+ napi_value args[2] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeSetAccessibilityFeatures napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t shell_holder;
+ ret = napi_get_value_int64(env, args[0], &shell_holder);
+ if (ret != napi_ok) {
+ LOGE("nativeDestroy napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeSetAccessibilityFeatures shell_holder: %{public}ld",
+ shell_holder);
+ int64_t flags;
+ ret = napi_get_value_int64(env, args[1], &flags);
+ if (ret != napi_ok) {
+ LOGE("nativeSetAccessibilityFeatures napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD(
+ "PlatformViewOHOSNapi::nativeSetAccessibilityFeatures flags: %{public}ld",
+ flags);
+ OHOS_SHELL_HOLDER->GetPlatformView()->SetAccessibilityFeatures(flags);
+ return nullptr;
+}
+
+/**
+ * 加载动态库,或者dart库失败时的通知
+ */
+napi_value PlatformViewOHOSNapi::nativeDeferredComponentInstallFailure(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeDeferredComponentInstallFailure");
+
+ napi_status ret;
+ size_t argc = 3;
+ napi_value args[3] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeDeferredComponentInstallFailure napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t loadingUnitId;
+ ret = napi_get_value_int64(env, args[0], &loadingUnitId);
+ if (ret != napi_ok) {
+ LOGE("nativeDeferredComponentInstallFailure napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD(
+ "PlatformViewOHOSNapi::nativeSetAccessibilityFeatures loadingUnitId: "
+ "%{public}ld",
+ loadingUnitId);
+ std::string error;
+ if (fml::napi::SUCCESS != fml::napi::GetString(env, args[1], error)) {
+ LOGE(
+ "nativeDeferredComponentInstallFailure napi_get_value_string_utf8 "
+ "error");
+ return nullptr;
+ }
+ LOGD("nativeSetAccessibilityFeatures loadingUnitId: %s", error.c_str());
+
+ bool isTransient;
+ ret = napi_get_value_bool(env, args[2], &isTransient);
+ if (ret != napi_ok) {
+ LOGE("nativeDeferredComponentInstallFailure napi_get_value_bool error");
+ return nullptr;
+ }
+ LOGD("nativeSetAccessibilityFeatures loadingUnitId: %{public}d", isTransient);
+
+ LoadLoadingUnitFailure(static_cast(loadingUnitId),
+ std::string(error), static_cast(isTransient));
+
+ return nullptr;
+}
+
+/**
+ * 应用低内存警告
+ */
+napi_value PlatformViewOHOSNapi::nativeNotifyLowMemoryWarning(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeNotifyLowMemoryWarning");
+
+ napi_status ret;
+ size_t argc = 1;
+ napi_value args[1] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeNotifyLowMemoryWarning napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t shell_holder;
+ ret = napi_get_value_int64(env, args[0], &shell_holder);
+ if (ret != napi_ok) {
+ LOGE("nativeNotifyLowMemoryWarning napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeNotifyLowMemoryWarning shell_holder: %{public}ld", shell_holder);
+ OHOS_SHELL_HOLDER->NotifyLowMemoryWarning();
+
+ return nullptr;
+}
+
+// 下面的方法,从键盘输入中判断当前字符是否是emoji
+
+/**
+ *
+ */
+napi_value PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmoji(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmoji");
+ napi_status ret;
+ size_t argc = 1;
+ napi_value args[1] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsEmoji napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t codePoint;
+ ret = napi_get_value_int64(env, args[0], &codePoint);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsEmoji napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeFlutterTextUtilsIsEmoji codePoint: %{public}ld ", codePoint);
+
+ bool value = u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI);
+ napi_value result = nullptr;
+ ret = napi_get_boolean(env, value, &result);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsEmoji napi_get_boolean error");
+ return nullptr;
+ }
+
+ return result;
+}
+
+/**
+ *
+ */
+napi_value PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmojiModifier(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmojiModifier");
+
+ napi_status ret;
+ size_t argc = 1;
+ napi_value args[1] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsEmojiModifier napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t codePoint;
+ ret = napi_get_value_int64(env, args[0], &codePoint);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsEmojiModifier napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeFlutterTextUtilsIsEmojiModifier codePoint: %{public}ld ",
+ codePoint);
+
+ bool value = u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI_MODIFIER);
+ napi_value result = nullptr;
+ ret = napi_get_boolean(env, value, &result);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsEmojiModifier napi_get_boolean error");
+ return nullptr;
+ }
+
+ return result;
+}
+
+/**
+ *
+ */
+napi_value PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmojiModifierBase(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeFlutterTextUtilsIsEmojiModifierBase");
+
+ napi_status ret;
+ size_t argc = 1;
+ napi_value args[1] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsEmojiModifierBase napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t codePoint;
+ ret = napi_get_value_int64(env, args[0], &codePoint);
+ if (ret != napi_ok) {
+ LOGE(
+ "nativeFlutterTextUtilsIsEmojiModifierBase napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeFlutterTextUtilsIsEmojiModifierBase codePoint: %{public}ld ",
+ codePoint);
+
+ bool value =
+ u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI_MODIFIER_BASE);
+ napi_value result = nullptr;
+ ret = napi_get_boolean(env, value, &result);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsEmojiModifierBase napi_get_boolean error");
+ return nullptr;
+ }
+
+ return result;
+}
+
+/**
+ *
+ */
+napi_value PlatformViewOHOSNapi::nativeFlutterTextUtilsIsVariationSelector(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeFlutterTextUtilsIsVariationSelector");
+
+ napi_status ret;
+ size_t argc = 1;
+ napi_value args[1] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsVariationSelector napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t codePoint;
+ ret = napi_get_value_int64(env, args[0], &codePoint);
+ if (ret != napi_ok) {
+ LOGE(
+ "nativeFlutterTextUtilsIsVariationSelector napi_get_value_int64 error");
+ return nullptr;
+ }
+ LOGD("nativeFlutterTextUtilsIsVariationSelector codePoint: %{public}ld ",
+ codePoint);
+
+ bool value =
+ u_hasBinaryProperty(codePoint, UProperty::UCHAR_VARIATION_SELECTOR);
+ napi_value result = nullptr;
+ ret = napi_get_boolean(env, value, &result);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsVariationSelector napi_get_boolean error");
+ return nullptr;
+ }
+
+ return result;
+}
+
+/**
+ *
+ */
+napi_value PlatformViewOHOSNapi::nativeFlutterTextUtilsIsRegionalIndicator(
+ napi_env env,
+ napi_callback_info info) {
+ LOGD("PlatformViewOHOSNapi::nativeFlutterTextUtilsIsRegionalIndicator");
+
+ napi_status ret;
+ size_t argc = 1;
+ napi_value args[1] = {nullptr};
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsRegionalIndicator napi_get_cb_info error");
+ return nullptr;
+ }
+
+ int64_t codePoint;
+ ret = napi_get_value_int64(env, args[0], &codePoint);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsRegionalIndicator napi_get_value_int64 fail");
+ return nullptr;
+ }
+ LOGD("nativeFlutterTextUtilsIsRegionalIndicator codePoint: %{public}ld ",
+ codePoint);
+
+ bool value =
+ u_hasBinaryProperty(codePoint, UProperty::UCHAR_REGIONAL_INDICATOR);
+ napi_value result = nullptr;
+ ret = napi_get_boolean(env, value, &result);
+ if (ret != napi_ok) {
+ LOGE("nativeFlutterTextUtilsIsRegionalIndicator napi_get_boolean error");
+ return nullptr;
+ }
+
+ return result;
+}
+
+/**
+ * @brief ArkTS下发系统语言设置列表
+ * @note
+ * @param nativeShellHolderId: number
+ * @param systemLanguages: Array
+ * @return void
+ */
+napi_value PlatformViewOHOSNapi::nativeGetSystemLanguages(
+ napi_env env,
+ napi_callback_info info) {
+ napi_status ret;
+ size_t argc = 2;
+ napi_value args[2] = {nullptr};
+ int64_t shell_holder;
+ std::vector local_languages;
+ ret = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
+ if (ret != napi_ok) {
+ FML_DLOG(ERROR) << "nativeGetSystemLanguages napi_get_cb_info error:"
+ << ret;
+ return nullptr;
+ }
+ ret = napi_get_value_int64(env, args[0], &shell_holder);
+ if (ret != napi_ok) {
+ FML_DLOG(ERROR) << "nativeGetSystemLanguages napi_get_value_int64 error";
+ return nullptr;
+ }
+ if (fml::napi::SUCCESS !=
+ fml::napi::GetArrayString(env, args[1], local_languages)) {
+ FML_DLOG(ERROR) << "nativeGetSystemLanguages GetArrayString error";
+ return nullptr;
+ }
+ system_languages = local_languages;
+ return nullptr;
+}
+
+int64_t PlatformViewOHOSNapi::GetShellHolder() {
+ return PlatformViewOHOSNapi::shell_holder;
+}
+
+void PlatformViewOHOSNapi::SurfaceCreated(int64_t shell_holder, void* window) {
+ auto native_window = fml::MakeRefCounted(
+ static_cast(window));
+ OHOS_SHELL_HOLDER->GetPlatformView()->NotifyCreate(std::move(native_window));
+}
+
+void PlatformViewOHOSNapi::SurfaceChanged(int64_t shell_holder,
+ int32_t width,
+ int32_t height) {
+ OHOS_SHELL_HOLDER->GetPlatformView()->NotifyChanged(
+ SkISize::Make(width, height));
+}
+
+void PlatformViewOHOSNapi::SurfaceDestroyed(int64_t shell_holder) {
+ OHOS_SHELL_HOLDER->GetPlatformView()->NotifyDestroyed();
+}
+
+void PlatformViewOHOSNapi::SetPlatformTaskRunner(
+ fml::RefPtr platform_task_runner) {
+ platform_task_runner_ = platform_task_runner;
+}
+
+} // namespace flutter
diff --git a/shell/platform/ohos/napi/platform_view_ohos_napi.h b/shell/platform/ohos/napi/platform_view_ohos_napi.h
new file mode 100644
index 0000000000000000000000000000000000000000..8e698dc6e57f70335e85e85e5e3409f7b0338d9a
--- /dev/null
+++ b/shell/platform/ohos/napi/platform_view_ohos_napi.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PLATFORM_VIEW_OHOS_NAPI_H
+#define PLATFORM_VIEW_OHOS_NAPI_H
+#include
+#include "../napi_common.h"
+#include "flutter/assets/directory_asset_bundle.h"
+#include "flutter/common/settings.h"
+#include "flutter/fml/file.h"
+#include "flutter/fml/logging.h"
+#include "flutter/fml/mapping.h"
+#include "flutter/fml/native_library.h"
+#include "flutter/fml/size.h"
+#include "flutter/lib/ui/plugins/callback_cache.h"
+#include "flutter/runtime/dart_service_isolate.h"
+#include "flutter/shell/common/run_configuration.h"
+#include "napi/native_api.h"
+// class for all c++ to call js function
+namespace flutter {
+
+struct locale {
+ std::string language;
+ std::string script;
+ std::string region;
+};
+
+class PlatformViewOHOSNapi {
+ public:
+ static napi_value nativeDispatchEmptyPlatformMessage(
+ napi_env env,
+ napi_callback_info info); // 发送一个空的PlatformMessage
+ static napi_value nativeDispatchPlatformMessage(
+ napi_env env,
+ napi_callback_info info); // 发送一个PlatformMessage
+ static napi_value nativeInvokePlatformMessageEmptyResponseCallback(
+ napi_env env,
+ napi_callback_info info); // 空的PlatformMessage响应回调
+ static napi_value nativeInvokePlatformMessageResponseCallback(
+ napi_env env,
+ napi_callback_info info);
+
+ explicit PlatformViewOHOSNapi(napi_env env);
+ void SetPlatformTaskRunner(fml::RefPtr platform_task_runner);
+ void FlutterViewHandlePlatformMessageResponse(
+ int reponse_id,
+ std::unique_ptr data);
+ void FlutterViewHandlePlatformMessage(
+ int reponse_id,
+ std::unique_ptr message);
+
+ void FlutterViewOnFirstFrame();
+ void FlutterViewOnPreEngineRestart();
+ flutter::locale resolveNativeLocale(
+ std::vector supportedLocales);
+ std::unique_ptr>
+ FlutterViewComputePlatformResolvedLocales(
+ const std::vector& support_locale_data);
+ void DecodeImage(int64_t imageGeneratorAddress,
+ void* inputData,
+ size_t dataSize);
+
+ static napi_value nativeUpdateRefreshRate(
+ napi_env env,
+ napi_callback_info info); // 设置刷新率
+ static napi_value nativeRunBundleAndSnapshotFromLibrary(
+ napi_env env,
+ napi_callback_info info); // 加载dart工程构建产物
+ static napi_value nativePrefetchDefaultFontManager(
+ napi_env env,
+ napi_callback_info
+ info); // 初始化SkFontMgr::RefDefault(),skia引擎文字管理初始化
+ static napi_value nativeGetIsSoftwareRenderingEnabled(
+ napi_env env,
+ napi_callback_info info); // 返回是否支持软件绘制
+
+ static napi_value nativeAttach(
+ napi_env env,
+ napi_callback_info
+ info); // attach flutterNapi实例给到 native
+ // engine,这个支持rkts到flutter平台的无关引擎之间的通信
+ // attach只需要执行一次
+ static napi_value nativeSpawn(
+ napi_env env,
+ napi_callback_info info); // 从当前的flutterNapi复制一个新的实例
+ static napi_value nativeDestroy(
+ napi_env env,
+ napi_callback_info info); // Detaches flutterNapi和engine之间的关联
+ static napi_value nativeSetViewportMetrics(
+ napi_env env,
+ napi_callback_info info); // 把物理屏幕参数通知到native
+ static napi_value nativeSetAccessibilityFeatures(
+ napi_env env,
+ napi_callback_info info); // 设置能力参数
+
+ static napi_value nativeCleanupMessageData(
+ napi_env env,
+ napi_callback_info info); // 清除某个messageData
+ static napi_value nativeLoadDartDeferredLibrary(
+ napi_env env,
+ napi_callback_info info); // load一个合法的.so文件到dart vm
+ static napi_value nativeUpdateOhosAssetManager(
+ napi_env env,
+ napi_callback_info info); // 设置ResourceManager和assetBundlePath到engine
+ static napi_value nativeDeferredComponentInstallFailure(
+ napi_env env,
+ napi_callback_info info); // 加载动态库,或者dart库失败时的通知
+ static napi_value nativeGetPixelMap(
+ napi_env env,
+ napi_callback_info info); // 从engine获取当前绘制pixelMap
+ static napi_value nativeNotifyLowMemoryWarning(
+ napi_env env,
+ napi_callback_info info); // 应用低内存警告
+
+ // 下面的方法,从键盘输入中判断当前字符是否是emoji,实现优先级低
+ static napi_value nativeFlutterTextUtilsIsEmoji(napi_env env,
+ napi_callback_info info);
+ static napi_value nativeFlutterTextUtilsIsEmojiModifier(
+ napi_env env,
+ napi_callback_info info);
+ static napi_value nativeFlutterTextUtilsIsEmojiModifierBase(
+ napi_env env,
+ napi_callback_info info);
+ static napi_value nativeFlutterTextUtilsIsVariationSelector(
+ napi_env env,
+ napi_callback_info info);
+ static napi_value nativeFlutterTextUtilsIsRegionalIndicator(
+ napi_env env,
+ napi_callback_info info);
+ static napi_value nativeGetSystemLanguages(
+ napi_env env,
+ napi_callback_info info); // 应用下发系统语言设置
+
+ // Surface相关,XComponent调用
+ static void SurfaceCreated(int64_t shell_holder, void* window);
+ static void SurfaceChanged(int64_t shell_holder,
+ int32_t width,
+ int32_t height);
+ static void SurfaceDestroyed(int64_t shell_holder);
+ static int64_t GetShellHolder();
+
+ private:
+ static napi_env env_;
+ static napi_ref ref_napi_obj_;
+ static int64_t shell_holder;
+ static std::vector system_languages;
+ fml::RefPtr platform_task_runner_;
+};
+
+} // namespace flutter
+#endif
diff --git a/shell/platform/ohos/napi_common.h b/shell/platform/ohos/napi_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..1783f071818ed634ea98f148a14dbf68a47209ea
--- /dev/null
+++ b/shell/platform/ohos/napi_common.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// Created on 2023/6/17.
+//
+// Node APIs are not fully supported. To solve the compilation error of the
+// interface cannot be found, please include "napi/native_api.h".
+
+#ifndef XComponentDemo_native_common_H
+#define XComponentDemo_native_common_H
+
+#include
+#define APP_LOG_DOMAIN 0x0000
+#define APP_LOG_TAG "XComFlutterOHOS_Native"
+#define LOGI(...) \
+ ((void)OH_LOG_Print(LOG_APP, LOG_INFO, APP_LOG_DOMAIN, APP_LOG_TAG, \
+ __VA_ARGS__))
+// #define LOGD(...) ((void)OH_LOG_Print(LOG_APP, LOG_DEBUG, APP_LOG_DOMAIN,
+// APP_LOG_TAG, __VA_ARGS__))
+#define LOGD(...) \
+ ((void)OH_LOG_Print(LOG_APP, LOG_INFO, APP_LOG_DOMAIN, APP_LOG_TAG, \
+ __VA_ARGS__))
+#define LOGW(...) \
+ ((void)OH_LOG_Print(LOG_APP, LOG_WARN, APP_LOG_DOMAIN, APP_LOG_TAG, \
+ __VA_ARGS__))
+#define LOGE(...) \
+ ((void)OH_LOG_Print(LOG_APP, LOG_ERROR, APP_LOG_DOMAIN, APP_LOG_TAG, \
+ __VA_ARGS__))
+
+#define NAPI_RETVAL_NOTHING
+
+#define GET_AND_THROW_LAST_ERROR(env) \
+ do { \
+ const napi_extended_error_info* errorInfo = nullptr; \
+ napi_get_last_error_info((env), &errorInfo); \
+ bool isPending = false; \
+ napi_is_exception_pending((env), &isPending); \
+ if (!isPending && errorInfo != nullptr) { \
+ const char* errorMessage = errorInfo->error_message != nullptr \
+ ? errorInfo->error_message \
+ : "empty error message"; \
+ napi_throw_error((env), nullptr, errorMessage); \
+ } \
+ } while (0)
+
+#define NAPI_ASSERT_BASE(env, assertion, message, retVal) \
+ do { \
+ if (!(assertion)) { \
+ napi_throw_error((env), nullptr, \
+ "assertion (" #assertion ") failed: " message); \
+ return retVal; \
+ } \
+ } while (0)
+
+#define NAPI_ASSERT(env, assertion, message) \
+ NAPI_ASSERT_BASE(env, assertion, message, nullptr)
+
+#define NAPI_ASSERT_RETURN_VOID(env, assertion, message) \
+ NAPI_ASSERT_BASE(env, assertion, message, NAPI_RETVAL_NOTHING)
+
+#define NAPI_CALL_BASE(env, theCall, retVal) \
+ do { \
+ if ((theCall) != napi_ok) { \
+ GET_AND_THROW_LAST_ERROR((env)); \
+ return retVal; \
+ } \
+ } while (0)
+
+#define NAPI_CALL(env, theCall) NAPI_CALL_BASE(env, theCall, nullptr)
+
+#define NAPI_CALL_RETURN_VOID(env, theCall) \
+ NAPI_CALL_BASE(env, theCall, NAPI_RETVAL_NOTHING)
+
+#define DECLARE_NAPI_PROPERTY(name, val) \
+ { (name), nullptr, nullptr, nullptr, nullptr, val, napi_default, nullptr }
+
+#define DECLARE_NAPI_STATIC_PROPERTY(name, val) \
+ { (name), nullptr, nullptr, nullptr, nullptr, val, napi_static, nullptr }
+
+#define DECLARE_NAPI_FUNCTION(name, func) \
+ { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr }
+
+#define DECLARE_NAPI_FUNCTION_WITH_DATA(name, func, data) \
+ { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, data }
+
+#define DECLARE_NAPI_STATIC_FUNCTION(name, func) \
+ { (name), nullptr, (func), nullptr, nullptr, nullptr, napi_static, nullptr }
+
+#define DECLARE_NAPI_GETTER(name, getter) \
+ { \
+ (name), nullptr, nullptr, (getter), nullptr, nullptr, napi_default, \
+ nullptr \
+ }
+
+#define DECLARE_NAPI_SETTER(name, setter) \
+ { \
+ (name), nullptr, nullptr, nullptr, (setter), nullptr, napi_default, \
+ nullptr \
+ }
+
+#define DECLARE_NAPI_GETTER_SETTER(name, getter, setter) \
+ { \
+ (name), nullptr, nullptr, (getter), (setter), nullptr, napi_default, \
+ nullptr \
+ }
+
+#endif // XComponentDemo_native_common_H
diff --git a/shell/platform/ohos/ohos_asset_provider.cpp b/shell/platform/ohos/ohos_asset_provider.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..8cabce185ea2bd5b0ca89114493b473a11160a06
--- /dev/null
+++ b/shell/platform/ohos/ohos_asset_provider.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ohos_asset_provider.h"
+#include
+#include
+#include "napi_common.h"
+
+namespace flutter {
+
+class FileDescriptionMapping : public fml::Mapping {
+ public:
+ explicit FileDescriptionMapping(RawFile* fileHandle)
+ : fileHandle_(fileHandle), filebuf(nullptr), _read_from_file(false) {
+ LOGD("FileDescriptionMapping :%{public}p", fileHandle_);
+ int ret = 0;
+ if (0 > (ret = ReadFile())) {
+ LOGD("FileDescriptionMapping :%{public}d", ret);
+ }
+ }
+ void* GetBuffer() {
+ // TODO 考虑线程安全
+
+ if (filebuf != nullptr)
+ return filebuf;
+
+ size_t bufLenth = GetSize();
+
+ if (fileHandle_ != nullptr && bufLenth > 0) {
+ LOGD("FileDescriptionMapping buflenth = %{public}ld", bufLenth);
+ filebuf = malloc(bufLenth + 1);
+ memset(filebuf, 0, bufLenth + 1);
+ }
+ return filebuf;
+ }
+
+ ~FileDescriptionMapping() override {
+ if (fileHandle_ != nullptr) {
+ OH_ResourceManager_CloseRawFile(fileHandle_);
+ }
+ if (filebuf != nullptr) {
+ free(filebuf);
+ filebuf = nullptr;
+ }
+ }
+
+ size_t GetSize() const override {
+ if (fileHandle_ == nullptr)
+ return 0;
+
+ size_t ret = OH_ResourceManager_GetRawFileSize(fileHandle_);
+ LOGD("GetSize():%{public}zu", ret);
+ return ret;
+ }
+
+ int ReadFile() {
+ if (fileHandle_ == nullptr) {
+ LOGE("GetMapping failed. fileHandle_:%{public}p,filebuf:%{public}p",
+ fileHandle_, filebuf);
+ return -1;
+ }
+
+ size_t len = GetSize();
+ void* buf = GetBuffer();
+ int ret = 0;
+
+ if (buf != nullptr) {
+ ret = OH_ResourceManager_ReadRawFile(fileHandle_, buf, len);
+ _read_from_file = true;
+ }
+ LOGD("GetMapping ... total:%{public}zu, ret:%{public}d,buf:%{public}p", len,
+ ret, buf);
+ return ret;
+ }
+ const uint8_t* GetMapping() const override {
+ return reinterpret_cast(filebuf);
+ }
+
+ bool IsDontNeedSafe() const override {
+ // thread unsafe
+ return false;
+ }
+
+ private:
+ RawFile* fileHandle_;
+ void* filebuf;
+ bool _read_from_file;
+ FML_DISALLOW_COPY_AND_ASSIGN(FileDescriptionMapping);
+};
+
+OHOSAssetProvider::OHOSAssetProvider(void* assetHandle, const std::string& dir)
+ : assetHandle_(assetHandle), dir_(dir) {
+ LOGD("assets dir:%{public}s", dir.c_str());
+}
+
+bool OHOSAssetProvider::IsValid() const {
+ return (assetHandle_ != nullptr);
+}
+
+bool OHOSAssetProvider::IsValidAfterAssetManagerChange() const {
+ return true;
+}
+
+AssetResolver::AssetResolverType OHOSAssetProvider::GetType() const {
+ return AssetResolver::AssetResolverType::kApkAssetProvider;
+}
+
+std::unique_ptr OHOSAssetProvider::GetAsMapping(
+ const std::string& asset_name) const {
+ NativeResourceManager* nativeResMgr =
+ reinterpret_cast(assetHandle_);
+ if (assetHandle_ == nullptr || nativeResMgr == nullptr) {
+ LOGE("nativeResMgr is null:%{public}p or nativeResMgr is null:%{public}p ",
+ assetHandle_, nativeResMgr);
+ }
+ std::string relativePath = dir_ + "/" + asset_name;
+
+ LOGE("GetAsMapping=%{public}s->%{public}s", asset_name.c_str(),
+ relativePath.c_str());
+
+ RawFile* fileHandle =
+ OH_ResourceManager_OpenRawFile(nativeResMgr, relativePath.c_str());
+ LOGE("GetAsMapping=%{public}s->%{public}p", relativePath.c_str(), fileHandle);
+
+ if (fileHandle == nullptr) {
+ fileHandle =
+ OH_ResourceManager_OpenRawFile(nativeResMgr, asset_name.c_str());
+ LOGE("GetAsMapping2 ..fallback:%{public}s->%{public}p", asset_name.c_str(),
+ fileHandle);
+ }
+ LOGE("GetAsMappingend:%{public}p", fileHandle);
+ return fileHandle == nullptr
+ ? nullptr
+ : (std::make_unique(fileHandle));
+}
+
+std::unique_ptr OHOSAssetProvider::Clone() const {
+ return std::make_unique(assetHandle_);
+}
+
+} // namespace flutter
diff --git a/shell/platform/ohos/ohos_asset_provider.h b/shell/platform/ohos/ohos_asset_provider.h
new file mode 100755
index 0000000000000000000000000000000000000000..666aeb69b66cedb6e7859821efeb6c9fec59965a
--- /dev/null
+++ b/shell/platform/ohos/ohos_asset_provider.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OHOS_ASSET_PROVIDER_H
+#define OHOS_ASSET_PROVIDER_H
+
+#include "flutter/assets/asset_resolver.h"
+#include "flutter/fml/memory/ref_counted.h"
+
+namespace flutter {
+
+// ohos平台的文件管理 ,必须通过NativeResourceManager* 指针对它进行初始化
+class OHOSAssetProvider final : public AssetResolver {
+ public:
+ explicit OHOSAssetProvider(void* assetHandle,
+ const std::string& dir = "flutter_assets");
+ ~OHOSAssetProvider() = default;
+
+ std::unique_ptr Clone() const;
+
+ private:
+ void* assetHandle_;
+ std::string dir_;
+
+ bool IsValid() const override;
+
+ bool IsValidAfterAssetManagerChange() const override;
+
+ AssetResolver::AssetResolverType GetType() const override;
+
+ std::unique_ptr GetAsMapping(
+ const std::string& asset_name) const override;
+};
+} // namespace flutter
+#endif
\ No newline at end of file
diff --git a/shell/platform/ohos/ohos_context_gl_impeller.cpp b/shell/platform/ohos/ohos_context_gl_impeller.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..1610073bb8364a0d9f55134dd5be5de8a85770d7
--- /dev/null
+++ b/shell/platform/ohos/ohos_context_gl_impeller.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ohos_context_gl_impeller.h"
+
+namespace flutter {
+
+OHOSContextGLImpeller::OHOSContextGLImpeller()
+ : OHOSContext(OHOSRenderingAPI::kOpenGLES) {}
+
+OHOSContextGLImpeller::~OHOSContextGLImpeller() {}
+
+bool OHOSContextGLImpeller::IsValid() const {
+ return true;
+}
+
+} // namespace flutter
\ No newline at end of file
diff --git a/shell/platform/ohos/ohos_context_gl_impeller.h b/shell/platform/ohos/ohos_context_gl_impeller.h
new file mode 100755
index 0000000000000000000000000000000000000000..3947b457d1452d90ac8ae87b100f91e4dc92047e
--- /dev/null
+++ b/shell/platform/ohos/ohos_context_gl_impeller.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OHOS_CONTEXT_GL_IMPELLER_H
+#define OHOS_CONTEXT_GL_IMPELLER_H
+#include "context/ohos_context.h"
+#include "flutter/fml/macros.h"
+
+namespace flutter {
+class OHOSContextGLImpeller : public OHOSContext {
+ public:
+ OHOSContextGLImpeller();
+
+ ~OHOSContextGLImpeller();
+
+ bool IsValid() const override;
+
+ private:
+ FML_DISALLOW_COPY_AND_ASSIGN(OHOSContextGLImpeller);
+};
+} // namespace flutter
+#endif
\ No newline at end of file
diff --git a/shell/platform/ohos/ohos_context_gl_skia.cpp b/shell/platform/ohos/ohos_context_gl_skia.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..2dbd1a971833dc6f5d6d5bbd3ab90b921c1dfe96
--- /dev/null
+++ b/shell/platform/ohos/ohos_context_gl_skia.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flutter/shell/platform/ohos/ohos_context_gl_skia.h"
+
+#include
+
+#include "flutter/fml/trace_event.h"
+#include "flutter/shell/platform/ohos/ohos_egl_surface.h"
+
+namespace flutter {
+
+template
+using EGLResult = std::pair;
+
+static EGLResult CreateContext(EGLDisplay display,
+ EGLConfig config,
+ EGLContext share = EGL_NO_CONTEXT) {
+ EGLint attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+
+ EGLContext context = eglCreateContext(display, config, share, attributes);
+
+ return {context != EGL_NO_CONTEXT, context};
+}
+
+static EGLResult ChooseEGLConfiguration(EGLDisplay display,
+ uint8_t msaa_samples) {
+ EGLint sample_buffers = msaa_samples > 1 ? 1 : 0;
+ EGLint attributes[] = {
+ // clang-format off
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 0,
+ EGL_STENCIL_SIZE, 0,
+ EGL_SAMPLES, static_cast(msaa_samples),
+ EGL_SAMPLE_BUFFERS, sample_buffers,
+ EGL_NONE, // termination sentinel
+ // clang-format on
+ };
+
+ EGLint config_count = 0;
+ EGLConfig egl_config = nullptr;
+
+ if (eglChooseConfig(display, attributes, &egl_config, 1, &config_count) !=
+ EGL_TRUE) {
+ return {false, nullptr};
+ }
+
+ bool success = config_count > 0 && egl_config != nullptr;
+
+ return {success, success ? egl_config : nullptr};
+}
+
+static bool TeardownContext(EGLDisplay display, EGLContext context) {
+ if (context != EGL_NO_CONTEXT) {
+ return eglDestroyContext(display, context) == EGL_TRUE;
+ }
+
+ return true;
+}
+
+OhosContextGLSkia::OhosContextGLSkia(OHOSRenderingAPI rendering_api,
+ fml::RefPtr environment,
+ const TaskRunners& task_runners,
+ uint8_t msaa_samples)
+ : OHOSContext(OHOSRenderingAPI::kOpenGLES),
+ environment_(std::move(environment)),
+ config_(nullptr),
+ task_runners_(task_runners) {
+ if (!environment_->IsValid()) {
+ FML_LOG(ERROR) << "Could not create an Ohos GL environment.";
+ return;
+ }
+
+ bool success = false;
+
+ // Choose a valid configuration.
+ std::tie(success, config_) =
+ ChooseEGLConfiguration(environment_->Display(), msaa_samples);
+ if (!success) {
+ FML_LOG(ERROR) << "Could not choose an EGL configuration.";
+ LogLastEGLError();
+ return;
+ }
+
+ // Create a context for the configuration.
+ std::tie(success, context_) =
+ CreateContext(environment_->Display(), config_, EGL_NO_CONTEXT);
+ if (!success) {
+ FML_LOG(ERROR) << "Could not create an EGL context";
+ LogLastEGLError();
+ return;
+ }
+
+ std::tie(success, resource_context_) =
+ CreateContext(environment_->Display(), config_, context_);
+ if (!success) {
+ FML_LOG(ERROR) << "Could not create an EGL resource context";
+ LogLastEGLError();
+ return;
+ }
+
+ // All done!
+ valid_ = true;
+}
+
+OhosContextGLSkia::~OhosContextGLSkia() {
+ FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
+ sk_sp main_context = GetMainSkiaContext();
+ SetMainSkiaContext(nullptr);
+ fml::AutoResetWaitableEvent latch;
+ // This context needs to be deallocated from the raster thread in order to
+ // keep a coherent usage of egl from a single thread.
+ fml::TaskRunner::RunNowOrPostTask(task_runners_.GetRasterTaskRunner(), [&] {
+ if (main_context) {
+ std::unique_ptr pbuffer_surface = CreatePbufferSurface();
+ auto status = pbuffer_surface->MakeCurrent();
+ if (status != OhosEGLSurfaceMakeCurrentStatus::kFailure) {
+ main_context->releaseResourcesAndAbandonContext();
+ main_context.reset();
+ ClearCurrent();
+ }
+ }
+ latch.Signal();
+ });
+ latch.Wait();
+
+ if (!TeardownContext(environment_->Display(), context_)) {
+ FML_LOG(ERROR)
+ << "Could not tear down the EGL context. Possible resource leak.";
+ LogLastEGLError();
+ }
+
+ if (!TeardownContext(environment_->Display(), resource_context_)) {
+ FML_LOG(ERROR) << "Could not tear down the EGL resource context. Possible "
+ "resource leak.";
+ LogLastEGLError();
+ }
+}
+
+std::unique_ptr OhosContextGLSkia::CreateOnscreenSurface(
+ const fml::RefPtr& window) const {
+ if (window->IsFakeWindow()) {
+ return CreatePbufferSurface();
+ } else {
+ EGLDisplay display = environment_->Display();
+
+ const EGLint attribs[] = {EGL_NONE};
+
+ EGLSurface surface = eglCreateWindowSurface(
+ display, config_,
+ reinterpret_cast(window->handle()), attribs);
+ return std::make_unique(surface, display, context_);
+ }
+}
+
+std::unique_ptr OhosContextGLSkia::CreateOffscreenSurface()
+ const {
+ // We only ever create pbuffer surfaces for background resource loading
+ // contexts. We never bind the pbuffer to anything.
+ FML_LOG(INFO) << "CreateOffscreenSurface 1";
+ if (environment_) {
+ FML_LOG(INFO) << "CreateOffscreenSurface environment_ ";
+ } else {
+ FML_LOG(INFO) << "CreateOffscreenSurface environment_ nullptr";
+ }
+
+ EGLDisplay display = environment_->Display();
+
+ const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
+ FML_LOG(INFO) << "CreateOffscreenSurface 2";
+ EGLSurface surface = eglCreatePbufferSurface(display, config_, attribs);
+ FML_LOG(INFO) << "CreateOffscreenSurface 3";
+ return std::make_unique(surface, display, resource_context_);
+}
+
+std::unique_ptr OhosContextGLSkia::CreatePbufferSurface()
+ const {
+ EGLDisplay display = environment_->Display();
+
+ const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
+
+ EGLSurface surface = eglCreatePbufferSurface(display, config_, attribs);
+ return std::make_unique(surface, display, context_);
+}
+
+fml::RefPtr OhosContextGLSkia::Environment() const {
+ return environment_;
+}
+
+bool OhosContextGLSkia::IsValid() const {
+ return valid_;
+}
+
+bool OhosContextGLSkia::ClearCurrent() const {
+ if (eglGetCurrentContext() != context_) {
+ return true;
+ }
+ if (eglMakeCurrent(environment_->Display(), EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT) != EGL_TRUE) {
+ FML_LOG(ERROR) << "Could not clear the current context";
+ LogLastEGLError();
+ return false;
+ }
+ return true;
+}
+
+EGLContext OhosContextGLSkia::CreateNewContext() const {
+ bool success;
+ EGLContext context;
+ std::tie(success, context) =
+ CreateContext(environment_->Display(), config_, EGL_NO_CONTEXT);
+ return success ? context : EGL_NO_CONTEXT;
+}
+
+} // namespace flutter
diff --git a/shell/platform/ohos/ohos_context_gl_skia.h b/shell/platform/ohos/ohos_context_gl_skia.h
new file mode 100755
index 0000000000000000000000000000000000000000..c30a24da87310f8b2e02f62c53de08875e1152d6
--- /dev/null
+++ b/shell/platform/ohos/ohos_context_gl_skia.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_SKIA_H_
+#define FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_SKIA_H_
+
+#include "flutter/fml/macros.h"
+#include "flutter/fml/memory/ref_counted.h"
+#include "flutter/fml/memory/ref_ptr.h"
+#include "flutter/shell/common/platform_view.h"
+#include "flutter/shell/platform/ohos/context/ohos_context.h"
+#include "flutter/shell/platform/ohos/ohos_environment_gl.h"
+#include "flutter/shell/platform/ohos/surface/ohos_native_window.h"
+#include "third_party/skia/include/core/SkSize.h"
+
+namespace flutter {
+
+class OhosEGLSurface;
+
+//------------------------------------------------------------------------------
+/// The Ohos context is used by `OhosSurfaceGL` to create and manage
+/// EGL surfaces.
+///
+/// This context binds `EGLContext` to the current rendering thread and to the
+/// draw and read `EGLSurface`s.
+///
+class OhosContextGLSkia : public OHOSContext {
+ public:
+ OhosContextGLSkia(OHOSRenderingAPI rendering_api,
+ fml::RefPtr environment,
+ const TaskRunners& taskRunners,
+ uint8_t msaa_samples);
+
+ ~OhosContextGLSkia();
+
+ //----------------------------------------------------------------------------
+ /// @brief Allocates an new EGL window surface that is used for on-screen
+ /// pixels.
+ ///
+ /// @return The window surface.
+ ///
+ std::unique_ptr CreateOnscreenSurface(
+ const fml::RefPtr& window) const;
+
+ //----------------------------------------------------------------------------
+ /// @brief Allocates an 1x1 pbuffer surface that is used for making the
+ /// offscreen current for texture uploads.
+ ///
+ /// @return The pbuffer surface.
+ ///
+ std::unique_ptr CreateOffscreenSurface() const;
+
+ //----------------------------------------------------------------------------
+ /// @brief Allocates an 1x1 pbuffer surface that is used for making the
+ /// onscreen context current for snapshotting.
+ ///
+ /// @return The pbuffer surface.
+ ///
+ std::unique_ptr CreatePbufferSurface() const;
+
+ //----------------------------------------------------------------------------
+ /// @return The Ohos environment that contains a reference to the
+ /// display.
+ ///
+ fml::RefPtr Environment() const;
+
+ //----------------------------------------------------------------------------
+ /// @return Whether the current context is valid. That is, if the EGL
+ /// contexts were successfully created.
+ ///
+ bool IsValid() const override;
+
+ //----------------------------------------------------------------------------
+ /// @return Whether the current context was successfully clear.
+ ///
+ bool ClearCurrent() const;
+
+ //----------------------------------------------------------------------------
+ /// @brief Create a new EGLContext using the same EGLConfig.
+ ///
+ /// @return The EGLContext.
+ ///
+ EGLContext CreateNewContext() const;
+
+ //----------------------------------------------------------------------------
+ /// @brief The EGLConfig for this context.
+ ///
+ EGLConfig Config() const { return config_; }
+
+ private:
+ fml::RefPtr environment_;
+ EGLConfig config_;
+ EGLContext context_;
+ EGLContext resource_context_;
+ bool valid_ = false;
+ TaskRunners task_runners_;
+
+ FML_DISALLOW_COPY_AND_ASSIGN(OhosContextGLSkia);
+};
+
+} // namespace flutter
+
+#endif // FLUTTER_SHELL_PLATFORM_ANDROID_ANDROID_CONTEXT_GL_SKIA_H_
diff --git a/shell/platform/ohos/ohos_display.cpp b/shell/platform/ohos/ohos_display.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..32feddb2c3ad863179afd0be83d663c35a49b18e
--- /dev/null
+++ b/shell/platform/ohos/ohos_display.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flutter/shell/platform/ohos/ohos_display.h"
+
+namespace flutter {
+
+const double defaultFPS = 60;
+
+OHOSDisplay::OHOSDisplay(std::shared_ptr napi_facade)
+ : Display(60), napi_facade_(std::move(napi_facade)) {}
+
+double OHOSDisplay::GetRefreshRate() const {
+ return defaultFPS;
+}
+
+} // namespace flutter
\ No newline at end of file
diff --git a/shell/platform/ohos/ohos_display.h b/shell/platform/ohos/ohos_display.h
new file mode 100644
index 0000000000000000000000000000000000000000..873f2cff90e15467199eda7890a68b7c66229b62
--- /dev/null
+++ b/shell/platform/ohos/ohos_display.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OHOS_DISPLAY_H
+#define OHOS_DISPLAY_H
+
+#include
+
+#include "flutter/fml/macros.h"
+#include "flutter/shell/common/display.h"
+#include "flutter/shell/platform/ohos/napi/platform_view_ohos_napi.h"
+namespace flutter {
+
+class OHOSDisplay : public Display {
+ public:
+ explicit OHOSDisplay(std::shared_ptr napi_facade_);
+ ~OHOSDisplay() = default;
+
+ double GetRefreshRate() const override;
+
+ private:
+ std::shared_ptr napi_facade_;
+ FML_DISALLOW_COPY_AND_ASSIGN(OHOSDisplay);
+};
+} // namespace flutter
+#endif
\ No newline at end of file
diff --git a/shell/platform/ohos/ohos_egl_surface.cpp b/shell/platform/ohos/ohos_egl_surface.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..b416d1269fec3993de31982af9e70c868477c55c
--- /dev/null
+++ b/shell/platform/ohos/ohos_egl_surface.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flutter/shell/platform/ohos/ohos_egl_surface.h"
+
+#include
+
+#include
+#include
+
+#include "flutter/fml/trace_event.h"
+
+namespace flutter {
+
+void LogLastEGLError() {
+ struct EGLNameErrorPair {
+ const char* name;
+ EGLint code;
+ };
+
+#define _EGL_ERROR_DESC(a) \
+ { #a, a }
+
+ const EGLNameErrorPair pairs[] = {
+ _EGL_ERROR_DESC(EGL_SUCCESS),
+ _EGL_ERROR_DESC(EGL_NOT_INITIALIZED),
+ _EGL_ERROR_DESC(EGL_BAD_ACCESS),
+ _EGL_ERROR_DESC(EGL_BAD_ALLOC),
+ _EGL_ERROR_DESC(EGL_BAD_ATTRIBUTE),
+ _EGL_ERROR_DESC(EGL_BAD_CONTEXT),
+ _EGL_ERROR_DESC(EGL_BAD_CONFIG),
+ _EGL_ERROR_DESC(EGL_BAD_CURRENT_SURFACE),
+ _EGL_ERROR_DESC(EGL_BAD_DISPLAY),
+ _EGL_ERROR_DESC(EGL_BAD_SURFACE),
+ _EGL_ERROR_DESC(EGL_BAD_MATCH),
+ _EGL_ERROR_DESC(EGL_BAD_PARAMETER),
+ _EGL_ERROR_DESC(EGL_BAD_NATIVE_PIXMAP),
+ _EGL_ERROR_DESC(EGL_BAD_NATIVE_WINDOW),
+ _EGL_ERROR_DESC(EGL_CONTEXT_LOST),
+ };
+
+#undef _EGL_ERROR_DESC
+
+ const auto count = sizeof(pairs) / sizeof(EGLNameErrorPair);
+
+ EGLint last_error = eglGetError();
+
+ for (size_t i = 0; i < count; i++) {
+ if (last_error == pairs[i].code) {
+ FML_LOG(ERROR) << "EGL Error: " << pairs[i].name << " (" << pairs[i].code
+ << ")";
+ return;
+ }
+ }
+
+ FML_LOG(ERROR) << "Unknown EGL Error";
+}
+
+namespace {
+
+static bool HasExtension(const char* extensions, const char* name) {
+ const char* r = strstr(extensions, name);
+ auto len = strlen(name);
+ // check that the extension name is terminated by space or null terminator
+ return r != nullptr && (r[len] == ' ' || r[len] == 0);
+}
+
+} // namespace
+
+class OhosEGLSurfaceDamage {
+ public:
+ void init(EGLDisplay display, EGLContext context) {
+ const char* extensions = eglQueryString(display, EGL_EXTENSIONS);
+ if (HasExtension(extensions, "EGL_KHR_partial_update")) {
+ set_damage_region_ = reinterpret_cast(
+ eglGetProcAddress("eglSetDamageRegionKHR"));
+ }
+
+ if (HasExtension(extensions, "EGL_EXT_swap_buffers_with_damage")) {
+ swap_buffers_with_damage_ =
+ reinterpret_cast(
+ eglGetProcAddress("eglSwapBuffersWithDamageEXT"));
+ } else if (HasExtension(extensions, "EGL_KHR_swap_buffers_with_damage")) {
+ swap_buffers_with_damage_ =
+ reinterpret_cast(
+ eglGetProcAddress("eglSwapBuffersWithDamageKHR"));
+ }
+
+ partial_redraw_supported_ =
+ set_damage_region_ != nullptr && swap_buffers_with_damage_ != nullptr;
+ }
+
+ void SetDamageRegion(EGLDisplay display,
+ EGLSurface surface,
+ const std::optional& region) {
+ if (set_damage_region_ && region) {
+ auto rects = RectToInts(display, surface, *region);
+ set_damage_region_(display, surface, rects.data(), 1);
+ }
+ }
+
+ // Maximum damage history - for triple buffering we need to store damage for
+ // last two frames; Some Ohos devices (Pixel 4) use quad buffering.
+ static const int kMaxHistorySize = 10;
+
+ bool SupportsPartialRepaint() const { return partial_redraw_supported_; }
+
+ std::optional InitialDamage(EGLDisplay display, EGLSurface surface) {
+ if (!partial_redraw_supported_) {
+ return std::nullopt;
+ }
+
+ EGLint age;
+ eglQuerySurface(display, surface, EGL_BUFFER_AGE_EXT, &age);
+
+ if (age == 0) { // full repaint
+ return std::nullopt;
+ } else {
+ // join up to (age - 1) last rects from damage history
+ --age;
+ auto res = SkIRect::MakeEmpty();
+ for (auto i = damage_history_.rbegin();
+ i != damage_history_.rend() && age > 0; ++i, --age) {
+ res.join(*i);
+ }
+ return res;
+ }
+ }
+
+ bool SwapBuffersWithDamage(EGLDisplay display,
+ EGLSurface surface,
+ const std::optional& damage) {
+ if (swap_buffers_with_damage_ && damage) {
+ damage_history_.push_back(*damage);
+ if (damage_history_.size() > kMaxHistorySize) {
+ damage_history_.pop_front();
+ }
+ auto rects = RectToInts(display, surface, *damage);
+ return swap_buffers_with_damage_(display, surface, rects.data(), 1);
+ } else {
+ return eglSwapBuffers(display, surface);
+ }
+ }
+
+ private:
+ std::array static RectToInts(EGLDisplay display,
+ EGLSurface surface,
+ const SkIRect& rect) {
+ EGLint height;
+ eglQuerySurface(display, surface, EGL_HEIGHT, &height);
+
+ std::array res{rect.left(), height - rect.bottom(), rect.width(),
+ rect.height()};
+ return res;
+ }
+
+ PFNEGLSETDAMAGEREGIONKHRPROC set_damage_region_ = nullptr;
+ PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage_ = nullptr;
+
+ bool partial_redraw_supported_;
+
+ std::list damage_history_;
+};
+
+OhosEGLSurface::OhosEGLSurface(EGLSurface surface,
+ EGLDisplay display,
+ EGLContext context)
+ : surface_(surface),
+ display_(display),
+ context_(context),
+ damage_(std::make_unique()),
+ presentation_time_proc_(nullptr) {
+ FML_LOG(INFO) << "OhosEGLSurface start";
+ damage_->init(display_, context);
+ FML_LOG(INFO) << "OhosEGLSurface end";
+}
+
+OhosEGLSurface::~OhosEGLSurface() {
+ [[maybe_unused]] auto result = eglDestroySurface(display_, surface_);
+ FML_DCHECK(result == EGL_TRUE);
+}
+
+bool OhosEGLSurface::IsValid() const {
+ return surface_ != EGL_NO_SURFACE;
+}
+
+bool OhosEGLSurface::IsContextCurrent() const {
+ EGLContext current_egl_context = eglGetCurrentContext();
+ if (context_ != current_egl_context) {
+ return false;
+ }
+
+ EGLDisplay current_egl_display = eglGetCurrentDisplay();
+ if (display_ != current_egl_display) {
+ return false;
+ }
+
+ EGLSurface draw_surface = eglGetCurrentSurface(EGL_DRAW);
+ if (draw_surface != surface_) {
+ return false;
+ }
+
+ EGLSurface read_surface = eglGetCurrentSurface(EGL_READ);
+ if (read_surface != surface_) {
+ return false;
+ }
+
+ return true;
+}
+
+OhosEGLSurfaceMakeCurrentStatus OhosEGLSurface::MakeCurrent() const {
+ if (IsContextCurrent()) {
+ return OhosEGLSurfaceMakeCurrentStatus::kSuccessAlreadyCurrent;
+ }
+ if (eglMakeCurrent(display_, surface_, surface_, context_) != EGL_TRUE) {
+ FML_LOG(ERROR) << "Could not make the context current";
+ LogLastEGLError();
+ return OhosEGLSurfaceMakeCurrentStatus::kFailure;
+ }
+ return OhosEGLSurfaceMakeCurrentStatus::kSuccessMadeCurrent;
+}
+
+void OhosEGLSurface::SetDamageRegion(
+ const std::optional& buffer_damage) {
+ damage_->SetDamageRegion(display_, surface_, buffer_damage);
+}
+
+bool OhosEGLSurface::SetPresentationTime(
+ const fml::TimePoint& presentation_time) {
+ if (presentation_time_proc_) {
+ const auto time_ns = presentation_time.ToEpochDelta().ToNanoseconds();
+ return presentation_time_proc_(display_, surface_, time_ns);
+ } else {
+ return false;
+ }
+}
+
+bool OhosEGLSurface::SwapBuffers(const std::optional& surface_damage) {
+ TRACE_EVENT0("flutter", "OhosContextGL::SwapBuffers");
+ return damage_->SwapBuffersWithDamage(display_, surface_, surface_damage);
+}
+
+bool OhosEGLSurface::SupportsPartialRepaint() const {
+ return damage_->SupportsPartialRepaint();
+}
+
+std::optional OhosEGLSurface::InitialDamage() {
+ return damage_->InitialDamage(display_, surface_);
+}
+
+SkISize OhosEGLSurface::GetSize() const {
+ EGLint width = 0;
+ EGLint height = 0;
+
+ if (!eglQuerySurface(display_, surface_, EGL_WIDTH, &width) ||
+ !eglQuerySurface(display_, surface_, EGL_HEIGHT, &height)) {
+ FML_LOG(ERROR) << "Unable to query EGL surface size";
+ LogLastEGLError();
+ return SkISize::Make(0, 0);
+ }
+ return SkISize::Make(width, height);
+}
+
+} // namespace flutter
diff --git a/shell/platform/ohos/ohos_egl_surface.h b/shell/platform/ohos/ohos_egl_surface.h
new file mode 100755
index 0000000000000000000000000000000000000000..a2f98f90a40b295fe836e065c890a491e4b1df6f
--- /dev/null
+++ b/shell/platform/ohos/ohos_egl_surface.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLUTTER_SHELL_PLATFORM_OHOS_EGL_SURFACE_H_
+#define FLUTTER_SHELL_PLATFORM_OHOS_EGL_SURFACE_H_
+
+#include
+#include
+#include
+#include
+
+#include "flutter/fml/macros.h"
+#include "flutter/fml/time/time_point.h"
+#include "flutter/shell/platform/ohos/ohos_environment_gl.h"
+#include "third_party/skia/include/core/SkRect.h"
+
+namespace flutter {
+
+//------------------------------------------------------------------------------
+/// Holds an `EGLSurface` reference.
+///
+///
+/// This can be used in conjunction to unique_ptr to provide better guarantees
+/// about the lifespan of the `EGLSurface` object.
+///
+class OhosEGLSurfaceDamage;
+
+/// Result of calling MakeCurrent on OhosEGLSurface.
+enum class OhosEGLSurfaceMakeCurrentStatus {
+ /// Success, the egl context for the surface was already current.
+ kSuccessAlreadyCurrent,
+ /// Success, the egl context for the surface made current.
+ kSuccessMadeCurrent,
+ /// Failed to make the egl context for the surface current.
+ kFailure,
+};
+
+void LogLastEGLError();
+
+class OhosEGLSurface {
+ public:
+ OhosEGLSurface(EGLSurface surface, EGLDisplay display, EGLContext context);
+
+ ~OhosEGLSurface();
+
+ //----------------------------------------------------------------------------
+ /// @return Whether the current `EGLSurface` reference is valid. That is,
+ /// if
+ /// the surface doesn't point to `EGL_NO_SURFACE`.
+ ///
+ bool IsValid() const;
+
+ //----------------------------------------------------------------------------
+ /// @brief Binds the EGLContext context to the current rendering thread
+ /// and to the draw and read surface.
+ ///
+ /// @return Whether the surface was made current.
+ ///
+ OhosEGLSurfaceMakeCurrentStatus MakeCurrent() const;
+
+ //----------------------------------------------------------------------------
+ ///
+ /// @return Whether target surface supports partial repaint.
+ ///
+ bool SupportsPartialRepaint() const;
+
+ //----------------------------------------------------------------------------
+ /// @brief This is the minimal area that needs to be repainted to get
+ /// correct result.
+ ///
+ /// With double or triple buffering this buffer content may lag behind
+ /// current front buffer and the rect accounts for accumulated damage.
+ ///
+ /// @return The area of current surface where it is behind front buffer.
+ ///
+ std::optional InitialDamage();
+
+ //----------------------------------------------------------------------------
+ /// @brief Sets the damage region for current surface. Corresponds to
+ // eglSetDamageRegionKHR
+ void SetDamageRegion(const std::optional& buffer_damage);
+
+ //----------------------------------------------------------------------------
+ /// @brief Sets the presentation time for the current surface. This
+ // corresponds to calling eglPresentationTimeOhos when
+ // available.
+ bool SetPresentationTime(const fml::TimePoint& presentation_time);
+
+ //----------------------------------------------------------------------------
+ /// @brief This only applies to on-screen surfaces such as those created
+ /// by `OhosContextGL::CreateOnscreenSurface`.
+ ///
+ /// @return Whether the EGL surface color buffer was swapped.
+ ///
+ bool SwapBuffers(const std::optional& surface_damage);
+
+ //----------------------------------------------------------------------------
+ /// @return The size of an `EGLSurface`.
+ ///
+ SkISize GetSize() const;
+
+ private:
+ /// Returns true if the EGLContext held is current for the display and surface
+ bool IsContextCurrent() const;
+
+ const EGLSurface surface_;
+ const EGLDisplay display_;
+ const EGLContext context_;
+ std::unique_ptr damage_;
+ PFNEGLPRESENTATIONTIMEANDROIDPROC presentation_time_proc_;
+};
+
+} // namespace flutter
+
+#endif
diff --git a/shell/platform/ohos/ohos_environment_gl.cpp b/shell/platform/ohos/ohos_environment_gl.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..b179e6a05aa5c15d4585c610c4db40cb1ae9f819
--- /dev/null
+++ b/shell/platform/ohos/ohos_environment_gl.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flutter/shell/platform/ohos/ohos_environment_gl.h"
+
+namespace flutter {
+
+OhosEnvironmentGL::OhosEnvironmentGL()
+ : display_(EGL_NO_DISPLAY), valid_(false) {
+ // Get the display.
+ display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+ if (display_ == EGL_NO_DISPLAY) {
+ return;
+ }
+
+ // Initialize the display connection.
+ if (eglInitialize(display_, nullptr, nullptr) != EGL_TRUE) {
+ return;
+ }
+
+ valid_ = true;
+}
+
+OhosEnvironmentGL::~OhosEnvironmentGL() {
+ // Disconnect the display if valid.
+ if (display_ != EGL_NO_DISPLAY) {
+ eglTerminate(display_);
+ }
+}
+
+bool OhosEnvironmentGL::IsValid() const {
+ return valid_;
+}
+
+EGLDisplay OhosEnvironmentGL::Display() const {
+ return display_;
+}
+
+} // namespace flutter
diff --git a/shell/platform/ohos/ohos_environment_gl.h b/shell/platform/ohos/ohos_environment_gl.h
new file mode 100755
index 0000000000000000000000000000000000000000..a2e925f61284b27471b703a6c903558758ac4c30
--- /dev/null
+++ b/shell/platform/ohos/ohos_environment_gl.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLUTTER_SHELL_PLATFORM_OHOS_ENVIRONMENT_GL_H_
+#define FLUTTER_SHELL_PLATFORM_OHOS_ENVIRONMENT_GL_H_
+
+#include "flutter/fml/macros.h"
+#include "flutter/fml/memory/ref_counted.h"
+
+#include
+
+namespace flutter {
+
+class OhosEnvironmentGL : public fml::RefCountedThreadSafe {
+ private:
+ // MakeRefCounted
+ OhosEnvironmentGL();
+
+ // MakeRefCounted
+ ~OhosEnvironmentGL();
+
+ public:
+ bool IsValid() const;
+
+ EGLDisplay Display() const;
+
+ private:
+ EGLDisplay display_;
+ bool valid_;
+
+ FML_FRIEND_MAKE_REF_COUNTED(OhosEnvironmentGL);
+ FML_FRIEND_REF_COUNTED_THREAD_SAFE(OhosEnvironmentGL);
+ FML_DISALLOW_COPY_AND_ASSIGN(OhosEnvironmentGL);
+};
+
+} // namespace flutter
+
+#endif
diff --git a/shell/platform/ohos/ohos_external_texture_gl.cpp b/shell/platform/ohos/ohos_external_texture_gl.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..8c5c6a68260abcef0f49c15799cc9b299a8bece3
--- /dev/null
+++ b/shell/platform/ohos/ohos_external_texture_gl.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ohos_external_texture_gl.h"
+#include
+
+#include
+
+#include "third_party/skia/include/core/SkAlphaType.h"
+#include "third_party/skia/include/core/SkColorSpace.h"
+#include "third_party/skia/include/core/SkColorType.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/gpu/GrBackendSurface.h"
+#include "third_party/skia/include/gpu/GrDirectContext.h"
+
+namespace flutter {
+
+OHOSExternalTextureGL::OHOSExternalTextureGL(int id)
+ : Texture(id), transform(SkMatrix::I()) {}
+
+OHOSExternalTextureGL::~OHOSExternalTextureGL() {
+ if (state_ == AttachmentState::attached) {
+ // glDeleteTextures(1, &texture_name_);
+ }
+}
+
+void OHOSExternalTextureGL::Paint(PaintContext& context,
+ const SkRect& bounds,
+ bool freeze,
+ const SkSamplingOptions& sampling) {
+ if (state_ == AttachmentState::detached) {
+ return;
+ }
+ if (state_ == AttachmentState::uninitialized) {
+ // glGenTextures(1, &texture_name_);
+ Attach(static_cast(texture_name_));
+ state_ = AttachmentState::attached;
+ }
+ if (!freeze && new_frame_ready_) {
+ Update();
+ new_frame_ready_ = false;
+ }
+ GrGLTextureInfo textureInfo = {0, texture_name_, GL_RGBA8_OES};
+ GrBackendTexture backendTexture(1, 1, GrMipMapped::kNo, textureInfo);
+ sk_sp image = SkImage::MakeFromTexture(
+ context.gr_context, backendTexture, kTopLeft_GrSurfaceOrigin,
+ kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
+ if (image) {
+ SkAutoCanvasRestore autoRestore(context.canvas, true);
+
+ // The incoming texture is vertically flipped, so we flip it
+ // back. OpenGL's coordinate system has Positive Y equivalent to up, while
+ // Skia's coordinate system has Negative Y equvalent to up.
+ context.canvas->translate(bounds.x(), bounds.y() + bounds.height());
+ context.canvas->scale(bounds.width(), -bounds.height());
+
+ if (!transform.isIdentity()) {
+ sk_sp shader = image->makeShader(
+ SkTileMode::kRepeat, SkTileMode::kRepeat, sampling, transform);
+
+ SkPaint paintWithShader;
+ if (context.sk_paint) {
+ paintWithShader = *context.sk_paint;
+ }
+ paintWithShader.setShader(shader);
+ context.canvas->drawRect(SkRect::MakeWH(1, 1), paintWithShader);
+ } else {
+ context.canvas->drawImage(image, 0, 0, sampling, context.sk_paint);
+ }
+ }
+}
+
+void OHOSExternalTextureGL::OnGrContextCreated() {
+ state_ = AttachmentState::uninitialized;
+}
+
+void OHOSExternalTextureGL::OnGrContextDestroyed() {
+ if (state_ == AttachmentState::attached) {
+ Detach();
+ // glDeleteTextures(1, &texture_name_);
+ }
+ state_ = AttachmentState::detached;
+}
+
+void OHOSExternalTextureGL::MarkNewFrameAvailable() {
+ new_frame_ready_ = true;
+}
+
+void OHOSExternalTextureGL::OnTextureUnregistered() {
+ // do nothing
+}
+
+void OHOSExternalTextureGL::Attach(int textureName) {
+ // do nothing
+}
+
+void OHOSExternalTextureGL::Update() {
+ UpdateTransform();
+}
+
+void OHOSExternalTextureGL::Detach() {
+ // do nothing
+}
+
+void OHOSExternalTextureGL::UpdateTransform() {
+ SkMatrix inverted;
+ if (!transform.invert(&inverted)) {
+ FML_LOG(FATAL) << "Invalid SurfaceTexture transformation matrix";
+ }
+ transform = inverted;
+}
+} // namespace flutter
\ No newline at end of file
diff --git a/shell/platform/ohos/ohos_external_texture_gl.h b/shell/platform/ohos/ohos_external_texture_gl.h
new file mode 100755
index 0000000000000000000000000000000000000000..aa08880048c15b286713289593a7fb8073d7cb29
--- /dev/null
+++ b/shell/platform/ohos/ohos_external_texture_gl.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OHOS_EXTERNAL_TEXTURE_GL_H
+#define OHOS_EXTERNAL_TEXTURE_GL_H
+#include
+
+#include "flutter/common/graphics/texture.h"
+#include "napi/platform_view_ohos_napi.h"
+
+// maybe now unused
+namespace flutter {
+
+class OHOSExternalTextureGL : public flutter::Texture {
+ public:
+ explicit OHOSExternalTextureGL(int id);
+
+ ~OHOSExternalTextureGL() override;
+
+ void Paint(PaintContext& context,
+ const SkRect& bounds,
+ bool freeze,
+ const SkSamplingOptions& sampling) override;
+
+ void OnGrContextCreated() override;
+
+ void OnGrContextDestroyed() override;
+
+ void MarkNewFrameAvailable() override;
+
+ void OnTextureUnregistered() override;
+
+ private:
+ void Attach(int textureName);
+
+ void Update();
+
+ void Detach();
+
+ void UpdateTransform();
+
+ enum class AttachmentState { uninitialized, attached, detached };
+
+ AttachmentState state_ = AttachmentState::uninitialized;
+
+ bool new_frame_ready_ = false;
+
+ GLuint texture_name_ = 0;
+
+ SkMatrix transform;
+
+ FML_DISALLOW_COPY_AND_ASSIGN(OHOSExternalTextureGL);
+};
+} // namespace flutter
+#endif
\ No newline at end of file
diff --git a/shell/platform/ohos/ohos_image_generator.cpp b/shell/platform/ohos/ohos_image_generator.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..0e0e525f60bb746cb2dec7bf77ab98a1858e6881
--- /dev/null
+++ b/shell/platform/ohos/ohos_image_generator.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ohos_image_generator.h"
+
+#include
+#include
+
+#include
+#include "third_party/skia/include/codec/SkCodecAnimation.h"
+
+namespace flutter {
+
+OHOSImageGenerator::OHOSImageGenerator(
+ sk_sp buffer,
+ std::shared_ptr napi_facade)
+ : data_(std::move(buffer)), image_info_(SkImageInfo::MakeUnknown(-1, -1)) {
+ napi_facade_ = napi_facade;
+}
+
+napi_env OHOSImageGenerator::g_env = nullptr;
+
+napi_value OHOSImageGenerator::ImageNativeInit(napi_env env,
+ napi_callback_info info) {
+ g_env = env;
+
+ return nullptr;
+}
+
+OHOSImageGenerator::~OHOSImageGenerator() = default;
+
+// |ImageGenerator|
+const SkImageInfo& OHOSImageGenerator::GetInfo() {
+ header_decoded_latch_.Wait();
+ return image_info_;
+}
+
+// |ImageGenerator|
+unsigned int OHOSImageGenerator::GetFrameCount() const {
+ return 1;
+}
+
+// |ImageGenerator|
+unsigned int OHOSImageGenerator::GetPlayCount() const {
+ return 1;
+}
+
+// |ImageGenerator|
+const ImageGenerator::FrameInfo OHOSImageGenerator::GetFrameInfo(
+ unsigned int frame_index) const {
+ return {.required_frame = std::nullopt,
+ .duration = 0,
+ .disposal_method = SkCodecAnimation::DisposalMethod::kKeep};
+}
+
+// |ImageGenerator|
+SkISize OHOSImageGenerator::GetScaledDimensions(float desired_scale) {
+ return GetInfo().dimensions();
+}
+
+// |ImageGenerator|
+bool OHOSImageGenerator::GetPixels(const SkImageInfo& info,
+ void* pixels,
+ size_t row_bytes,
+ unsigned int frame_index,
+ std::optional prior_frame) {
+ fully_decoded_latch_.Wait();
+ if (!software_decoded_data_) {
+ return false;
+ }
+
+ if (kRGBA_8888_SkColorType != info.colorType()) {
+ return false;
+ }
+
+ switch (info.alphaType()) {
+ case kOpaque_SkAlphaType:
+ if (kOpaque_SkAlphaType != GetInfo().alphaType()) {
+ return false;
+ }
+ break;
+ case kPremul_SkAlphaType:
+ break;
+ default:
+ return false;
+ }
+
+ // TODO(bdero): Override `GetImage()` to use `SkImage::FromAHardwareBuffer` on
+ // API level 30+ once it's updated to do symbol lookups and not get
+ // preprocessed out in Skia. This will allow for avoiding this copy in
+ // cases where the result image doesn't need to be resized.
+ memcpy(pixels, software_decoded_data_->data(),
+ software_decoded_data_->size());
+ return true;
+}
+
+void OHOSImageGenerator::DecodeImage() {
+ DoDecodeImage();
+
+ header_decoded_latch_.Signal();
+ fully_decoded_latch_.Signal();
+}
+
+std::shared_ptr OHOSImageGenerator::MakeFromData(
+ sk_sp data,
+ const fml::RefPtr