diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..e69de29b
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..0eb4fb60
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+.vs/
+.vscode/
+*.iml
+.idea/
+CMakeLists.txt
+cmake-build-debug/
+lite/appfwk/
+lite/base/
+lite/interfaces/
+lite/jsfwk/
+lite/maplejs/
+lite/tools/
+lite/ui/
+
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 00000000..8c10ac95
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,134 @@
+# Copyright (c) 2021 Huawei Device 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/ohos.gni")
+import("//foundation/ace/ace_engine/ace_config.gni")
+
+config("accessibility_library_config") {
+ include_dirs = [ "../accessibility/common/" ]
+}
+
+group("ace_packages") {
+ deps = []
+
+ # core library for Ability Cross-platform Environment(ACE) JS
+ deps += [
+ "$ace_root/frameworks/core/components/theme:build_theme_code",
+ "adapter/common/cpp:libace",
+ ]
+
+ if (is_wearable_product) {
+ deps += [ "adapter/common/cpp:libace_debug" ]
+ }
+
+ if (!is_wearable_product) {
+ deps += [
+ "adapter/common/cpp:libace_engine_qjs",
+ "adapter/common/cpp:libace_engine_qjs_debug",
+ "adapter/common/cpp:libace_engine_declarative_qjs"
+ ]
+ }
+}
+
+group("ace_test_packages") {
+ # ohos platform
+ deps = []
+}
+
+source_set("third_party_cjson") {
+ sources = [ "$cjson_root/cJSON.c" ]
+}
+
+# Common config for Ability Cross-platform Environment(ACE) source
+config("ace_config") {
+ visibility = [ ":*" ]
+ include_dirs = [
+ "$ace_root",
+ "$ace_root/frameworks",
+ "$root_out_dir/ace/framework",
+ "//third_party/zlib",
+ ]
+ if (is_standard_system) {
+ include_dirs += [
+ "//base/global/resmgr_standard/frameworks/resmgr/include",
+ "//base/global/resmgr_standard/interfaces/innerkits/include",
+ ]
+ }
+ defines = ace_common_defines
+
+ if (is_wearable_product) {
+ defines += ace_wearable_defines
+ }
+
+ if (enable_dump_drawcmd) {
+ defines += [ "DUMP_DRAW_CMD" ]
+ }
+
+ if (is_standard_system) {
+ defines += [ "SK_BUILD_FOR_UNIX" ]
+ }
+
+ cflags = [
+ "-fvisibility=hidden",
+ "-fdata-sections",
+ "-ffunction-sections",
+ "-Os",
+ ]
+
+ cflags_cc = [
+ "-fvisibility-inlines-hidden",
+ "-Os",
+ ]
+
+ if (use_js_debug) {
+ cflags_cc += [
+ "-fexceptions",
+ "-fno-complete-member-pointers",
+ "-Wno-implicit-fallthrough",
+ ]
+ }
+
+ if (use_mingw_win) {
+ cflags += [ "-std=c++17" ]
+ defines += [ "_USE_MATH_DEFINES" ]
+ }
+}
+
+config("ace_test_config") {
+ visibility = [ ":*" ]
+ include_dirs = [
+ "$ace_root",
+ "$ace_root/frameworks",
+ "$root_out_dir/ace/framework",
+ ]
+ if (is_standard_system) {
+ include_dirs += [
+ "//base/global/resmgr_standard/frameworks/resmgr/include",
+ "//base/global/resmgr_standard/interfaces/innerkits/include",
+ ]
+ }
+ defines = ace_common_defines
+ defines += ace_ohos_defines
+
+ if (is_wearable_product) {
+ defines += ace_wearable_defines
+ }
+
+ cflags = [
+ "-fvisibility=hidden",
+ "-fdata-sections",
+ "-ffunction-sections",
+ ]
+
+ cflags_cc = [ "-fvisibility-inlines-hidden" ]
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..4947287f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,177 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/OAT.xml b/OAT.xml
new file mode 100644
index 00000000..433926ba
--- /dev/null
+++ b/OAT.xml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/README.en.md b/README.en.md
deleted file mode 100644
index 3f94b629..00000000
--- a/README.en.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# ace_ace_engine
-
-#### Description
-JS UI framework | JS UI开发框架
-
-#### Software Architecture
-Software architecture description
-
-#### Installation
-
-1. xxxx
-2. xxxx
-3. xxxx
-
-#### Instructions
-
-1. xxxx
-2. xxxx
-3. xxxx
-
-#### Contribution
-
-1. Fork the repository
-2. Create Feat_xxx branch
-3. Commit your code
-4. Create Pull Request
-
-
-#### Gitee Feature
-
-1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
-2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
-3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
-4. The most valuable open source project [GVP](https://gitee.com/gvp)
-5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
-6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
diff --git a/README.md b/README.md
index 6e77a795..b9cf9967 100644
--- a/README.md
+++ b/README.md
@@ -1,37 +1,102 @@
-# ace_ace_engine
+# JS UI Framework
-#### 介绍
-JS UI framework | JS UI开发框架
+- [Introduction](#section15701932113019)
+- [Directory Structure](#section1791423143211)
+- [When to Use](#section171384529150)
+- [Available Components](#section271831717166)
+- [Repositories Involved](#section1447164910172)
-#### 软件架构
-软件架构说明
+## Introduction
+
+The OpenHarmony JS UI framework provides basic, container, and canvas UI components and standard CSS animation capabilities. It supports the web-development-like programming paradigm.
+
+- **Web-development-like paradigm**
+
+ The JS UI framework supports languages that are similar to those for web development, such as HTML and CSS. You can use them to describe the page layout and style, and use JavaScript \(conforming to the ECMAScript specification\) for page behavior. This paradigm allows you to avoid code for UI state switching. The view configuration information is intuitive.
-#### 安装教程
+**Figure 1** Framework architecture
+
-1. xxxx
-2. xxxx
-3. xxxx
+The JS UI framework consists of the application, framework, engine, and porting layers.
-#### 使用说明
+- **Application**
-1. xxxx
-2. xxxx
-3. xxxx
+ Contains apps with Feature Abilities \(FAs\) developed with the JS UI framework. The FA app in this document refers to the app with FAs developed using JavaScript.
-#### 参与贡献
+- **Framework**
-1. Fork 本仓库
-2. 新建 Feat_xxx 分支
-3. 提交代码
-4. 新建 Pull Request
+ Parses UI pages and provides the Model-View-ViewModel \(MVVM\), page routing, custom components and more for front end development.
+
+- **Engine**
+
+ Accomplishes animation parsing, Document Object Model \(DOM\) building, layout computing, rendering command building and drawing, and event management.
+
+- **Porting Layer**
+
+ Abstracts the platform layer to provide abstract interfaces to connect to the platform. For example, event interconnection, rendering pipeline interconnection, and lifecycle interconnection.
-#### 特技
+## Directory Structure
+
+The source code of the framework is stored in **/foundation/ace/ace\_engine**. The following shows the directory structure.
+
+```
+/foundation/ace/ace_engine
+├── adapter # Platform adaptation code
+│ ├── common
+│ └── ohos
+├── frameworks # Framework code
+│ ├── base # Basic libraries
+│ ├── bridge # Bridging layer for frontend and backend components
+│ └── core # Core components
+```
+
+## When to Use
+
+JS UI framework provides various UI components with rich functionalities and style definitions. You can use and reuse any component anywhere as needed. You can customize new components by combining existing ones to simplify development.
+
+## Available Components
+
+**Table 1** Components provided by the framework
+
+
+
Type
+ |
+Components
+ |
+
+
+Basic
+ |
+button, text, input, label, image, progress, rating, span, marquee, image-animator, divider, menu, chart, option, picker, picker-view, piece, qrcode, select, slider, switch, toolbar, toolbar-item, toggle
+ |
+
+Container
+ |
+div, list, list-item, list-item-group, stack, swiper, tabs, tab-bar, tab-content, refresh, dialog, badge, panel, popup, stepper, stepper-item
+ |
+
+Canvas
+ |
+canvas
+ |
+
+Grid
+ |
+grid-container, grid-row, grid-col
+ |
+
+
+
+
+## Repositories Involved
+
+JS UI framework
+
+**ace\_ace\_engine**
+
+ace\_ace\_engine\_lite
+
+ace\_napi
-1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
-2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
-3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
-4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
-5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
-6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
diff --git a/README_zh.md b/README_zh.md
new file mode 100644
index 00000000..596939a2
--- /dev/null
+++ b/README_zh.md
@@ -0,0 +1,102 @@
+# JS UI框架组件
+
+- [简介](#section15701932113019)
+- [目录](#section1791423143211)
+- [使用场景](#section171384529150)
+- [接口说明](#section271831717166)
+- [涉及仓](#section1447164910172)
+
+## 简介
+
+JS UI框架是OpenHarmony UI开发框架,提供基础类、容器类、画布类等UI组件和标准CSS动画能力,支持类Web范式编程。
+
+- **类Web范式编程**
+
+ JS UI框架采用类HTML和CSS Web编程语言作为页面布局和页面样式的开发语言,页面业务逻辑则支持ECMAScript规范的JavaScript语言。JS UI框架提供的类Web编程范式,可以让开发者避免编写UI状态切换的代码,视图配置信息更加直观。
+
+
+**图 1** JS UI框架架构
+
+
+JS UI框架包括应用层(Application)、前端框架层(Framework)、引擎层(Engine)和平台适配层(Porting Layer)。
+
+- **Application**
+
+ 应用层表示开发者使用JS UI框架开发的FA应用,这里的FA应用特指JS FA应用。
+
+- **Framework**
+
+ 前端框架层主要完成前端页面解析,以及提供MVVM(Model-View-ViewModel)开发模式、页面路由机制和自定义组件等能力。
+
+- **Engine**
+
+ 引擎层主要提供动画解析、DOM(Document Object Model)树构建、布局计算、渲染命令构建与绘制、事件管理等能力。
+
+- **Porting Layer**
+
+ 适配层主要完成对平台层进行抽象,提供抽象接口,可以对接到系统平台。比如:事件对接、渲染管线对接和系统生命周期对接等。
+
+
+## 目录
+
+JS UI开发框架源代码在/foundation/ace/ace\_engine下,目录结构如下图所示:
+
+```
+/foundation/ace/ace_engine
+├── adapter # 平台适配目录
+│ ├── common
+│ └── ohos
+├── frameworks # 框架代码
+│ ├── base # 基础库
+│ ├── bridge # 前后端组件对接层
+│ └── core # 核心组件目录
+```
+
+## 使用场景
+
+JS UI框架提供了丰富的、功能强大的UI组件、样式定义,组件之间相互独立,随取随用,也可以在需求相同的地方重复使用。开发者还可以通过组件间合理的搭配定义满足业务需求的新组件,减少开发量。
+
+## 接口说明
+
+**表 1** 组件介绍
+
+
+组件类型
+ |
+主要组件
+ |
+
+
+基础组件
+ |
+button、text、input、label、image、progress、rating、span、marquee、image-animator、divider、menu、chart、option、picker、picker-view、piece、qrcode、select、slider、switch、toolbar、toolbar-item、toggle
+ |
+
+容器组件
+ |
+div、list、list-item、list-item-group、stack、swiper、tabs、tab-bar、tab-content、refresh、dialog、badge、panel、popup、stepper、stepper-item
+ |
+
+画布组件
+ |
+canvas
+ |
+
+栅格组件
+ |
+grid-container、grid-row、grid-col
+ |
+
+
+
+
+## 涉及仓
+
+JS UI框架子系统
+
+**ace\_ace\_engine**
+
+ace\_ace\_engine\_lite
+
+ace\_napi
+
diff --git a/ace_config.gni b/ace_config.gni
new file mode 100644
index 00000000..6dbe159b
--- /dev/null
+++ b/ace_config.gni
@@ -0,0 +1,26 @@
+# Copyright (c) 2021 Huawei Device 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("//third_party/flutter/flutter_ace_config.gni")
+
+ace_root = "//foundation/ace/ace_engine"
+
+ace_test_output_root = "ace_engine_standard"
+
+objcopy_aarch64 = "//prebuilts/gcc/linux-x86/arm/gcc-linaro-7.5.0-arm-linux-gnueabi/arm-linux-gnueabi/bin/objcopy"
+objcopy_x86_64 = ""
+ark_tools_root = "//prebuilts/ace-toolkit/ace-loader/panda"
+node_js_path = "//prebuilts/ace-toolkit/nodejs/node-v12.18.4-linux-x64/bin/"
+cjson_root = "//third_party/cJSON"
+
+use_js_debug = false
diff --git a/adapter/common/cpp/BUILD.gn b/adapter/common/cpp/BUILD.gn
new file mode 100644
index 00000000..cdc65abe
--- /dev/null
+++ b/adapter/common/cpp/BUILD.gn
@@ -0,0 +1,179 @@
+# Copyright (c) 2021 Huawei Device 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/ohos.gni")
+import("//foundation/ace/ace_engine/ace_config.gni")
+
+# build static
+template("ace_base_platform_source_set") {
+ # get is_ohos_platform
+ forward_variables_from(invoker, "*")
+
+ ohos_source_set(target_name) {
+ defines += invoker.defines
+ configs = [
+ "$ace_root:ace_config",
+ "$flutter_root:flutter_config",
+ "$flutter_root:icu_config_$platform",
+ ]
+
+ include_dirs = [ "//utils/native/base/include" ]
+
+ sources = [
+ "ace_res_config.cpp",
+ "ace_res_key_parser.cpp",
+ "ace_trace.cpp",
+ "file_asset_provider.cpp",
+ "flutter_task_executor.cpp",
+ "localization.cpp",
+ "thread_util.cpp",
+ ]
+ if (is_standard_system) {
+ sources += [ "$ace_root/adapter/common/cpp/flutter_window.cpp" ]
+ external_deps = [
+ "appexecfwk_standard:libeventhandler",
+ "ipc:ipc_core",
+ ]
+ }
+
+ if (is_ohos_platform) {
+ deps = [ "//third_party/zlib:libz" ]
+ }
+ }
+}
+
+ace_base_platform_source_set("ace_base_common_ohos") {
+ defines = ace_ohos_defines
+ is_ohos_platform = true
+ platform = "ohos"
+}
+
+# Build libace shared library
+template("libace_shared_library") {
+ # get is_ohos_platform
+ forward_variables_from(invoker, "*")
+
+ ohos_shared_library(target_name) {
+ deps = [
+ "$ace_root/frameworks/base:ace_base_$platform",
+ "$ace_root/frameworks/base/resource:ace_resource",
+ "$ace_root/frameworks/bridge:js_framework_$platform",
+ "$ace_root/frameworks/core:ace_core_$platform",
+ "$ace_root/frameworks/core/accessibility:ace_accessibility_$platform",
+ ]
+
+ if (link_qjs_engine) {
+ if (use_js_debug) {
+ deps += [ "$ace_root/frameworks/bridge:js_engine_debug_$platform" ]
+ } else {
+ deps += [
+ "$ace_root/frameworks/bridge:js_engine_$platform",
+ "$ace_root/frameworks/bridge:declarative_js_engine_qjs_$platform",
+ ]
+ }
+ }
+
+ if (is_ohos_platform) {
+ subsystem_name = "ace"
+ }
+
+ if (is_standard_system) {
+ part_name = "ace_engine_standard"
+ }
+ }
+}
+
+libace_shared_library("libace") {
+ is_ohos_platform = true
+ if (is_standard_system) {
+ platform = "ohos"
+ }
+ if (is_wearable_product) {
+ link_qjs_engine = true
+ use_js_debug = false
+ } else {
+ link_qjs_engine = false
+ }
+}
+
+libace_shared_library("libace_debug") {
+ is_ohos_platform = true
+ if (is_standard_system) {
+ platform = "ohos"
+ }
+ if (is_wearable_product) {
+ link_qjs_engine = true
+ use_js_debug = true
+ } else {
+ link_qjs_engine = false
+ }
+}
+
+# build platform engine sources
+template("ace_platform_engine") {
+ # get is_ohos_platform, use_quickjs_engine
+ forward_variables_from(invoker, "*")
+
+ ohos_shared_library(target_name) {
+ deps = []
+
+ if (is_ohos_platform) {
+ deps += [ "$ace_root/adapter/common/cpp:libace" ]
+ }
+
+ if (use_quickjs_engine) {
+ if (use_js_debug) {
+ deps += [ "$ace_root/frameworks/bridge:js_engine_debug_$platform" ]
+ } else if (is_declarative) {
+ deps += [ "$ace_root/frameworks/bridge:declarative_js_engine_qjs_$platform" ]
+ } else {
+ deps += [ "$ace_root/frameworks/bridge:js_engine_$platform"]
+ }
+ }
+
+ if (is_ohos_platform) {
+ subsystem_name = "ace"
+ }
+
+ if (is_standard_system) {
+ part_name = "ace_engine_standard"
+ }
+ }
+}
+
+ace_platform_engine("libace_engine_qjs") {
+ is_ohos_platform = true
+ use_quickjs_engine = true
+ if (is_standard_system) {
+ platform = "ohos"
+ }
+ is_declarative = false
+}
+
+ace_platform_engine("libace_engine_declarative_qjs") {
+ is_ohos_platform = true
+ use_quickjs_engine = true
+ if (is_standard_system) {
+ platform = "ohos"
+ }
+ is_declarative = true
+}
+
+ace_platform_engine("libace_engine_qjs_debug") {
+ is_ohos_platform = true
+ use_quickjs_engine = true
+ use_js_debug = true
+ if (is_standard_system) {
+ platform = "ohos"
+ }
+}
diff --git a/adapter/common/cpp/ace_res_config.cpp b/adapter/common/cpp/ace_res_config.cpp
new file mode 100644
index 00000000..be8ad48d
--- /dev/null
+++ b/adapter/common/cpp/ace_res_config.cpp
@@ -0,0 +1,720 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 "adapter/common/cpp/ace_res_config.h"
+
+#include
+
+#include "unicode/locid.h"
+
+#include "adapter/common/cpp/ace_res_key_parser.h"
+#include "base/json/json_util.h"
+#include "frameworks/bridge/common/utils/utils.h"
+
+namespace OHOS::Ace {
+namespace {
+
+const std::unordered_map LOCALE_PARENTS {
+ { "ar-DZ", "ar-015" },
+ { "ar-EH", "ar-015" },
+ { "ar-LY", "ar-015" },
+ { "ar-MA", "ar-015" },
+ { "ar-TN", "ar-015" },
+ { "zh-MO", "zh-HK" },
+ { "en-150", "en-001" },
+ { "en-AG", "en-001" },
+ { "en-AI", "en-001" },
+ { "en-AU", "en-001" },
+ { "en-BB", "en-001" },
+ { "en-BE", "en-001" },
+ { "en-BM", "en-001" },
+ { "en-BS", "en-001" },
+ { "en-BZ", "en-001" },
+ { "en-CC", "en-001" },
+ { "en-CK", "en-001" },
+ { "en-CX", "en-001" },
+ { "en-DG", "en-001" },
+ { "en-ER", "en-001" },
+ { "en-FK", "en-001" },
+ { "en-FM", "en-001" },
+ { "en-GB", "en-001" },
+ { "en-GD", "en-001" },
+ { "en-GG", "en-001" },
+ { "en-GI", "en-001" },
+ { "en-GY", "en-001" },
+ { "en-HK", "en-001" },
+ { "en-IE", "en-001" },
+ { "en-IM", "en-001" },
+ { "en-IN", "en-001" },
+ { "en-IO", "en-001" },
+ { "en-JE", "en-001" },
+ { "en-KI", "en-001" },
+ { "en-KN", "en-001" },
+ { "en-KY", "en-001" },
+ { "en-LC", "en-001" },
+ { "en-LR", "en-001" },
+ { "en-LS", "en-001" },
+ { "en-MM", "en-001" },
+ { "en-MO", "en-001" },
+ { "en-MS", "en-001" },
+ { "en-MT", "en-001" },
+ { "en-MY", "en-001" },
+ { "en-NF", "en-001" },
+ { "en-NR", "en-001" },
+ { "en-NU", "en-001" },
+ { "en-NZ", "en-001" },
+ { "en-PG", "en-001" },
+ { "en-PK", "en-001" },
+ { "en-PN", "en-001" },
+ { "en-PW", "en-001" },
+ { "en-SB", "en-001" },
+ { "en-SC", "en-001" },
+ { "en-SD", "en-001" },
+ { "en-SG", "en-001" },
+ { "en-SH", "en-001" },
+ { "en-SL", "en-001" },
+ { "en-SS", "en-001" },
+ { "en-SX", "en-001" },
+ { "en-SZ", "en-001" },
+ { "en-TC", "en-001" },
+ { "en-TK", "en-001" },
+ { "en-TT", "en-001" },
+ { "en-TV", "en-001" },
+ { "en-VC", "en-001" },
+ { "en-VG", "en-001" },
+ { "en-WS", "en-001" },
+ { "en-ZG", "en-001" },
+ { "es-AR", "es-419" },
+ { "es-BO", "es-419" },
+ { "es-BR", "es-419" },
+ { "es-BZ", "es-419" },
+ { "es-CL", "es-419" },
+ { "es-CO", "es-419" },
+ { "es-CR", "es-419" },
+ { "es-CU", "es-419" },
+ { "es-DO", "es-419" },
+ { "es-EC", "es-419" },
+ { "es-GT", "es-419" },
+ { "es-HN", "es-419" },
+ { "es-MX", "es-419" },
+ { "es-NI", "es-419" },
+ { "es-PA", "es-419" },
+ { "es-PE", "es-419" },
+ { "es-PR", "es-419" },
+ { "es-PY", "es-419" },
+ { "es-SV", "es-419" },
+ { "es-US", "es-419" },
+ { "es-UY", "es-419" },
+ { "es-VE", "es-419" },
+ { "pt-AO", "pt-PT" },
+ { "pt-CH", "pt-PT" },
+ { "pt-CV", "pt-PT" },
+ { "pt-GQ", "pt-PT" },
+ { "pt-GW", "pt-PT" },
+ { "pt-LU", "pt-PT" },
+ { "pt-MO", "pt-PT" },
+ { "pt-MZ", "pt-PT" },
+ { "pt-ST", "pt-PT" },
+ { "pt-TL", "pt-PT" },
+};
+
+const std::unordered_map DEFAULT_LANG {
+ { "es-419", "es-US" },
+ { "en-Qaag", "en-GB" },
+ { "en-001", "en-GB" },
+};
+
+const std::unordered_map LANGUAGE_CODE_MAP {
+ { "iw", "he" },
+ { "tl", "fil" },
+ { "in", "id" },
+};
+
+std::string ComputeScript(const AceResConfig& resConfig)
+{
+ icu::Locale locale(resConfig.language_.c_str(), resConfig.region_.c_str());
+ UErrorCode status = U_ZERO_ERROR;
+ locale.addLikelySubtags(status);
+ if (status != U_ZERO_ERROR) {
+ return std::string();
+ }
+ return locale.getScript();
+}
+
+AceResConfig ConvertLocaleTagToConfig(const std::string& localeTag)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ icu::Locale locale = icu::Locale::forLanguageTag(icu::StringPiece(localeTag), status);
+ if (status != U_ZERO_ERROR) {
+ LOGE("This localeTag is not valid.");
+ return AceResConfig("", "", "");
+ }
+ return AceResConfig(locale.getLanguage(), locale.getScript(), locale.getCountry());
+}
+
+std::string ConvertLocaleConfigToTag(const AceResConfig& localeConfig)
+{
+ std::string localeTag = localeConfig.language_;
+ if (!localeConfig.script_.empty()) {
+ localeTag += ('-' + localeConfig.script_);
+ }
+ if (!localeConfig.region_.empty()) {
+ localeTag += ('-' + localeConfig.region_);
+ }
+ return localeTag;
+}
+
+bool IsPseudoLocale(const AceResConfig& resConfig)
+{
+ return (resConfig.language_ == "en" && resConfig.region_ == "XA") ||
+ (resConfig.language_ == "ar" && resConfig.region_ == "XB");
+}
+
+void MatchLocaleConfig(const std::vector& candidatesLocaleConfig, const AceResConfig& deviceLocaleConfig,
+ std::vector& matchedLocaleConfigs)
+{
+ std::string deviceLanguage = deviceLocaleConfig.language_;
+ std::string deviceScript = deviceLocaleConfig.script_;
+ auto iter = LANGUAGE_CODE_MAP.find(deviceLanguage);
+ if (iter != LANGUAGE_CODE_MAP.end()) {
+ deviceLanguage = iter->second;
+ }
+ for (auto& candidate : candidatesLocaleConfig) {
+ std::string candidateLanguage = candidate.language_;
+ // Languages codes need to be specially handled.
+ auto candidateIter = LANGUAGE_CODE_MAP.find(candidateLanguage);
+ if (candidateIter != LANGUAGE_CODE_MAP.end()) {
+ candidateLanguage = candidateIter->second;
+ }
+ if (candidateLanguage != deviceLanguage) {
+ continue;
+ }
+ if (IsPseudoLocale(candidate)) {
+ if (IsPseudoLocale(deviceLocaleConfig)) {
+ matchedLocaleConfigs.emplace_back(candidate);
+ }
+ continue;
+ }
+ if (deviceLanguage == "en" && deviceScript == "Qaag") {
+ deviceScript = "Latn";
+ }
+ // Compute Script when it is not provided.
+ std::string candidateScript = candidate.script_.empty() ? ComputeScript(candidate) : candidate.script_;
+ if (deviceScript != candidateScript) {
+ continue;
+ }
+ matchedLocaleConfigs.emplace_back(candidate);
+ }
+}
+
+void FindBacktrackPath(
+ const AceResConfig& localeConfig, std::vector& backtrackPath, const std::string& localeTag)
+{
+ if (LOCALE_PARENTS.find(localeTag) != LOCALE_PARENTS.end()) {
+ std::string curTag = LOCALE_PARENTS.find(localeTag)->second;
+ backtrackPath.emplace_back(curTag);
+ FindBacktrackPath(localeConfig, backtrackPath, curTag);
+ } else {
+ backtrackPath.emplace_back(localeConfig.language_);
+ }
+}
+
+bool IsOnBacktrackingPath(const std::string& bestConfigTag, const std::string& candidateConfigTag,
+ const AceResConfig& bestLocaleConfig, const AceResConfig& candidateLocaleConfig,
+ std::vector backtrackPath)
+{
+ std::vector bestConfigBacktrackPaths;
+ FindBacktrackPath(bestLocaleConfig, bestConfigBacktrackPaths, bestConfigTag);
+ std::vector candidateConfigBacktrackPaths;
+ FindBacktrackPath(candidateLocaleConfig, candidateConfigBacktrackPaths, candidateConfigTag);
+ int32_t bestConfigIndex = -1;
+ int32_t candidateConfigIndex = -1;
+ for (std::size_t i = 0; i < backtrackPath.size(); i++) {
+ for (const auto& bestConfigPath : bestConfigBacktrackPaths) {
+ if (bestConfigPath == backtrackPath[i] && bestConfigIndex == -1) {
+ bestConfigIndex = i;
+ }
+ }
+ for (const auto& candidateConfigPath : candidateConfigBacktrackPaths) {
+ if (candidateConfigPath == backtrackPath[i] && candidateConfigIndex == -1) {
+ candidateConfigIndex = i;
+ }
+ }
+ }
+ if (bestConfigIndex < candidateConfigIndex) {
+ return (bestConfigIndex == -1);
+ } else if (candidateConfigIndex < bestConfigIndex) {
+ return (candidateConfigIndex != -1);
+ }
+ // Check if candidate and best are on the default area of device's backtracking path.
+ for (auto& path : backtrackPath) {
+ if (DEFAULT_LANG.find(path) != DEFAULT_LANG.end()) {
+ std::string curTag = DEFAULT_LANG.find(path)->second;
+ if (bestConfigTag == curTag) {
+ return false;
+ } else if (candidateConfigTag == curTag) {
+ return true;
+ }
+ }
+ }
+
+ // Compute the default region code through the device language code.
+ UErrorCode status = U_ZERO_ERROR;
+ icu::Locale locale = icu::Locale::forLanguageTag(icu::StringPiece(backtrackPath[backtrackPath.size() - 1]), status);
+ locale.addLikelySubtags(status);
+ if (status == U_ZERO_ERROR) {
+ if (bestLocaleConfig.region_ == locale.getCountry()) {
+ return false;
+ }
+ if (candidateLocaleConfig.region_ == locale.getCountry()) {
+ return true;
+ }
+ }
+
+ // If configs did not meet all the conditions above, sort the config region with dictionary order.
+ return strcmp(bestLocaleConfig.region_.c_str(), candidateLocaleConfig.region_.c_str()) >= 0;
+}
+
+bool IsLocaleConfigMoreSpecified(const AceResConfig& bestLocaleConfig, const AceResConfig& deviceLocaleConfig,
+ const AceResConfig& candidateLocaleConfig)
+{
+ // Candidates' language and script are equal with the device's after being filtered MatchLocaleConfig().
+ std::string deviceRegion = deviceLocaleConfig.region_;
+ if (bestLocaleConfig.region_ == deviceRegion) {
+ return false;
+ }
+ if (candidateLocaleConfig.region_ == deviceRegion) {
+ return true;
+ }
+ std::string deviceTag = deviceLocaleConfig.language_ + '-' + deviceLocaleConfig.region_;
+ std::vector deviceBacktrackPath;
+ FindBacktrackPath(deviceLocaleConfig, deviceBacktrackPath, deviceTag);
+ std::string bestConfigTag = bestLocaleConfig.language_;
+ if (!bestLocaleConfig.region_.empty()) {
+ bestConfigTag += '-' + bestLocaleConfig.region_;
+ }
+ std::string candidateConfigTag = candidateLocaleConfig.language_;
+ if (!candidateLocaleConfig.region_.empty()) {
+ candidateConfigTag += '-' + candidateLocaleConfig.region_;
+ }
+ int32_t bestConfigIndex = -1;
+ int32_t candidateConfigIndex = -1;
+ for (std::size_t i = 0; i < deviceBacktrackPath.size(); i++) {
+ if (deviceBacktrackPath[i] == bestConfigTag) {
+ bestConfigIndex = i;
+ }
+ if (deviceBacktrackPath[i] == candidateConfigTag) {
+ candidateConfigIndex = i;
+ }
+ }
+ if (bestConfigIndex < candidateConfigIndex) {
+ return (bestConfigIndex == -1);
+ } else if (candidateConfigIndex < bestConfigIndex) {
+ return (candidateConfigIndex != -1);
+ }
+ // Neither best nor candidate on the device's backtracking path, check if they are the default locale of the device.
+ if (candidateConfigIndex == bestConfigIndex && candidateConfigIndex == -1) {
+ std::string deviceTagWithScript = deviceLocaleConfig.language_ + "-" + deviceLocaleConfig.script_;
+ if (DEFAULT_LANG.find(deviceTagWithScript) != DEFAULT_LANG.end()) {
+ std::string defaultTag = DEFAULT_LANG.find(deviceTagWithScript)->second;
+ std::string defaultRegion = defaultTag.substr(defaultTag.find('-') + 1);
+ if (candidateLocaleConfig.region_ == defaultRegion) {
+ return true;
+ }
+ if (bestLocaleConfig.region_ == defaultRegion) {
+ return false;
+ }
+ }
+ // If they are not on the default area, continue to check the candidates' backtacking path.
+ return IsOnBacktrackingPath(
+ bestConfigTag, candidateConfigTag, bestLocaleConfig, candidateLocaleConfig, deviceBacktrackPath);
+ }
+ // Both best and candidate on the device's backtracking path with same index.
+ return false;
+}
+
+void SortLocaleConfigs(std::vector& candidatesLocaleConfig, const AceResConfig& deviceLocaleConfig,
+ int32_t left, int32_t right)
+{
+ if (left < right) {
+ AceResConfig bestLocaleConfig = candidatesLocaleConfig[left];
+ int32_t i = left;
+ int32_t j = right;
+ while (i < j) {
+ while (i < j &&
+ !IsLocaleConfigMoreSpecified(bestLocaleConfig, deviceLocaleConfig, candidatesLocaleConfig[j])) {
+ j--;
+ }
+ candidatesLocaleConfig[i] = candidatesLocaleConfig[j];
+ while (
+ i < j && IsLocaleConfigMoreSpecified(bestLocaleConfig, deviceLocaleConfig, candidatesLocaleConfig[i])) {
+ i++;
+ }
+ candidatesLocaleConfig[j] = candidatesLocaleConfig[i];
+ }
+ candidatesLocaleConfig[i] = bestLocaleConfig;
+ SortLocaleConfigs(candidatesLocaleConfig, deviceLocaleConfig, left, i - 1);
+ SortLocaleConfigs(candidatesLocaleConfig, deviceLocaleConfig, i + 1, right);
+ }
+}
+
+bool IsLowerResolutionPreferred(int32_t high, int32_t low, int32_t request)
+{
+ if (request <= low) {
+ return true;
+ }
+
+ if (request >= high) {
+ return false;
+ }
+
+ return ((2 * low) - request) * high > request * request; // scaling down is 2x better than up
+}
+
+bool IsCandidateResolutionPreferred(
+ const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
+{
+ if (bestConfig.resolution_ == candidateConfig.resolution_) {
+ return false;
+ }
+
+ const ResolutionType bestRes = bestConfig.resolution_ != ResolutionType::RESOLUTION_NONE
+ ? bestConfig.resolution_
+ : ResolutionType::RESOLUTION_MDPI;
+ const ResolutionType candidateRes = candidateConfig.resolution_ != ResolutionType::RESOLUTION_NONE
+ ? candidateConfig.resolution_
+ : ResolutionType::RESOLUTION_MDPI;
+
+ if (bestRes == ResolutionType::RESOLUTION_ANY) {
+ return false;
+ } else if (candidateRes == ResolutionType::RESOLUTION_ANY) {
+ return true;
+ }
+
+ ResolutionType deviceRes = deviceConfig.resolution_;
+ if (deviceConfig.resolution_ == ResolutionType::RESOLUTION_NONE ||
+ deviceConfig.resolution_ == ResolutionType::RESOLUTION_ANY) {
+ deviceRes = ResolutionType::RESOLUTION_MDPI;
+ }
+
+ if (bestRes > candidateRes) {
+ return IsLowerResolutionPreferred(
+ static_cast(bestRes), static_cast(candidateRes), static_cast(deviceRes));
+ }
+
+ if (bestRes < candidateRes) {
+ return !IsLowerResolutionPreferred(
+ static_cast(candidateRes), static_cast(bestRes), static_cast(deviceRes));
+ }
+
+ return false;
+}
+
+bool IsCandidateResConfigPreferred(
+ const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
+{
+ if ((candidateConfig.mcc_ != bestConfig.mcc_) && deviceConfig.mcc_) {
+ return candidateConfig.mcc_;
+ }
+ if ((candidateConfig.mnc_ != bestConfig.mnc_) && deviceConfig.mnc_) {
+ return candidateConfig.mnc_;
+ }
+
+ if (bestConfig.orientation_ != candidateConfig.orientation_ &&
+ deviceConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
+ return candidateConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED;
+ }
+
+ if (bestConfig.deviceType_ != DeviceType::UNKNOWN || candidateConfig.deviceType_ != DeviceType::UNKNOWN) {
+ if (bestConfig.deviceType_ != candidateConfig.deviceType_) {
+ return candidateConfig.deviceType_ != DeviceType::UNKNOWN;
+ }
+ }
+
+ if (bestConfig.colorMode_ != candidateConfig.colorMode_) {
+ return candidateConfig.colorMode_ == deviceConfig.colorMode_;
+ }
+
+ return IsCandidateResolutionPreferred(deviceConfig, bestConfig, candidateConfig);
+}
+
+void SortResConfigs(
+ const AceResConfig& desiredConfig, std::vector& candidateConfigs, int32_t left, int32_t right)
+{
+ if (left < right) {
+ AceResConfig bestConfig = candidateConfigs[left];
+ int32_t i = left;
+ int32_t j = right;
+ while (i < j) {
+ while (i < j && !IsCandidateResConfigPreferred(desiredConfig, bestConfig, candidateConfigs[j])) {
+ j--;
+ }
+ candidateConfigs[i] = candidateConfigs[j];
+ while (i < j && IsCandidateResConfigPreferred(desiredConfig, bestConfig, candidateConfigs[i])) {
+ i++;
+ }
+ candidateConfigs[j] = candidateConfigs[i];
+ }
+ candidateConfigs[i] = bestConfig;
+ SortResConfigs(desiredConfig, candidateConfigs, left, i - 1);
+ SortResConfigs(desiredConfig, candidateConfigs, i + 1, right);
+ }
+}
+
+bool IsOrientationMatch(const AceResConfig& desired, const AceResConfig& supported)
+{
+ return supported.orientation_ == DeviceOrientation::ORIENTATION_UNDEFINED ||
+ supported.orientation_ == desired.orientation_;
+}
+
+bool IsDeviceTypeMatch(const AceResConfig& desired, const AceResConfig& supported)
+{
+ return supported.deviceType_ == DeviceType::UNKNOWN || supported.deviceType_ == desired.deviceType_;
+}
+
+bool IsColorModeMatch(const AceResConfig& desired, const AceResConfig& supported)
+{
+ return supported.colorMode_ == ColorMode::COLOR_MODE_UNDEFINED || supported.colorMode_ == desired.colorMode_;
+}
+
+bool IsMccMncMatch(const AceResConfig& desired, const AceResConfig& supported)
+{
+ if (supported.mcc_ != 0 && supported.mcc_ != desired.mcc_) {
+ return false;
+ }
+ return !(supported.mnc_ != 0 && supported.mnc_ != desired.mnc_);
+}
+
+bool IsResolutionMatch(const AceResConfig& desired, const AceResConfig& supported)
+{
+ return supported.resolution_ == ResolutionType::RESOLUTION_NONE || supported.resolution_ == desired.resolution_;
+}
+
+bool MatchResConfig(const AceResConfig& desired, const AceResConfig& supported)
+{
+ return !(!IsOrientationMatch(desired, supported) || !IsDeviceTypeMatch(desired, supported) ||
+ !IsColorModeMatch(desired, supported) || !IsMccMncMatch(desired, supported) ||
+ !IsResolutionMatch(desired, supported));
+}
+
+} // namespace
+
+bool AceResConfig::operator==(const AceResConfig& other) const
+{
+ return language_ == other.language_ && script_ == other.script_ && region_ == other.region_ && mcc_ == other.mcc_ &&
+ mnc_ == other.mnc_ && orientation_ == other.orientation_ && colorMode_ == other.colorMode_ &&
+ deviceType_ == other.deviceType_ && resolution_ == other.resolution_;
+}
+
+void AceResConfig::MatchAndSortI18nConfigs(const std::vector& candidatesFiles,
+ const std::string& devicesLocaleTag, std::vector& fileList)
+{
+ std::vector candidateLocaleConfigs;
+ for (auto& file : candidatesFiles) {
+ AceResConfig LocaleConfig = ConvertLocaleTagToConfig(file);
+ if (file == ConvertLocaleConfigToTag(LocaleConfig)) {
+ candidateLocaleConfigs.emplace_back(LocaleConfig);
+ }
+ }
+ AceResConfig deviceLocaleConfig = ConvertLocaleTagToConfig(devicesLocaleTag);
+ // Compute Script when it is not provided.
+ if (deviceLocaleConfig.script_.empty()) {
+ deviceLocaleConfig.script_ = ComputeScript(deviceLocaleConfig);
+ }
+ std::vector matchedLocaleConfigs;
+ MatchLocaleConfig(candidateLocaleConfigs, deviceLocaleConfig, matchedLocaleConfigs);
+ int32_t left = 0;
+ int32_t right = matchedLocaleConfigs.size() - 1;
+ SortLocaleConfigs(matchedLocaleConfigs, deviceLocaleConfig, left, right);
+ bool existDefault = false;
+ for (const auto& matchedLocaleConfig : matchedLocaleConfigs) {
+ std::string localeConfigTag = ConvertLocaleConfigToTag(matchedLocaleConfig);
+ if (localeConfigTag == "en-US") {
+ existDefault = true;
+ }
+ fileList.emplace_back(localeConfigTag);
+ }
+
+ if (!existDefault) {
+ fileList.emplace_back("en-US");
+ }
+}
+
+void AceResConfig::MatchAndSortResConfigs(const std::vector& candidateFiles,
+ const std::string& deviceResTag, std::vector& matchedFileList)
+{
+ std::vector candidateResConfigs;
+ for (auto& file : candidateFiles) {
+ AceResConfig ResConfig = ConvertResTagToConfig(file);
+ if (file == ConvertResConfigToTag(ResConfig)) {
+ candidateResConfigs.emplace_back(ResConfig);
+ }
+ }
+
+ AceResConfig deviceResConfig = ConvertResTagToConfig(deviceResTag);
+ int32_t candidateConfigSize = candidateResConfigs.size();
+ std::vector matchedResConfigs;
+ for (auto i = 0; i < candidateConfigSize; i++) {
+ if (!MatchResConfig(deviceResConfig, candidateResConfigs[i])) {
+ continue;
+ } else {
+ matchedResConfigs.emplace_back(candidateResConfigs[i]);
+ }
+ }
+ int32_t left = 0;
+ int32_t right = matchedResConfigs.size() - 1;
+ SortResConfigs(deviceResConfig, matchedResConfigs, left, right);
+ for (const auto& matchedConfig : matchedResConfigs) {
+ matchedFileList.emplace_back(ConvertResConfigToTag(matchedConfig));
+ }
+ matchedFileList.emplace_back("res-defaults");
+}
+
+void AceResConfig::GetConfigString(KeyType type, int32_t value, std::string& buf)
+{
+ std::string appending;
+ if (!buf.empty()) {
+ appending = "-";
+ }
+
+ switch (type) {
+ case KeyType::ORIENTATION:
+ appending.append(
+ AceResKeyParser::GetInstance().GetOrientationByType(static_cast(value)));
+ break;
+ case KeyType::DEVICETYPE:
+ appending.append(AceResKeyParser::GetInstance().GetDeviceByType(static_cast(value)));
+ break;
+ case KeyType::RESOLUTION:
+ appending.append(AceResKeyParser::GetInstance().GetResolutionByType(static_cast(value)));
+ break;
+ case KeyType::COLOR_MODE:
+ appending.append(AceResKeyParser::GetInstance().GetColorModeByType(static_cast(value)));
+ break;
+ case KeyType::MCC:
+ appending.append(AceResKeyParser::GetInstance().GetMccByValue(value));
+ break;
+ case KeyType::MNC_SHORT_LEN:
+ appending.append(AceResKeyParser::GetInstance().GetMncShortLenByValue(value));
+ break;
+ case KeyType::MNC:
+ appending.append(AceResKeyParser::GetInstance().GetMncByValue(value));
+ break;
+ default:
+ break;
+ }
+ buf.append(appending);
+}
+
+bool AceResConfig::ParseConfig(const std::vector& keyParams)
+{
+ for (auto keyParam : keyParams) {
+ switch (keyParam.keyType) {
+ case KeyType::RESOLUTION:
+ resolution_ = static_cast(keyParam.value);
+ break;
+ case KeyType::ORIENTATION:
+ orientation_ = static_cast(keyParam.value);
+ break;
+ case KeyType::DEVICETYPE:
+ deviceType_ = static_cast(keyParam.value);
+ break;
+ case KeyType::COLOR_MODE:
+ colorMode_ = static_cast(keyParam.value);
+ break;
+ case KeyType::MCC:
+ mcc_ = keyParam.value;
+ break;
+ case KeyType::MNC:
+ mnc_ = keyParam.value;
+ break;
+ case KeyType::MNC_SHORT_LEN:
+ mnc_ = keyParam.value;
+ mncShortLen_ = true;
+ break;
+ default:
+ LOGE("unknown KeyType:%{public}d", keyParam.keyType);
+ break;
+ }
+ }
+ return true;
+}
+
+ResolutionType AceResConfig::GetResolutionType(double resolution)
+{
+ static const LinearEnumMapNode resolutionMap[] = {
+ { ResolutionType::RESOLUTION_LDPI,
+ [](double resolution) { return GreatNotEqual(resolution, 0.0) && LessNotEqual(resolution, 0.875); } },
+ { ResolutionType::RESOLUTION_MDPI,
+ [](double resolution) { return GreatOrEqual(resolution, 0.875) && LessNotEqual(resolution, 1.25); } },
+ { ResolutionType::RESOLUTION_HDPI,
+ [](double resolution) { return GreatOrEqual(resolution, 1.25) && LessNotEqual(resolution, 1.75); } },
+ { ResolutionType::RESOLUTION_XHDPI,
+ [](double resolution) { return GreatOrEqual(resolution, 1.75) && LessNotEqual(resolution, 2.5); } },
+ { ResolutionType::RESOLUTION_XXHDPI,
+ [](double resolution) { return GreatOrEqual(resolution, 2.5) && LessNotEqual(resolution, 3.5); } },
+ { ResolutionType::RESOLUTION_XXXHDPI, [](double resolution) { return GreatOrEqual(resolution, 3.5); } },
+ };
+
+ for (const auto& idx : resolutionMap) {
+ if (idx.value(resolution)) {
+ return idx.key;
+ }
+ }
+ return ResolutionType::RESOLUTION_MDPI;
+}
+
+AceResConfig AceResConfig::ConvertResTagToConfig(const std::string& deviceResConfigTag)
+{
+ AceResConfig resConfig;
+ std::vector keyParams;
+ bool parseSucceed = AceResKeyParser::GetInstance().Parse(deviceResConfigTag, keyParams);
+ if (parseSucceed) {
+ resConfig.ParseConfig(keyParams);
+ }
+ return resConfig;
+}
+
+std::string AceResConfig::ConvertResConfigToTag(const AceResConfig& resConfig)
+{
+ std::string resTag = "res";
+ if (resConfig.mcc_ != MCC_UNDEFINED && resConfig.mnc_ != MNC_UNDEFINED) {
+ GetConfigString(KeyType::MCC, resConfig.mcc_, resTag);
+ if (resConfig.mncShortLen_) {
+ GetConfigString(KeyType::MNC_SHORT_LEN, resConfig.mnc_, resTag);
+ } else {
+ GetConfigString(KeyType::MNC, resConfig.mnc_, resTag);
+ }
+ }
+
+ if (resConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
+ GetConfigString(KeyType::ORIENTATION, static_cast(resConfig.orientation_), resTag);
+ }
+
+ if (resConfig.colorMode_ != ColorMode::COLOR_MODE_UNDEFINED) {
+ GetConfigString(KeyType::COLOR_MODE, static_cast(resConfig.colorMode_), resTag);
+ }
+
+ if (resConfig.deviceType_ != DeviceType::UNKNOWN) {
+ GetConfigString(KeyType::DEVICETYPE, static_cast(resConfig.deviceType_), resTag);
+ }
+
+ if (resConfig.resolution_ != ResolutionType::RESOLUTION_NONE) {
+ GetConfigString(KeyType::RESOLUTION, static_cast(resConfig.resolution_), resTag);
+ }
+ return resTag;
+}
+
+} // namespace OHOS::Ace
\ No newline at end of file
diff --git a/adapter/common/cpp/ace_res_config.h b/adapter/common/cpp/ace_res_config.h
new file mode 100644
index 00000000..12803cae
--- /dev/null
+++ b/adapter/common/cpp/ace_res_config.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_CONFIG_H
+#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_CONFIG_H
+
+#include
+#include
+#include
+
+#include "adapter/common/cpp/ace_res_data_struct.h"
+
+namespace OHOS::Ace {
+class AceResConfig {
+public:
+ AceResConfig() = default;
+ ~AceResConfig() = default;
+ AceResConfig(const AceResConfig& config) = default;
+ AceResConfig& operator=(const AceResConfig& config) = default;
+ AceResConfig(const std::string& language, const std::string& script, const std::string& region)
+ : language_(language), script_(script), region_(region)
+ {}
+
+ AceResConfig(int32_t mcc, int32_t mnc, DeviceOrientation orientation, ColorMode colorMode, DeviceType deviceType,
+ ResolutionType resolution)
+ : mcc_(mcc), mnc_(mnc), orientation_(orientation), colorMode_(colorMode), deviceType_(deviceType),
+ resolution_(resolution)
+ {}
+
+ bool operator==(const AceResConfig& other) const;
+ static void MatchAndSortI18nConfigs(const std::vector& candidatesFiles,
+ const std::string& devicesLocaleTag, std::vector& fileList);
+ static void MatchAndSortResConfigs(const std::vector& candidateFiles,
+ const std::string& deviceConfigTag, std::vector& viableFileList);
+ static void GetConfigString(KeyType type, int32_t value, std::string& buf);
+ bool ParseConfig(const std::vector& keyParams);
+ static ResolutionType GetResolutionType(double resolution);
+ static AceResConfig ConvertResTagToConfig(const std::string& deviceResConfigTag);
+ static std::string ConvertResConfigToTag(const AceResConfig& resConfig);
+
+ std::string language_;
+ std::string script_;
+ std::string region_;
+ int32_t mcc_ = MCC_UNDEFINED;
+ int32_t mnc_ = MNC_UNDEFINED;
+ bool mncShortLen_ = false;
+ DeviceOrientation orientation_ = DeviceOrientation::ORIENTATION_UNDEFINED;
+ ColorMode colorMode_ = ColorMode::COLOR_MODE_UNDEFINED;
+ DeviceType deviceType_ = DeviceType::UNKNOWN;
+ ResolutionType resolution_ = ResolutionType::RESOLUTION_NONE;
+};
+} // namespace OHOS::Ace
+
+#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_CONFIG_H
\ No newline at end of file
diff --git a/adapter/common/cpp/ace_res_data_struct.h b/adapter/common/cpp/ace_res_data_struct.h
new file mode 100644
index 00000000..fcb0c809
--- /dev/null
+++ b/adapter/common/cpp/ace_res_data_struct.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_DATA_STRUCT_H
+#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_DATA_STRUCT_H
+
+#include
+#include
+
+#include "base/utils/system_properties.h"
+
+namespace OHOS::Ace {
+enum class KeyType : int32_t {
+ MCC = 0,
+ MNC = 1,
+ MNC_SHORT_LEN = 2,
+ ORIENTATION = 3,
+ COLOR_MODE = 4,
+ DEVICETYPE = 5,
+ RESOLUTION = 6,
+};
+
+struct KeyParam {
+ KeyType keyType;
+ int32_t value;
+};
+
+} // namespace OHOS::Ace
+
+#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_DATA_STRUCT_H
\ No newline at end of file
diff --git a/adapter/common/cpp/ace_res_key_parser.cpp b/adapter/common/cpp/ace_res_key_parser.cpp
new file mode 100644
index 00000000..8328362b
--- /dev/null
+++ b/adapter/common/cpp/ace_res_key_parser.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 "adapter/common/cpp/ace_res_key_parser.h"
+
+#ifdef WINDOWS_PLATFORM
+#include
+#else
+#include "securec.h"
+#endif
+#include
+#include
+
+#include "base/log/log.h"
+#include "base/utils/string_utils.h"
+
+namespace OHOS::Ace {
+namespace {
+
+constexpr int32_t MCC_MNC_KEYWORD_LEN = 3;
+constexpr int32_t MCC_MNC_VALUE_LEN = 3;
+constexpr int32_t MAX_MCC_MNC_LEN = 8;
+
+const std::unordered_map RES_RESOLUTION = {
+ { "ldpi", ResolutionType::RESOLUTION_LDPI },
+ { "mdpi", ResolutionType::RESOLUTION_MDPI },
+ { "hdpi", ResolutionType::RESOLUTION_HDPI },
+ { "xhdpi", ResolutionType::RESOLUTION_XHDPI },
+ { "xxhdpi", ResolutionType::RESOLUTION_XXHDPI },
+ { "xxxhdpi", ResolutionType::RESOLUTION_XXXHDPI },
+};
+
+const std::unordered_map RES_ORIENTATION = {
+ { "horizontal", DeviceOrientation::LANDSCAPE },
+ { "vertical", DeviceOrientation::PORTRAIT }
+};
+
+const std::unordered_map RES_COLOR_MODE = {
+ { "dark", ColorMode::DARK },
+};
+
+const std::unordered_map RES_DEVICE_TYPE = {
+ { "phone", DeviceType::PHONE },
+ { "tablet", DeviceType::TABLET },
+ { "tv", DeviceType::TV },
+ { "wearable", DeviceType::WATCH },
+};
+
+}
+
+AceResKeyParser::AceResKeyParser() = default;
+AceResKeyParser::~AceResKeyParser() = default;
+
+bool AceResKeyParser::Parse(const std::string& deviceResConfigTag, std::vector &keyParams)
+{
+ std::vector keyParts;
+ StringUtils::StringSpliter(deviceResConfigTag, '-', keyParts);
+
+ static parse_key_function functions[] = {
+ ParseMcc,
+ ParseMnc,
+ ParseOrientation,
+ ParseColorMode,
+ ParseDeviceType,
+ ParseResolution,
+ ParseDefaults,
+ };
+ const int32_t FUNC_LEN = sizeof(functions) / sizeof(functions[0]);
+ if (!keyParts.empty()) {
+ if (!ParseMatch(keyParts, keyParams, functions, FUNC_LEN)) {
+ LOGE("Invalid config:%{public}s", deviceResConfigTag.c_str());
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool AceResKeyParser::ParseMatch(const std::vector& keys, std::vector &keyParams,
+ parse_key_function functions[], int32_t funcLen) const
+{
+ for (auto iter = keys.begin(); iter != keys.end(); iter++) {
+ // currently, the first key part must be res
+ if (iter == keys.begin()) {
+ if (*iter == "res") {
+ continue;
+ } else {
+ LOGE("Invalid first key part:%{private}s", iter->c_str());
+ return false;
+ }
+ }
+ bool parseRet = false;
+ for (int32_t k = 0; k < funcLen; k++) {
+ if (functions[k](*iter, keyParams)) {
+ parseRet = true;
+ break;
+ }
+ }
+ if (!parseRet) {
+ LOGE("Invalid key:%{private}s", iter->c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
+bool AceResKeyParser::ParseMcc(const std::string& key, std::vector& keyParams)
+{
+ std::regex mcc("mcc(\\d{3})");
+ if (regex_match(key, mcc)) {
+ KeyParam keyParam;
+ keyParam.value = StringUtils::StringToInt(key.substr(MCC_MNC_KEYWORD_LEN));
+ keyParam.keyType = KeyType::MCC;
+ keyParams.emplace_back(keyParam);
+ return true;
+ }
+ return false;
+}
+
+bool AceResKeyParser::ParseMnc(const std::string& key, std::vector& keyParams)
+{
+ std::regex mnc("mnc(\\d{2,3})");
+ if (regex_match(key, mnc)) {
+ KeyParam keyParam;
+ keyParam.value = StringUtils::StringToInt(key.substr(MCC_MNC_KEYWORD_LEN));
+ if (key.substr(MCC_MNC_KEYWORD_LEN).length() == MCC_MNC_VALUE_LEN) {
+ keyParam.keyType = KeyType::MNC;
+ } else {
+ keyParam.keyType = KeyType::MNC_SHORT_LEN;
+ }
+ keyParams.emplace_back(keyParam);
+ return true;
+ }
+ return false;
+}
+
+bool AceResKeyParser::ParseOrientation(const std::string& key, std::vector& keyParams)
+{
+ auto iter = RES_ORIENTATION.find(key);
+ if (iter != RES_ORIENTATION.end()) {
+ KeyParam keyParam;
+ keyParam.keyType = KeyType::ORIENTATION;
+ keyParam.value = static_cast(iter->second);
+ keyParams.emplace_back(keyParam);
+ return true;
+ }
+ return false;
+}
+
+bool AceResKeyParser::ParseColorMode(const std::string& key, std::vector& keyParams)
+{
+ auto iter = RES_COLOR_MODE.find(key);
+ if (iter != RES_COLOR_MODE.end()) {
+ KeyParam keyParam;
+ keyParam.keyType = KeyType::COLOR_MODE;
+ keyParam.value = static_cast(iter->second);
+ keyParams.emplace_back(keyParam);
+ return true;
+ }
+ return false;
+}
+
+bool AceResKeyParser::ParseDeviceType(const std::string& key, std::vector& keyParams)
+{
+ auto iter = RES_DEVICE_TYPE.find(key);
+ if (iter != RES_DEVICE_TYPE.end()) {
+ KeyParam keyParam;
+ keyParam.keyType = KeyType::DEVICETYPE;
+ keyParam.value = static_cast(iter->second);
+ keyParams.emplace_back(keyParam);
+ return true;
+ }
+ return false;
+}
+
+bool AceResKeyParser::ParseResolution(const std::string& key, std::vector& keyParams)
+{
+ auto iter = RES_RESOLUTION.find(key);
+ if (iter != RES_RESOLUTION.end()) {
+ KeyParam keyParam;
+ keyParam.keyType = KeyType::RESOLUTION;
+ keyParam.value = static_cast(iter->second);
+ keyParams.emplace_back(keyParam);
+ return true;
+ }
+ return false;
+}
+
+bool AceResKeyParser::ParseDefaults(const std::string& key, std::vector& keyParams)
+{
+ return key == "defaults";
+}
+
+std::string AceResKeyParser::GetMccByValue(uint32_t value) const
+{
+ char mccStr[MAX_MCC_MNC_LEN] = {0};
+ if (sprintf_s(mccStr, MAX_MCC_MNC_LEN, "mcc%03d", value) < 0) {
+ LOGE("output mcc exception");
+ return "";
+ }
+ return std::string(mccStr);
+}
+
+std::string AceResKeyParser::GetMncShortLenByValue(uint32_t value) const
+{
+ char mncStr[MAX_MCC_MNC_LEN] = {0};
+ if (sprintf_s(mncStr, MAX_MCC_MNC_LEN, "mnc%02d", value) < 0) {
+ LOGE("output mnc short len exception");
+ return "";
+ }
+ return std::string(mncStr);
+}
+
+std::string AceResKeyParser::GetMncByValue(uint32_t value) const
+{
+ char mncStr[MAX_MCC_MNC_LEN] = {0};
+ if (sprintf_s(mncStr, MAX_MCC_MNC_LEN, "mnc%03d", value) < 0) {
+ LOGE("output mnc len exception");
+ return "";
+ }
+ return std::string(mncStr);
+}
+
+std::string AceResKeyParser::GetOrientationByType(DeviceOrientation type) const
+{
+ auto item = find_if(RES_ORIENTATION.begin(), RES_ORIENTATION.end(),
+ [type](auto iter) { return iter.second == type; });
+ if (item != RES_ORIENTATION.end()) {
+ return item->first;
+ }
+ return "";
+}
+
+std::string AceResKeyParser::GetColorModeByType(ColorMode type) const
+{
+ auto item = find_if(RES_COLOR_MODE.begin(), RES_COLOR_MODE.end(),
+ [type](auto iter) { return iter.second == type; });
+ if (item != RES_COLOR_MODE.end()) {
+ return item->first;
+ }
+ return "";
+}
+
+std::string AceResKeyParser::GetDeviceByType(DeviceType type) const
+{
+ auto deviceTypeItem = find_if(RES_DEVICE_TYPE.begin(), RES_DEVICE_TYPE.end(),
+ [type](auto iter) { return iter.second == type; });
+ if (deviceTypeItem != RES_DEVICE_TYPE.end()) {
+ return deviceTypeItem->first;
+ }
+ return "";
+}
+
+std::string AceResKeyParser::GetResolutionByType(ResolutionType type) const
+{
+ auto resolutionItem = find_if(RES_RESOLUTION.begin(), RES_RESOLUTION.end(),
+ [type](auto iter) { return iter.second == type; });
+ if (resolutionItem != RES_RESOLUTION.end()) {
+ return resolutionItem->first;
+ }
+ return "";
+}
+
+} // namespace OHOS::Ace
\ No newline at end of file
diff --git a/adapter/common/cpp/ace_res_key_parser.h b/adapter/common/cpp/ace_res_key_parser.h
new file mode 100644
index 00000000..cebf1e11
--- /dev/null
+++ b/adapter/common/cpp/ace_res_key_parser.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_KEY_PARSER_H
+#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_KEY_PARSER_H
+
+#include
+#include
+#include
+
+#include "adapter/common/cpp/ace_res_data_struct.h"
+#include "base/utils/singleton.h"
+
+namespace OHOS::Ace {
+using parse_key_function = std::function&)>;
+
+class AceResKeyParser final : public Singleton {
+ DECLARE_SINGLETON(AceResKeyParser);
+ ACE_DISALLOW_MOVE(AceResKeyParser);
+
+public:
+ bool Parse(const std::string& deviceResConfigTag, std::vector& keyParams);
+ std::string GetMccByValue(uint32_t value) const;
+ std::string GetMncByValue(uint32_t value) const;
+ std::string GetMncShortLenByValue(uint32_t value) const;
+ std::string GetOrientationByType(DeviceOrientation type) const;
+ std::string GetColorModeByType(ColorMode type) const;
+ std::string GetDeviceByType(DeviceType type) const;
+ std::string GetResolutionByType(ResolutionType type) const;
+
+private:
+ bool ParseMatch(const std::vector& keys, std::vector& keyParams,
+ parse_key_function functions[], int32_t funcLen) const;
+ static bool ParseMcc(const std::string& key, std::vector& keyParams);
+ static bool ParseMnc(const std::string& key, std::vector& keyParams);
+ static bool ParseOrientation(const std::string& key, std::vector& keyParams);
+ static bool ParseColorMode(const std::string& key, std::vector& keyParams);
+ static bool ParseDeviceType(const std::string& key, std::vector& keyParams);
+ static bool ParseResolution(const std::string& key, std::vector& keyParams);
+ static bool ParseDefaults(const std::string& key, std::vector& keyParams);
+};
+
+} // namespace OHOS::Ace
+
+#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_KEY_PARSER_H
\ No newline at end of file
diff --git a/adapter/common/cpp/ace_trace.cpp b/adapter/common/cpp/ace_trace.cpp
new file mode 100644
index 00000000..f0fbc940
--- /dev/null
+++ b/adapter/common/cpp/ace_trace.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 "base/log/ace_trace.h"
+
+#ifndef WINDOWS_PLATFORM
+#include "securec.h"
+#endif
+
+namespace OHOS::Ace {
+namespace {
+
+const size_t MAX_STRING_SIZE = 128;
+
+}
+
+bool AceTraceBeginWithArgv(const char* format, va_list args)
+{
+ char name[MAX_STRING_SIZE] = { 0 };
+ if (vsnprintf_s(name, sizeof(name), sizeof(name) - 1, format, args) < 0) {
+ return false;
+ }
+ AceTraceBegin(name);
+ return true;
+}
+
+} // namespace OHOS::Ace
diff --git a/adapter/common/cpp/file_asset_provider.cpp b/adapter/common/cpp/file_asset_provider.cpp
new file mode 100644
index 00000000..b7f57b56
--- /dev/null
+++ b/adapter/common/cpp/file_asset_provider.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 "adapter/common/cpp/file_asset_provider.h"
+
+#include
+
+#include "base/log/ace_trace.h"
+#include "base/log/log.h"
+
+namespace OHOS::Ace {
+
+FileAssetProvider::~FileAssetProvider()
+{
+}
+
+bool FileAssetProvider::Initialize(const std::string& packagePath, const std::vector& assetBasePaths)
+{
+ ACE_SCOPED_TRACE("Initialize");
+ if (packagePath.empty() || assetBasePaths.empty()) {
+ LOGE("the packagePath or assetBasePath is empty");
+ return false;
+ }
+ assetBasePaths_ = assetBasePaths;
+ packagePath_ = packagePath;
+ return true;
+}
+
+bool FileAssetProvider::IsValid() const
+{
+ return true;
+}
+
+class FileAssetMapping : public fml::Mapping {
+public:
+ FileAssetMapping(std::unique_ptr data, size_t size) : data_(std::move(data)), size_(size) {}
+
+ ~FileAssetMapping() override {}
+
+ size_t GetSize() const override
+ {
+ return size_;
+ }
+
+ const uint8_t* GetMapping() const override
+ {
+ return data_.get();
+ }
+
+private:
+ std::unique_ptr data_ = nullptr;
+ size_t size_ = 0;
+};
+
+std::unique_ptr FileAssetProvider::GetAsMapping(const std::string& assetName) const
+{
+ ACE_SCOPED_TRACE("GetAsMapping");
+ LOGD("assert name is: %{public}s", assetName.c_str());
+ std::lock_guard lock(mutex_);
+
+ for (const auto& basePath: assetBasePaths_) {
+ std::string fileName = packagePath_ + basePath + assetName;
+ std::FILE* fp = std::fopen(fileName.c_str(), "r");
+ if (fp == nullptr) {
+ continue;
+ }
+
+ if (std::fseek(fp, 0, SEEK_END) != 0) {
+ LOGE("seek file tail error");
+ std::fclose(fp);
+ continue;
+ }
+
+ long size = std::ftell(fp);
+ uint8_t* dataArray = new (std::nothrow) uint8_t[size];
+ if (dataArray == nullptr) {
+ LOGE("new uint8_t array failed");
+ std::fclose(fp);
+ continue;
+ }
+
+ rewind(fp);
+ std::unique_ptr data(dataArray);
+ size_t result = std::fread(data.get(), 1, size, fp);
+ if (result != (size_t)size) {
+ LOGE("read file failed");
+ std::fclose(fp);
+ continue;
+ }
+
+ fclose(fp);
+ return std::make_unique(std::move(data), size);
+ }
+ return nullptr;
+}
+
+std::string FileAssetProvider::GetAssetPath(const std::string& assetName)
+{
+ auto filePath = filePathMap_.find(assetName);
+ if (filePath == filePathMap_.end()) {
+ return "";
+ }
+ std::string assetPath;
+ assetPath.append(packagePath_).append("!/").append(filePath->second);
+ return assetPath;
+}
+
+} // namespace OHOS::Ace
diff --git a/adapter/common/cpp/file_asset_provider.h b/adapter/common/cpp/file_asset_provider.h
new file mode 100644
index 00000000..c866bfe6
--- /dev/null
+++ b/adapter/common/cpp/file_asset_provider.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_FILE_ASSET_PROVIDER_H
+#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_FILE_ASSET_PROVIDER_H
+
+#include
+#include
+#include
+
+#include "contrib/minizip/unzip.h"
+#include "flutter/assets/asset_resolver.h"
+#include "flutter/fml/mapping.h"
+
+#include "base/utils/macros.h"
+
+namespace OHOS::Ace {
+
+class ACE_EXPORT FileAssetProvider : public flutter::AssetResolver {
+public:
+ FileAssetProvider() = default;
+ ~FileAssetProvider() override;
+
+ bool Initialize(const std::string& packagePath, const std::vector& assetBasePaths);
+
+ bool IsValid() const override;
+
+ std::unique_ptr GetAsMapping(const std::string& assetName) const override;
+
+ std::string GetAssetPath(const std::string& assetName);
+
+private:
+ std::unordered_map fileMap_;
+ mutable std::mutex mutex_;
+ std::unordered_map filePathMap_;
+ std::string packagePath_;
+ std::vector assetBasePaths_;
+};
+
+} // namespace OHOS::Ace
+
+#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_FILE_ASSET_PROVIDER_H
diff --git a/adapter/common/cpp/flutter_asset_manager.h b/adapter/common/cpp/flutter_asset_manager.h
new file mode 100644
index 00000000..0e6b90dc
--- /dev/null
+++ b/adapter/common/cpp/flutter_asset_manager.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_ASSET_MANAGER_H
+#define FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_ASSET_MANAGER_H
+
+#include
+
+#include "flutter/assets/asset_resolver.h"
+#include "flutter/fml/mapping.h"
+
+#include "base/log/event_report.h"
+#include "base/memory/ace_type.h"
+#include "base/resource/asset_manager.h"
+#include "base/utils/macros.h"
+
+namespace OHOS::Ace {
+
+class FlutterAsset final : public Asset {
+public:
+ explicit FlutterAsset(std::unique_ptr mapping) : mapping_(std::move(mapping)) {}
+ ~FlutterAsset() override = default;
+
+ size_t GetSize() const override
+ {
+ return mapping_ ? mapping_->GetSize() : 0;
+ }
+
+ const uint8_t* GetData() const override
+ {
+ return mapping_ ? mapping_->GetMapping() : nullptr;
+ }
+
+private:
+ std::unique_ptr mapping_;
+};
+
+class FlutterAssetManager final : public AssetManager {
+ DECLARE_ACE_TYPE(FlutterAssetManager, AssetManager);
+
+public:
+ FlutterAssetManager() = default;
+ ~FlutterAssetManager() override = default;
+
+ void PushFront(std::unique_ptr provider)
+ {
+ if (!provider || !provider->IsValid()) {
+ return;
+ }
+ providers_.push_front(std::move(provider));
+ }
+
+ void PushBack(std::unique_ptr provider)
+ {
+ if (!provider || !provider->IsValid()) {
+ return;
+ }
+ providers_.push_back(std::move(provider));
+ }
+
+ RefPtr GetAsset(const std::string& assetName) override
+ {
+ if (assetName.empty()) {
+ return nullptr;
+ }
+
+ for (const auto& provider : providers_) {
+ auto mapping = provider->GetAsMapping(assetName);
+ if (mapping) {
+ return AceType::MakeRefPtr(std::move(mapping));
+ }
+ }
+ LOGE("find asset failed, assetName = %{private}s", assetName.c_str());
+ return nullptr;
+ }
+
+private:
+ std::deque> providers_;
+};
+
+} // namespace OHOS::Ace
+
+#endif // FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_ASSET_MANAGER_H
diff --git a/adapter/common/cpp/flutter_task_executor.cpp b/adapter/common/cpp/flutter_task_executor.cpp
new file mode 100644
index 00000000..b445be16
--- /dev/null
+++ b/adapter/common/cpp/flutter_task_executor.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 "adapter/common/cpp/flutter_task_executor.h"
+
+#include
+#include
+#include
+#include
+
+#ifdef FML_EMBEDDER_ONLY
+#undef FML_EMBEDDER_ONLY
+#define FML_EMBEDDER_ONLY
+#endif
+#include "flutter/fml/message_loop.h"
+#include "flutter/shell/platform/ohos/platform_task_runner_adapter.h"
+
+#include "base/log/log.h"
+#include "base/thread/background_task_executor.h"
+
+namespace OHOS::Ace {
+namespace {
+
+constexpr int32_t GPU_THREAD_PRIORITY = -10;
+constexpr int32_t UI_THREAD_PRIORITY = -8;
+
+inline std::string GenJsThreadName()
+{
+ static std::atomic instanceCount { 1 };
+ return std::string("jsThread-") + std::to_string(instanceCount.fetch_add(1, std::memory_order_relaxed));
+}
+
+bool PostTaskToTaskRunner(const fml::RefPtr& taskRunner, TaskExecutor::Task&& task, uint32_t delayTime)
+{
+ if (!taskRunner || !task) {
+ return false;
+ }
+
+ if (delayTime > 0) {
+ taskRunner->PostDelayedTask(std::move(task), fml::TimeDelta::FromMilliseconds(delayTime));
+ } else {
+ taskRunner->PostTask(std::move(task));
+ }
+ return true;
+}
+
+void SetThreadPriority(int32_t priority)
+{
+ if (setpriority(PRIO_PROCESS, gettid(), priority) < 0) {
+ LOGW("Failed to set thread priority, errno = %{private}d", errno);
+ }
+}
+
+} // namespace
+
+FlutterTaskExecutor::~FlutterTaskExecutor()
+{
+ // To guarantee the jsThread released in platform thread
+ auto rawPtr = jsThread_.release();
+ PostTaskToTaskRunner(
+ platformRunner_, [rawPtr] { std::unique_ptr jsThread(rawPtr); }, 0);
+}
+
+void FlutterTaskExecutor::InitPlatformThread()
+{
+ platformRunner_ = flutter::PlatformTaskRunnerAdapter::CurrentTaskRunner();
+}
+
+void FlutterTaskExecutor::InitJsThread(bool newThread)
+{
+ if (newThread) {
+ jsThread_ = std::make_unique(GenJsThreadName());
+ jsRunner_ = jsThread_->GetTaskRunner();
+ } else {
+ jsRunner_ = uiRunner_;
+ }
+}
+
+void FlutterTaskExecutor::InitOtherThreads(const flutter::TaskRunners& taskRunners)
+{
+ uiRunner_ = taskRunners.GetUITaskRunner();
+ ioRunner_ = taskRunners.GetIOTaskRunner();
+ gpuRunner_ = taskRunners.GetGPUTaskRunner();
+
+ PostTaskToTaskRunner(
+ uiRunner_, [] { SetThreadPriority(UI_THREAD_PRIORITY); }, 0);
+ PostTaskToTaskRunner(
+ gpuRunner_, [] { SetThreadPriority(GPU_THREAD_PRIORITY); }, 0);
+}
+
+bool FlutterTaskExecutor::OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const
+{
+ switch (type) {
+ case TaskType::PLATFORM:
+ return PostTaskToTaskRunner(platformRunner_, std::move(task), delayTime);
+ case TaskType::UI:
+ return PostTaskToTaskRunner(uiRunner_, std::move(task), delayTime);
+ case TaskType::IO:
+ return PostTaskToTaskRunner(ioRunner_, std::move(task), delayTime);
+ case TaskType::GPU:
+ return PostTaskToTaskRunner(gpuRunner_, std::move(task), delayTime);
+ case TaskType::JS:
+ return PostTaskToTaskRunner(jsRunner_, std::move(task), delayTime);
+ case TaskType::BACKGROUND:
+ // Ignore delay time
+ return BackgroundTaskExecutor::GetInstance().PostTask(std::move(task));
+ default:
+ return false;
+ }
+}
+
+bool FlutterTaskExecutor::WillRunOnCurrentThread(TaskType type) const
+{
+ switch (type) {
+ case TaskType::PLATFORM:
+ return platformRunner_ ? platformRunner_->RunsTasksOnCurrentThread() : false;
+ case TaskType::UI:
+ return uiRunner_ ? uiRunner_->RunsTasksOnCurrentThread() : false;
+ case TaskType::IO:
+ return ioRunner_ ? ioRunner_->RunsTasksOnCurrentThread() : false;
+ case TaskType::GPU:
+ return gpuRunner_ ? gpuRunner_->RunsTasksOnCurrentThread() : false;
+ case TaskType::JS:
+ return jsRunner_ ? jsRunner_->RunsTasksOnCurrentThread() : false;
+ case TaskType::BACKGROUND:
+ // Always return false for background tasks.
+ return false;
+ default:
+ return false;
+ }
+}
+
+void FlutterTaskExecutor::AddTaskObserver(Task&& callback)
+{
+ fml::MessageLoop::GetCurrent().AddTaskObserver(reinterpret_cast(this), std::move(callback));
+}
+
+void FlutterTaskExecutor::RemoveTaskObserver()
+{
+ fml::MessageLoop::GetCurrent().RemoveTaskObserver(reinterpret_cast(this));
+}
+
+} // namespace OHOS::Ace
diff --git a/adapter/common/cpp/flutter_task_executor.h b/adapter/common/cpp/flutter_task_executor.h
new file mode 100644
index 00000000..7bda52f0
--- /dev/null
+++ b/adapter/common/cpp/flutter_task_executor.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_TASK_EXECUTOR_H
+#define FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_TASK_EXECUTOR_H
+
+#include "flutter/common/task_runners.h"
+#include "flutter/fml/thread.h"
+
+#include "base/thread/task_executor.h"
+#include "base/utils/macros.h"
+
+namespace OHOS::Ace {
+
+class ACE_EXPORT FlutterTaskExecutor final : public TaskExecutor {
+ DECLARE_ACE_TYPE(FlutterTaskExecutor, TaskExecutor);
+
+public:
+ ~FlutterTaskExecutor() final;
+ // Must call this method on platform thread
+ void InitPlatformThread();
+ void InitJsThread(bool newThread = true);
+ void InitOtherThreads(const flutter::TaskRunners& taskRunners);
+
+ void AddTaskObserver(Task&& callback) override;
+ void RemoveTaskObserver() override;
+ bool WillRunOnCurrentThread(TaskType type) const final;
+
+private:
+ bool OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const final;
+
+ std::unique_ptr jsThread_;
+
+ fml::RefPtr platformRunner_;
+ fml::RefPtr uiRunner_;
+ fml::RefPtr ioRunner_;
+ fml::RefPtr jsRunner_;
+ fml::RefPtr gpuRunner_;
+};
+
+} // namespace OHOS::Ace
+
+#endif // FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_TASK_EXECUTOR_H
diff --git a/adapter/common/cpp/flutter_window.cpp b/adapter/common/cpp/flutter_window.cpp
new file mode 100644
index 00000000..a2581c69
--- /dev/null
+++ b/adapter/common/cpp/flutter_window.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 "adapter/common/cpp/flutter_window.h"
+
+#include
+
+#include "flutter/runtime/window_manager.h"
+
+#include "base/log/log.h"
+#include "core/common/ace_view.h"
+#include "core/pipeline/base/render_node.h"
+
+namespace OHOS::Ace {
+
+std::unique_ptr PlatformWindow::Create(AceView* view)
+{
+ if (view != nullptr) {
+ return std::make_unique(view->GetInstanceId());
+ } else {
+ return nullptr;
+ }
+}
+
+namespace Platform {
+
+FlutterWindow::FlutterWindow(int32_t instanceId) : instanceId_(instanceId) {}
+
+FlutterWindow::~FlutterWindow() {}
+
+void FlutterWindow::RequestFrame()
+{
+ auto window = flutter::WindowManager::GetWindow(instanceId_);
+ if (window != nullptr) {
+ window->ScheduleFrame();
+ if (!window->HasBeginFrameCallback()) {
+ window->SetBeginFrameCallback(std::bind(&FlutterWindow::OnVsyncCallback, this, std::placeholders::_1));
+ }
+ }
+}
+
+void FlutterWindow::RegisterVsyncCallback(AceVsyncCallback&& callback)
+{
+ vsyncCallbacks_.emplace_back(std::move(callback));
+}
+
+void FlutterWindow::SetRootRenderNode(const RefPtr& root) {}
+
+void FlutterWindow::OnVsyncCallback(uint64_t timeStampNanos)
+{
+ for (const auto& vsyncCallback : vsyncCallbacks_) {
+ vsyncCallback(timeStampNanos, 0);
+ }
+}
+
+} // namespace Platform
+} // namespace OHOS::Ace
diff --git a/adapter/common/cpp/flutter_window.h b/adapter/common/cpp/flutter_window.h
new file mode 100644
index 00000000..ad5dc977
--- /dev/null
+++ b/adapter/common/cpp/flutter_window.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_FLUTTER_WINDOW_H
+#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_FLUTTER_WINDOW_H
+
+#include
+
+#include "base/utils/noncopyable.h"
+#include "core/common/platform_window.h"
+
+namespace OHOS::Ace::Platform {
+
+class FlutterWindow final : public PlatformWindow {
+public:
+ explicit FlutterWindow(int32_t instanceId);
+ ~FlutterWindow() override;
+
+ // Platform window interface
+ void RequestFrame() override;
+ void RegisterVsyncCallback(AceVsyncCallback&& callback) override;
+ void SetRootRenderNode(const RefPtr& root) override;
+
+ // Vsync callback
+ void OnVsyncCallback(uint64_t timeStampNanos);
+
+private:
+ std::vector vsyncCallbacks_;
+ int32_t instanceId_;
+
+ ACE_DISALLOW_COPY_AND_MOVE(FlutterWindow);
+};
+
+} // namespace OHOS::Ace::Platform
+
+#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_FLUTTER_WINDOW_H
diff --git a/adapter/common/cpp/localization.cpp b/adapter/common/cpp/localization.cpp
new file mode 100644
index 00000000..c9a5474c
--- /dev/null
+++ b/adapter/common/cpp/localization.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 "base/i18n/localization.h"
+
+#include
+
+#ifndef WINDOWS_PLATFORM
+#include "securec.h"
+#endif
+
+namespace OHOS::Ace {
+namespace {
+
+const size_t MAX_FORMAT_BUFFER = 256;
+
+}
+
+const std::string FormatEntry(const char* fmt, ...)
+{
+ char buf[MAX_FORMAT_BUFFER] = { 0 };
+ bool ret = false;
+ va_list args;
+ va_start(args, fmt);
+ if (vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, fmt, args) < 0) {
+ ret = true;
+ }
+ va_end(args);
+ return ret ? "" : buf;
+}
+
+} // namespace OHOS::Ace
diff --git a/adapter/common/cpp/multimodal/fake_multimodal_subscriber.h b/adapter/common/cpp/multimodal/fake_multimodal_subscriber.h
new file mode 100644
index 00000000..f996e206
--- /dev/null
+++ b/adapter/common/cpp/multimodal/fake_multimodal_subscriber.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_MULTIMODAL_FAKE_MULTIMODAL_SUBSCRIBER_H
+#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_MULTIMODAL_FAKE_MULTIMODAL_SUBSCRIBER_H
+
+#include "core/event/multimodal/multimodal_subscriber.h"
+
+namespace OHOS::Ace::Platform {
+
+class FakeMultimodalSubscriber : public MultimodalSubscriber {
+ DECLARE_ACE_TYPE(FakeMultimodalSubscriber, MultimodalSubscriber)
+
+public:
+ FakeMultimodalSubscriber() = default;
+ ~FakeMultimodalSubscriber() override = default;
+
+ void RegisterCallback(const std::function& callback,
+ const std::function& successCallback) override {}
+ bool SubscribeVoiceEvents(const std::vector& voiceEvents) override
+ {
+ return false;
+ }
+ void UnSubscribeVoiceEvents(const std::vector& voiceEvents) override {}
+ void UnSubscribeAllEvents() override {}
+};
+
+} // namespace OHOS::Ace::Platform
+
+#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_MULTIMODAL_FAKE_MULTIMODAL_SUBSCRIBER_H
diff --git a/adapter/common/cpp/thread_util.cpp b/adapter/common/cpp/thread_util.cpp
new file mode 100644
index 00000000..7eb0bf26
--- /dev/null
+++ b/adapter/common/cpp/thread_util.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 "base/thread/thread_util.h"
+
+#include
+
+namespace OHOS::Ace {
+
+void SetCurrentThreadName(const std::string& name)
+{
+#ifdef MAC_PLATFORM
+ pthread_setname_np(name.c_str());
+#else
+ pthread_setname_np(pthread_self(), name.c_str());
+#endif
+}
+
+} // namespace OHOS::Ace
diff --git a/adapter/ohos/cpp/BUILD.gn b/adapter/ohos/cpp/BUILD.gn
new file mode 100644
index 00000000..6385a536
--- /dev/null
+++ b/adapter/ohos/cpp/BUILD.gn
@@ -0,0 +1,63 @@
+# Copyright (c) 2021 Huawei Device 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/ohos.gni")
+import("//foundation/ace/ace_engine/ace_config.gni")
+
+# build static
+template("ace_base_platform_source_set") {
+ # get is_ohos_platform
+ forward_variables_from(invoker, "*")
+
+ ohos_source_set(target_name) {
+ defines += invoker.defines
+
+ sources = [
+ "$ace_root/adapter/ohos/cpp/ace_ability.cpp",
+ "$ace_root/adapter/ohos/cpp/ace_application_info.cpp",
+ "$ace_root/adapter/ohos/cpp/ace_container.cpp",
+ "$ace_root/adapter/ohos/cpp/flutter_ace_view.cpp",
+ ]
+
+ configs = [
+ "$ace_root:ace_config",
+ "$flutter_root:flutter_config",
+ "$flutter_root:icu_config_$platform",
+ ]
+
+ include_dirs = [ "//utils/native/base/include" ]
+
+ deps = [
+ "$flutter_root:ace_skia_$platform",
+ "//base/global/resmgr_standard/frameworks/resmgr:global_resmgr",
+ "//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native",
+ "//foundation/graphic/standard:libwms_client",
+ "//third_party/zlib:libz",
+ ]
+
+ external_deps = [
+ "aafwk_standard:ability_manager",
+ "aafwk_standard:want",
+ "appexecfwk_standard:appexecfwk_base",
+ "appexecfwk_standard:appexecfwk_core",
+ "appexecfwk_standard:libeventhandler",
+ "ipc:ipc_core",
+ "multimodalinput_base:mmi_event",
+ ]
+ }
+}
+
+ace_base_platform_source_set("ace_base_platform_ohos") {
+ defines = ace_ohos_defines
+ platform = "ohos"
+}
diff --git a/adapter/ohos/cpp/ace_ability.cpp b/adapter/ohos/cpp/ace_ability.cpp
new file mode 100644
index 00000000..c3a0edff
--- /dev/null
+++ b/adapter/ohos/cpp/ace_ability.cpp
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 "adapter/ohos/cpp/ace_ability.h"
+
+#include "adapter/ohos/cpp/ace_container.h"
+#include "adapter/ohos/cpp/flutter_ace_view.h"
+#include "base/log/log.h"
+#include "core/common/ace_application_info.h"
+#include "core/common/frontend.h"
+#include "init_data.h"
+#include "touch_event.h"
+
+#include "locale_info.h"
+#include "res_config.h"
+#include "resource_manager.h"
+
+namespace OHOS {
+namespace Ace {
+namespace {
+FrontendType GetFrontendTypeFromManifest(const std::string& packagePathStr)
+{
+ auto manifestPath = packagePathStr + std::string("assets/js/default/manifest.json");
+ char realPath[PATH_MAX] = { 0x00 };
+ if (realpath(manifestPath.c_str(), realPath) == nullptr) {
+ LOGE("realpath fail! filePath: %{private}s, fail reason: %{public}s", manifestPath.c_str(), strerror(errno));
+ LOGE("return default frontend: JS frontend.");
+ return FrontendType::JS;
+ }
+ std::unique_ptr file(fopen(realPath, "rb"), fclose);
+ if (!file) {
+ LOGE("open file failed, filePath: %{private}s, fail reason: %{public}s", manifestPath.c_str(), strerror(errno));
+ LOGE("return default frontend: JS frontend.");
+ return FrontendType::JS;
+ }
+ if (std::fseek(file.get(), 0, SEEK_END) != 0) {
+ LOGE("seek file tail error, return default frontend: JS frontend.");
+ return FrontendType::JS;
+ }
+
+ long size = std::ftell(file.get());
+ char* fileData = new (std::nothrow) char[size];
+ if (fileData == nullptr) {
+ LOGE("new json buff failed, return default frontend: JS frontend.");
+ return FrontendType::JS;
+ }
+ rewind(file.get());
+ std::unique_ptr jsonStream(fileData);
+ size_t result = std::fread(jsonStream.get(), 1, size, file.get());
+ if (result != (size_t)size) {
+ LOGE("read file failed, return default frontend: JS frontend.");
+ return FrontendType::JS;
+ }
+
+ std::string jsonString(jsonStream.get(), jsonStream.get() + size);
+ auto rootJson = JsonUtil::ParseJsonString(jsonString);
+ std::string frontendType = rootJson->GetString("type");
+ if (frontendType == "normal") {
+ return FrontendType::JS;
+ } else if (frontendType == "form") {
+ return FrontendType::JS_CARD;
+ } else if (frontendType == "declarative") {
+ return FrontendType::DECLARATIVE_JS;
+ } else {
+ LOGE("frontend type not supported. return default frontend: JS frontend.");
+ return FrontendType::JS;
+ }
+}
+}
+
+using namespace OHOS::AAFwk;
+using namespace OHOS::AppExecFwk;
+
+using AcePlatformFinish = std::function;
+class AcePlatformEventCallback final : public Platform::PlatformEventCallback {
+public:
+ explicit AcePlatformEventCallback(AcePlatformFinish onFinish) : onFinish_(onFinish) {}
+
+ ~AcePlatformEventCallback() = default;
+
+ virtual void OnFinish() const
+ {
+ LOGI("AcePlatformEventCallback OnFinish");
+ if (onFinish_) {
+ onFinish_();
+ }
+ }
+
+ virtual void OnStatusBarBgColorChanged(uint32_t color)
+ {
+ LOGI("AcePlatformEventCallback OnStatusBarBgColorChanged");
+ }
+
+private:
+ AcePlatformFinish onFinish_;
+};
+
+int32_t AceAbility::instanceId_ = 0;
+const std::string AceAbility::START_PARAMS_KEY = "__startParams";
+const std::string AceAbility::PAGE_URI = "url";
+const std::string AceAbility::CONTINUE_PARAMS_KEY = "__remoteData";
+
+REGISTER_AA(AceAbility)
+void AceAbility::OnStart(const Want& want)
+{
+ Ability::OnStart(want);
+ LOGI("AceAbility::OnStart called");
+
+ SetHwIcuDirectory();
+
+ std::unique_ptr resConfig(Global::Resource::CreateResConfig());
+ auto resourceManager = GetResourceManager();
+ if (resourceManager != nullptr) {
+ resourceManager->GetResConfig(*resConfig);
+ auto localeInfo = resConfig->GetLocaleInfo();
+ AceApplicationInfo::GetInstance().SetResourceManager(resourceManager);
+ if (localeInfo != nullptr) {
+ auto language = localeInfo->GetLanguage();
+ auto region = localeInfo->GetRegion();
+ auto script = localeInfo->GetScript();
+ AceApplicationInfo::GetInstance().SetLocale(
+ (language == nullptr) ? "" : language,
+ (region == nullptr) ? "" : region,
+ (script == nullptr) ? "" : script,
+ "");
+ }
+ }
+
+ auto packagePathStr = GetBundleCodePath();
+ auto moduleInfo = GetHapModuleInfo();
+ if (moduleInfo != nullptr) {
+ packagePathStr += "/" + moduleInfo->name + "/";
+ }
+ FrontendType frontendType = GetFrontendTypeFromManifest(packagePathStr);
+
+ // create container
+ Platform::AceContainer::CreateContainer(
+ abilityId_, frontendType, this,
+ std::make_unique([this]() {
+ TerminateAbility();
+ }));
+ // create view.
+ auto flutterAceView = Platform::FlutterAceView::CreateView(abilityId_);
+ OHOS::Window* window = Ability::GetWindow().get();
+
+ auto&& touchEventCallback = [aceView = flutterAceView](OHOS::TouchEvent event) -> bool {
+ LOGD("RegistOnTouchCb touchEventCallback called");
+ return aceView->DispatchTouchEvent(aceView, event);
+ };
+ window->RegistOnTouchCb(touchEventCallback);
+
+ Platform::FlutterAceView::SurfaceCreated(flutterAceView, window);
+
+ // set metrics
+ BufferRequestConfig windowConfig;
+ window->GetRequestConfig(windowConfig);
+ LOGI("AceAbility: windowConfig: width: %{public}d, height: %{public}d", windowConfig.width, windowConfig.height);
+
+ flutter::ViewportMetrics metrics;
+ metrics.physical_width = windowConfig.width;
+ metrics.physical_height = windowConfig.height;
+ Platform::FlutterAceView::SetViewportMetrics(flutterAceView, metrics);
+
+ // add asset path.
+ auto assetBasePathStr = { std::string("assets/js/default/"), std::string("assets/js/share/") };
+ Platform::AceContainer::AddAssetPath(abilityId_, packagePathStr, assetBasePathStr);
+ // set view
+ Platform::AceContainer::SetView(flutterAceView, density_, windowConfig.width, windowConfig.height);
+ Platform::FlutterAceView::SurfaceChanged(flutterAceView, windowConfig.width, windowConfig.height, 0);
+
+ // get url
+ std::string parsedPageUrl;
+ if (!remotePageUrl_.empty()) {
+ parsedPageUrl = remotePageUrl_;
+ } else if (!pageUrl_.empty()) {
+ parsedPageUrl = pageUrl_;
+ } else if (want.HasParameter(PAGE_URI)) {
+ parsedPageUrl = want.GetStringParam(PAGE_URI);
+ } else {
+ parsedPageUrl = "";
+ }
+
+ // run page.
+ Platform::AceContainer::RunPage(
+ abilityId_, Platform::AceContainer::GetContainer(abilityId_)->GeneratePageId(),
+ parsedPageUrl, want.GetStringParam(START_PARAMS_KEY));
+
+ Platform::AceContainer::OnRestoreData(abilityId_, remoteData_);
+ LOGI("AceAbility::OnStart called End");
+}
+
+void AceAbility::OnStop()
+{
+ LOGI("AceAbility::OnStop called ");
+ Ability::OnStop();
+ Platform::AceContainer::DestroyContainer(abilityId_);
+ LOGI("AceAbility::OnStop called End");
+}
+
+void AceAbility::OnActive()
+{
+ LOGI("AceAbility::OnActive called ");
+ Ability::OnActive();
+ Platform::AceContainer::OnActive(abilityId_);
+ LOGI("AceAbility::OnActive called End");
+}
+
+void AceAbility::OnForeground(const Want& want)
+{
+ LOGI("AceAbility::OnForeground called ");
+ Ability::OnForeground(want);
+ Platform::AceContainer::OnShow(abilityId_);
+ LOGI("AceAbility::OnForeground called End");
+}
+
+void AceAbility::OnBackground()
+{
+ LOGI("AceAbility::OnBackground called ");
+ Ability::OnBackground();
+ Platform::AceContainer::OnHide(abilityId_);
+ LOGI("AceAbility::OnBackground called End");
+}
+
+void AceAbility::OnInactive()
+{
+ LOGI("AceAbility::OnInactive called ");
+ Ability::OnInactive();
+ Platform::AceContainer::OnInactive(abilityId_);
+ LOGI("AceAbility::OnInactive called End");
+}
+
+void AceAbility::OnBackPressed()
+{
+ LOGI("AceAbility::OnBackPressed called ");
+ if (!Platform::AceContainer::OnBackPressed(abilityId_)) {
+ LOGI("AceAbility::OnBackPressed: passed to Ability to process");
+ Ability::OnBackPressed();
+ }
+ LOGI("AceAbility::OnBackPressed called End");
+}
+
+void AceAbility::OnNewWant(const Want& want)
+{
+ LOGI("AceAbility::OnNewWant called ");
+ Ability::OnNewWant(want);
+ std::string params = want.GetStringParam(START_PARAMS_KEY);
+ Platform::AceContainer::OnNewRequest(abilityId_, params);
+ LOGI("AceAbility::OnNewWant called End");
+}
+
+void AceAbility::OnRestoreAbilityState(const PacMap& inState)
+{
+ LOGI("AceAbility::OnRestoreAbilityState called ");
+ Ability::OnRestoreAbilityState(inState);
+ LOGI("AceAbility::OnRestoreAbilityState called End");
+}
+
+void AceAbility::OnSaveAbilityState(PacMap& outState)
+{
+ LOGI("AceAbility::OnSaveAbilityState called ");
+ Ability::OnSaveAbilityState(outState);
+ LOGI("AceAbility::OnSaveAbilityState called End");
+}
+
+void AceAbility::OnConfigurationUpdated(const Configuration& configuration)
+{
+ LOGI("AceAbility::OnConfigurationUpdated called ");
+ Ability::OnConfigurationUpdated(configuration);
+ LOGI("AceAbility::OnConfigurationUpdated called End");
+}
+
+}
+} // namespace OHOS::Ace
diff --git a/adapter/ohos/cpp/ace_ability.h b/adapter/ohos/cpp/ace_ability.h
new file mode 100644
index 00000000..ae55c233
--- /dev/null
+++ b/adapter/ohos/cpp/ace_ability.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_ABILITY_H
+#define FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_ABILITY_H
+
+#include "ability.h"
+#include "ability_loader.h"
+#include "want.h"
+
+namespace OHOS::Ace {
+
+class AceAbility final : public OHOS::AppExecFwk::Ability {
+public:
+ AceAbility()
+ {
+ abilityId_ = instanceId_;
+ instanceId_++;
+ }
+ virtual ~AceAbility() = default;
+
+ void OnStart(const OHOS::AAFwk::Want& want) override;
+ void OnStop() override;
+ void OnActive() override;
+ void OnInactive() override;
+ void OnForeground(const OHOS::AAFwk::Want& want) override;
+ void OnBackground() override;
+ void OnBackPressed() override;
+ void OnNewWant(const OHOS::AAFwk::Want& want) override;
+ void OnRestoreAbilityState(const OHOS::AppExecFwk::PacMap& inState) override;
+ void OnSaveAbilityState(OHOS::AppExecFwk::PacMap& outState) override;
+ void OnConfigurationUpdated(const OHOS::AppExecFwk::Configuration& configuration) override;
+
+private:
+ static int32_t instanceId_;
+ static const std::string START_PARAMS_KEY;
+ static const std::string PAGE_URI;
+ static const std::string CONTINUE_PARAMS_KEY;
+
+ int32_t abilityId_ = 0;
+ float density_ = 1.0f;
+ std::string remotePageUrl_;
+ std::string remoteData_;
+ std::string pageUrl_;
+};
+
+} // namespace OHOS::Ace
+
+#endif // FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_ABILITY_H
diff --git a/adapter/ohos/cpp/ace_application_info.cpp b/adapter/ohos/cpp/ace_application_info.cpp
new file mode 100755
index 00000000..f1db9cf0
--- /dev/null
+++ b/adapter/ohos/cpp/ace_application_info.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 "adapter/ohos/cpp/ace_application_info.h"
+
+#include
+#include
+#include
+
+#include "contrib/minizip/unzip.h"
+#include "unicode/locid.h"
+
+#include "adapter/common/cpp/ace_res_config.h"
+#include "adapter/common/cpp/ace_res_data_struct.h"
+#include "base/i18n/localization.h"
+#include "base/log/ace_trace.h"
+#include "base/log/log.h"
+#include "core/common/ace_engine.h"
+
+#include "init_data.h"
+
+namespace OHOS::Ace::Platform {
+
+AceApplicationInfoImpl::AceApplicationInfoImpl() {}
+
+AceApplicationInfoImpl::~AceApplicationInfoImpl() = default;
+
+void AceApplicationInfoImpl::SetJsEngineParam(const std::string& key, const std::string& value)
+{
+ jsEngineParams_[key] = value;
+}
+
+std::string AceApplicationInfoImpl::GetJsEngineParam(const std::string& key) const
+{
+ std::string value;
+ auto iter = jsEngineParams_.find(key);
+ if (iter != jsEngineParams_.end()) {
+ value = iter->second;
+ }
+ return value;
+}
+
+void AceApplicationInfoImpl::ChangeLocale(const std::string& language, const std::string& countryOrRegion)
+{
+ std::string languageLower;
+ std::transform(language.begin(), language.end(), languageLower.begin(), ::tolower);
+
+ std::string countryOrRegionUpper;
+ std::transform(countryOrRegion.begin(), countryOrRegion.end(), countryOrRegionUpper.begin(), ::tolower);
+
+ std::unique_ptr resConfig(Global::Resource::CreateResConfig());
+ resourceManager_->GetResConfig(*resConfig);
+
+ auto localeInfo = resConfig->GetLocaleInfo();
+ if (localeInfo == nullptr) {
+ LOGE("get local info failed");
+ return;
+ }
+
+ auto script = localeInfo->GetScript();
+ resConfig->SetLocaleInfo(languageLower.c_str(), script, countryOrRegionUpper.c_str());
+ resourceManager_->UpdateResConfig(*resConfig);
+
+ SetLocale(languageLower, countryOrRegionUpper, (script == nullptr) ? "" : script, "");
+}
+
+std::vector AceApplicationInfoImpl::GetLocaleFallback(const std::vector& localeList) const
+{
+ ACE_SCOPED_TRACE("GetLocaleFallback");
+ std::vector fileList;
+ AceResConfig::MatchAndSortI18nConfigs(localeList, localeTag_, fileList);
+ return fileList;
+}
+
+void AceApplicationInfoImpl::SetLocale(
+ const std::string& language,
+ const std::string& countryOrRegion,
+ const std::string& script,
+ const std::string& keywordsAndValues)
+{
+ language_ = language;
+ countryOrRegion_ = countryOrRegion;
+ script_ = script;
+ keywordsAndValues_ = keywordsAndValues;
+
+ localeTag_ = language;
+ if (!script_.empty()) {
+ localeTag_.append("-" + script_);
+ }
+ localeTag_.append("-" + countryOrRegion_);
+
+ icu::Locale locale(language_.c_str(), countryOrRegion.c_str());
+ isRightToLeft_ = locale.isRightToLeft();
+
+ auto languageList = Localization::GetLanguageList(language_);
+ if (languageList.size() == 1) {
+ Localization::SetLocale(
+ language_, countryOrRegion_, script, languageList.front(), keywordsAndValues_);
+ } else {
+ auto selectLanguage = GetLocaleFallback(languageList);
+ Localization::SetLocale(
+ language_, countryOrRegion_, script, selectLanguage.front(), keywordsAndValues_);
+ }
+}
+
+bool AceApplicationInfoImpl::GetFiles(const std::string& filePath, std::vector& fileList) const
+{
+ const auto& packagePath = AceEngine::Get().GetPackagePath();
+ const auto& assetBasePathSet = AceEngine::Get().GetAssetBasePath();
+ if (packagePath.empty() || assetBasePathSet.empty()) {
+ LOGE("the packagePath or assetBasePathSet is empty");
+ return false;
+ }
+
+ for (const auto& assetBasePath : assetBasePathSet) {
+ std::string dirPath = packagePath + assetBasePath + filePath;
+ DIR* dir = opendir(dirPath.c_str());
+ if (dir == nullptr) {
+ continue;
+ }
+ struct dirent* dirEntry = readdir(dir);
+ while (dirEntry != nullptr) {
+ std::string file = dirEntry->d_name;
+ std::string fullPath = dirPath + file;
+ dirEntry = readdir(dir);
+
+ struct stat st;
+ if (stat(fullPath.c_str(), &st) != 0 || !S_ISREG(st.st_mode)) {
+ continue;
+ }
+ fileList.emplace_back(file);
+ }
+ closedir(dir);
+ }
+ return true;
+}
+
+std::vector AceApplicationInfoImpl::SplitLocale(const std::string& desireLocales)
+{
+ std::vector ret;
+ if (desireLocales.empty()) {
+ ret.emplace_back("en-US");
+ return ret;
+ }
+
+ size_t rpos = -1;
+ auto pos = desireLocales.find(',');
+ while (pos != std::string::npos) {
+ ret.emplace_back(desireLocales.substr(rpos + 1, pos - rpos - 1));
+ rpos = pos;
+ pos = desireLocales.find(',', rpos + 1);
+ }
+ ret.emplace_back(desireLocales.substr(rpos + 1, desireLocales.length() - rpos - 1));
+
+ return ret;
+}
+
+bool AceApplicationInfoImpl::GetBundleInfo(const std::string& packageName, AceBundleInfo& bundleInfo)
+{
+ return false;
+}
+
+AceApplicationInfoImpl& AceApplicationInfoImpl::GetInstance()
+{
+ static AceApplicationInfoImpl instance;
+ return instance;
+}
+
+} // namespace OHOS::Ace::Platform
+
+namespace OHOS::Ace {
+
+AceApplicationInfo& AceApplicationInfo::GetInstance()
+{
+ return Platform::AceApplicationInfoImpl::GetInstance();
+}
+
+} // namespace OHOS::Ace
diff --git a/adapter/ohos/cpp/ace_application_info.h b/adapter/ohos/cpp/ace_application_info.h
new file mode 100755
index 00000000..eb8db223
--- /dev/null
+++ b/adapter/ohos/cpp/ace_application_info.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021 Huawei Device 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_APPLICATION_INFO_H
+#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_APPLICATION_INFO_H
+
+#include