diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..2ab7ff6
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,106 @@
+---
+Language: Cpp
+AccessModifierOffset: -4
+AlignAfterOpenBracket: DontAlign
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Left
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Empty
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: Yes
+BinPackArguments: true
+BinPackParameters: true
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: true
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ AfterExternBlock: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+ SplitEmptyFunction: false
+ SplitEmptyRecord: false
+ SplitEmptyNamespace: false
+BreakBeforeBinaryOperators: None
+BreakBeforeInheritanceComma: false
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: BeforeColon
+BreakInheritanceList: BeforeColon
+BreakStringLiterals: true
+BreakAfterJavaFieldAnnotations: true
+ColumnLimit: 120
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+DisableFormat: false
+FixNamespaceComments: true
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^"(base|core|elements|rendering|adapter|dsl|frameworks|resource|accessibility|bridge)/'
+ Priority: 3
+ - Regex: '<*>'
+ Priority: 1
+ - Regex: '.*'
+ Priority: 2
+IndentCaseLabels: true
+IndentPPDirectives: None
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 39
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 80
+PointerAlignment: Left
+ReflowComments: true
+SortIncludes: true
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: true
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInCStyleCastParentheses: false
+SpacesInContainerLiterals: true
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 4
+UseTab: Never
+...
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..95e6cdc
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright (c) 2022 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")
+
+group("ui_appearance_packages") {
+ deps = [
+ "etc/para:ui_appearance.para",
+ "etc/para:ui_appearance.para.dac",
+ "sa_profile:arkui_ui_appearance_sa_profiles",
+ "interfaces/kits/napi:uiappearance",
+ "services:ui_appearance_service",
+ ]
+}
+
+
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..4947287
--- /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 0000000..27154b0
--- /dev/null
+++ b/OAT.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.en.md b/README.en.md
deleted file mode 100644
index 5de2863..0000000
--- a/README.en.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# arkui_ui_appearance
-
-#### Description
-{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
-
-#### 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
deleted file mode 100644
index 6449b7e..0000000
--- a/README.md
+++ /dev/null
@@ -1,39 +0,0 @@
-# arkui_ui_appearance
-
-#### 介绍
-{**以下是 Gitee 平台说明,您可以替换此简介**
-Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
-无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
-
-#### 软件架构
-软件架构说明
-
-
-#### 安装教程
-
-1. xxxx
-2. xxxx
-3. xxxx
-
-#### 使用说明
-
-1. xxxx
-2. xxxx
-3. xxxx
-
-#### 参与贡献
-
-1. Fork 本仓库
-2. 新建 Feat_xxx 分支
-3. 提交代码
-4. 新建 Pull Request
-
-
-#### 特技
-
-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 0000000..ea762ba
--- /dev/null
+++ b/README_zh.md
@@ -0,0 +1,57 @@
+# 用户界面外观
+
+
+## 简介
+
+**内容介绍**:用户界面外观目前仅支持深色模式服务,提供了系统应用API,用于获取和设置系统的深浅色模式,同时可持久化保存当前配置的深浅色模式。
+
+**架构图**:
+
+
+
+
+## 目录
+
+深色模式服务源代码在/foundation/arkui/ui\_appearance下,目录结构如下图所示:
+
+```
+/foundation/arkui/ui_appearance
+├── etc
+│ └── para # 持久化配置文件存放目录
+│── interfaces/kits
+│ └── napi # napi外部接口存放目录
+│── sa_profile # 深色模式系统服务的配置文件
+│── services # 深色模式系统服务实现
+├── test # 接口单元测试
+```
+
+
+## 使用场景
+
+仅支持具有权限的系统应用通过API接口控制和切换当前用户界面的外观模式。
+
+
+## 说明
+
+### 接口说明
+
+| 接口名 | 描述 |
+| -------- | -------- |
+| setDarkMode(mode: DarkMode, callback: AsyncCallback\): void | 设置用户界面模式(深色或浅色),Callback方式。 |
+| setDarkMode(mode: DarkMode): Promise\ | 设置用户界面模式(深色或浅色),Promise方式。 |
+| getDarkMode(): DarkMode | 获取当前用户界面的模式(深色或浅色)。 |
+
+### 使用说明
+
+功能模块开发指导可参考[**开发指南**](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-uiappearance.md)
+
+
+## 相关仓
+
+[ArkUI框架子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/ArkUI%E6%A1%86%E6%9E%B6%E5%AD%90%E7%B3%BB%E7%BB%9F.md)
+
+[arkui\_napi](https://gitee.com/openharmony/arkui_napi)
+
+[arkui\_ace\_engine](https://gitee.com/openharmony/arkui_ace_engine/blob/master/README_zh.md)
+
+**arkui\_ui\_appearance**
\ No newline at end of file
diff --git a/bundle.json b/bundle.json
new file mode 100644
index 0000000..c71b9a7
--- /dev/null
+++ b/bundle.json
@@ -0,0 +1,50 @@
+{
+ "name": "@ohos/ui_appearance",
+ "description": "Provide ui_appearance management.",
+ "version": "3.2",
+ "license": "Apache License 2.0",
+ "publishAs": "code-segment",
+ "segment": {
+ "destpath": "foundation/arkui/ui_appearance"
+ },
+ "dirs": {},
+ "scripts": {},
+ "component": {
+ "name": "ui_appearance",
+ "subsystem": "arkui",
+ "syscap": [
+ "SystemCapability.ArkUI.UiAppearance"
+ ],
+ "features": [
+ ],
+ "adapted_system_type": [
+ "standard"
+ ],
+ "rom":"300KB",
+ "ram":"1024KB",
+ "deps": {
+ "components": [
+ "ipc",
+ "hiviewdfx_hilog_native",
+ "appexecfwk_standard",
+ "aafwk_standard",
+ "safwk",
+ "ability_runtime",
+ "ability_base",
+ "bundle_framework",
+ "samgr"
+ ],
+ "third_party": []
+ },
+ "build": {
+ "sub_component": [
+ "//foundation/arkui/ui_appearance:ui_appearance_packages"
+ ],
+ "inner_kits": [
+ ],
+ "test": [
+ "//foundation/arkui/ui_appearance/test/unittest:ui_appearance_test"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/etc/para/BUILD.gn b/etc/para/BUILD.gn
new file mode 100644
index 0000000..aa1a972
--- /dev/null
+++ b/etc/para/BUILD.gn
@@ -0,0 +1,29 @@
+# Copyright (C) 2022 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")
+
+ohos_prebuilt_etc("ui_appearance.para") {
+ source = "ui_appearance.para"
+ subsystem_name = "arkui"
+ part_name = "ui_appearance"
+ module_install_dir = "etc/param"
+}
+
+ohos_prebuilt_etc("ui_appearance.para.dac") {
+ source = "ui_appearance.para.dac"
+ subsystem_name = "arkui"
+ part_name = "ui_appearance"
+ module_install_dir = "etc/param"
+}
diff --git a/etc/para/ui_appearance.para b/etc/para/ui_appearance.para
new file mode 100644
index 0000000..937d083
--- /dev/null
+++ b/etc/para/ui_appearance.para
@@ -0,0 +1,14 @@
+# Copyright (C) 2022 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.
+
+persist.darkmode=light
diff --git a/etc/para/ui_appearance.para.dac b/etc/para/ui_appearance.para.dac
new file mode 100644
index 0000000..8581137
--- /dev/null
+++ b/etc/para/ui_appearance.para.dac
@@ -0,0 +1,15 @@
+# Copyright (c) 2022 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.
+
+persist.darkmode = uiserver:uiserver:0600
+
diff --git a/figures/uiAppearance-architecture_zh.png b/figures/uiAppearance-architecture_zh.png
new file mode 100644
index 0000000..f97fbb1
Binary files /dev/null and b/figures/uiAppearance-architecture_zh.png differ
diff --git a/interfaces/kits/napi/BUILD.gn b/interfaces/kits/napi/BUILD.gn
new file mode 100644
index 0000000..c89294e
--- /dev/null
+++ b/interfaces/kits/napi/BUILD.gn
@@ -0,0 +1,36 @@
+# Copyright (c) 2022 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")
+
+config("ui_appearance_interfaces_kits_napi_config") {
+ visibility = [ ":*" ]
+ include_dirs = [ "include" ]
+}
+
+ohos_shared_library("uiappearance") {
+ include_dirs = [ "include" ]
+ public_configs = [ ":ui_appearance_interfaces_kits_napi_config" ]
+ sources = [ "src/js_ui_appearance.cpp" ]
+
+ deps = [ "../../../services:ui_appearance_client" ]
+ external_deps = [
+ "napi:ace_napi",
+ "c_utils:utils",
+ "hiviewdfx_hilog_native:libhilog",
+ ]
+
+ relative_install_dir = "module"
+ subsystem_name = "arkui"
+ part_name = "ui_appearance"
+}
\ No newline at end of file
diff --git a/interfaces/kits/napi/include/js_ui_appearance.h b/interfaces/kits/napi/include/js_ui_appearance.h
new file mode 100644
index 0000000..b7753d8
--- /dev/null
+++ b/interfaces/kits/napi/include/js_ui_appearance.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2022 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 JS_UI_APPEARANCE_H
+#define JS_UI_APPEARANCE_H
+
+#include "napi/native_api.h"
+#include "napi/native_common.h"
+#include "napi/native_node_api.h"
+#include "ui_appearance_ability_client.h"
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+struct AsyncContext {
+ napi_env env = nullptr;
+ napi_async_work work = nullptr;
+ napi_deferred deferred = nullptr;
+ napi_ref callbackRef = nullptr;
+ int32_t jsSetArg = -1;
+ int32_t status = 0;
+ bool isArgsValid = true;
+ UiAppearanceAbilityInterface::DarkMode mode;
+};
+
+class JsDarkMode final {
+public:
+ enum EnumNapiResults { ERROR = 0, COMMON, BUTT };
+
+ static void OnExecute(napi_env env, void* data);
+ static void OnComplete(napi_env env, napi_status status, void* data);
+ static napi_status CheckArgs(napi_env env, size_t argc, napi_value* argv);
+ static UiAppearanceAbilityInterface::DarkMode ConvertJsDarkMode2Enum(int32_t jsVal);
+};
+
+napi_value JSSetDarkModeSync(napi_env env, napi_callback_info info);
+napi_value JSGetDarkModeSync(napi_env env, napi_callback_info info);
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
+#endif // JS_UI_APPEARANCE_H
\ No newline at end of file
diff --git a/interfaces/kits/napi/src/js_ui_appearance.cpp b/interfaces/kits/napi/src/js_ui_appearance.cpp
new file mode 100644
index 0000000..8a8936b
--- /dev/null
+++ b/interfaces/kits/napi/src/js_ui_appearance.cpp
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2022 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 "js_ui_appearance.h"
+
+#include "ui_appearance_log.h"
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+void JsDarkMode::OnExecute(napi_env env, void* data)
+{
+ JS_HILOG_INFO("OnExecute begin.");
+ AsyncContext* asyncContext = static_cast(data);
+ if (asyncContext->isArgsValid) {
+ auto res = UiAppearanceAbilityClient::GetInstance()->SetDarkMode(asyncContext->mode);
+ asyncContext->status = res;
+ }
+}
+
+void JsDarkMode::OnComplete(napi_env env, napi_status status, void* data)
+{
+ JS_HILOG_INFO("OnComplete begin.");
+ AsyncContext* asyncContext = static_cast(data);
+ napi_value result[EnumNapiResults::BUTT] = { 0 };
+
+ // set result
+ if (asyncContext->isArgsValid && asyncContext->status == UiAppearanceAbilityInterface::ErrCode::SUCCEEDED) {
+ napi_get_undefined(env, &result[EnumNapiResults::ERROR]);
+ napi_get_undefined(env, &result[EnumNapiResults::COMMON]);
+ } else {
+ std::string err;
+ napi_value message = nullptr;
+ if (!asyncContext->isArgsValid || asyncContext->status == UiAppearanceAbilityInterface::ErrCode::INVALID_ARG) {
+ err.assign("invalid argument.");
+ } else if (asyncContext->status == UiAppearanceAbilityInterface::ErrCode::PERMISSION_ERR) {
+ err.assign("permission verification failed.");
+ } else {
+ err.assign("system error.");
+ }
+ napi_create_string_utf8(env, err.c_str(), NAPI_AUTO_LENGTH, &message);
+ napi_create_error(env, nullptr, message, &result[EnumNapiResults::ERROR]);
+ napi_get_undefined(env, &result[EnumNapiResults::COMMON]);
+ }
+
+ if (asyncContext->deferred) { // promise
+ if (asyncContext->isArgsValid && asyncContext->status == UiAppearanceAbilityInterface::ErrCode::SUCCEEDED) {
+ napi_resolve_deferred(env, asyncContext->deferred, result[EnumNapiResults::COMMON]);
+ } else {
+ napi_reject_deferred(env, asyncContext->deferred, result[EnumNapiResults::ERROR]);
+ }
+ } else { // AsyncCallback
+ JS_HILOG_INFO("napi call function start.");
+ napi_value callback = nullptr;
+ napi_value returnValue = nullptr;
+ auto errCode =
+ (asyncContext->isArgsValid) ? asyncContext->status : UiAppearanceAbilityInterface::ErrCode::INVALID_ARG;
+ napi_create_int32(env, errCode, result);
+ napi_get_reference_value(env, asyncContext->callbackRef, &callback);
+ napi_call_function(env, nullptr, callback, EnumNapiResults::BUTT, result, &returnValue);
+ napi_delete_reference(env, asyncContext->callbackRef);
+ }
+ napi_delete_async_work(env, asyncContext->work);
+ delete asyncContext;
+}
+
+napi_status JsDarkMode::CheckArgs(napi_env env, size_t argc, napi_value* argv)
+{
+ if (argc < 1 || argc > 2) { // 1 and 2 is the number of arguments
+ return napi_invalid_arg;
+ }
+
+ napi_valuetype valueType = napi_undefined;
+ switch (argc) {
+ case 2: // 2 is the number of arguments
+ napi_typeof(env, argv[1], &valueType);
+ if (valueType != napi_function) {
+ return napi_invalid_arg;
+ }
+ [[fallthrough]];
+ case 1:
+ napi_typeof(env, argv[0], &valueType);
+ if (valueType != napi_number) {
+ return napi_invalid_arg;
+ }
+ break;
+ default:
+ return napi_invalid_arg;
+ }
+ return napi_ok;
+}
+
+UiAppearanceAbilityInterface::DarkMode JsDarkMode::ConvertJsDarkMode2Enum(int32_t jsVal)
+{
+ switch (jsVal) {
+ case 0:
+ return UiAppearanceAbilityInterface::DarkMode::ALWAYS_DARK;
+ case 1:
+ return UiAppearanceAbilityInterface::DarkMode::ALWAYS_LIGHT;
+ default:
+ return UiAppearanceAbilityInterface::DarkMode::UNKNOWN;
+ }
+}
+
+static napi_value JSSetDarkMode(napi_env env, napi_callback_info info)
+{
+ JS_HILOG_INFO("JSSetDarkMode begin.");
+
+ size_t argc = 2;
+ napi_value argv[2] = { 0 };
+ napi_status napiStatus = napi_ok;
+ do {
+ napiStatus = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
+ if (napiStatus != napi_ok) {
+ JS_HILOG_ERROR("get callback info failed.");
+ break;
+ }
+ napiStatus = JsDarkMode::CheckArgs(env, argc, argv);
+ if (napiStatus != napi_ok) {
+ JS_HILOG_ERROR("invalid argument.");
+ break;
+ }
+ } while (0);
+
+ auto asyncContext = new (std::nothrow) AsyncContext();
+ if (asyncContext == nullptr) {
+ JS_HILOG_ERROR("new AsyncContext failed.");
+ napi_value result = nullptr;
+ napi_get_undefined(env, &result);
+ return result;
+ }
+
+ asyncContext->isArgsValid = (napiStatus == napi_ok);
+ if (asyncContext->isArgsValid) {
+ napi_get_value_int32(env, argv[0], &asyncContext->jsSetArg);
+ asyncContext->mode = JsDarkMode::ConvertJsDarkMode2Enum(asyncContext->jsSetArg);
+ }
+ if (argc == 2) { // 2: the number of arguments
+ napi_create_reference(env, argv[1], 1, &asyncContext->callbackRef);
+ }
+
+ napi_value result = nullptr;
+ if (asyncContext->callbackRef == nullptr) {
+ napi_create_promise(env, &asyncContext->deferred, &result);
+ } else {
+ napi_get_undefined(env, &result);
+ }
+
+ napi_value resource = nullptr;
+ napi_create_string_utf8(env, "JSSetDarkMode", NAPI_AUTO_LENGTH, &resource);
+ napi_create_async_work(env, nullptr, resource, JsDarkMode::OnExecute, JsDarkMode::OnComplete,
+ reinterpret_cast(asyncContext), &asyncContext->work);
+ napi_queue_async_work(env, asyncContext->work);
+
+ return result;
+}
+
+static napi_value JSGetDarkMode(napi_env env, napi_callback_info info)
+{
+ JS_HILOG_INFO("JSGetDarkMode begin.");
+
+ size_t argc = 0;
+ NAPI_CALL(env, napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr));
+ NAPI_ASSERT(env, argc == 0, "requires no parameter");
+
+ UiAppearanceAbilityInterface::DarkMode mode = UiAppearanceAbilityClient::GetInstance()->GetDarkMode();
+ napi_value result;
+ NAPI_CALL(env, napi_create_int32(env, mode, &result));
+ return result;
+}
+
+EXTERN_C_START
+static napi_value UiAppearanceExports(napi_env env, napi_value exports)
+{
+ napi_value DarkMode = nullptr;
+ napi_value alwaysDark = nullptr;
+ napi_value alwaysLight = nullptr;
+ NAPI_CALL(env, napi_create_int32(env, 0, &alwaysDark));
+ NAPI_CALL(env, napi_create_int32(env, 1, &alwaysLight));
+ NAPI_CALL(env, napi_create_object(env, &DarkMode));
+ NAPI_CALL(env, napi_set_named_property(env, DarkMode, "ALWAYS_DARK", alwaysDark));
+ NAPI_CALL(env, napi_set_named_property(env, DarkMode, "ALWAYS_LIGHT", alwaysLight));
+ napi_property_descriptor properties[] = {
+ DECLARE_NAPI_FUNCTION("setDarkMode", JSSetDarkMode),
+ DECLARE_NAPI_FUNCTION("getDarkMode", JSGetDarkMode),
+ DECLARE_NAPI_STATIC_PROPERTY("DarkMode", DarkMode),
+ };
+ NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties));
+ return exports;
+}
+EXTERN_C_END
+
+static napi_module ui_appearance_module = {
+ .nm_version = 1,
+ .nm_flags = 0,
+ .nm_filename = nullptr,
+ .nm_register_func = UiAppearanceExports,
+ .nm_modname = "uiAppearance", // relative to the module name while import.
+ .nm_priv = nullptr,
+ .reserved = { 0 },
+};
+
+extern "C" __attribute__((constructor)) void UiAppearanceRegister()
+{
+ napi_module_register(&ui_appearance_module);
+}
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
diff --git a/sa_profile/7002.xml b/sa_profile/7002.xml
new file mode 100644
index 0000000..a6f2ba2
--- /dev/null
+++ b/sa_profile/7002.xml
@@ -0,0 +1,26 @@
+
+
+
+ ui_service
+
+ 7002
+ libui_appearance_service.z.so
+ true
+ false
+ 1
+
+
+
diff --git a/sa_profile/BUILD.gn b/sa_profile/BUILD.gn
new file mode 100644
index 0000000..0890f58
--- /dev/null
+++ b/sa_profile/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright (c) 2022 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("//build/ohos/sa_profile/sa_profile.gni")
+
+ohos_sa_profile("arkui_ui_appearance_sa_profiles") {
+ sources = [ "7002.xml" ]
+ part_name = "ui_appearance"
+}
diff --git a/services/BUILD.gn b/services/BUILD.gn
new file mode 100644
index 0000000..d6a8cc2
--- /dev/null
+++ b/services/BUILD.gn
@@ -0,0 +1,63 @@
+# Copyright (C) 2022 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")
+
+config("ui_appearance_service_config") {
+ visibility = [ ":*" ]
+ include_dirs = [ "include" ]
+}
+
+ohos_shared_library("ui_appearance_service") {
+ sources = [
+ "src/ui_appearance_ability.cpp",
+ "src/ui_appearance_ability_stub.cpp",
+ ]
+
+ public_configs = [ ":ui_appearance_service_config" ]
+ include_dirs = [ "include/" ]
+ deps = []
+ external_deps = [
+ "ability_base:configuration",
+ "ability_runtime:app_manager",
+ "access_token:libaccesstoken_sdk",
+ "c_utils:utils",
+ "hiviewdfx_hilog_native:libhilog",
+ "init:libbegetutil",
+ "ipc:ipc_single",
+ "safwk:system_ability_fwk",
+ "samgr:samgr_proxy",
+ ]
+ subsystem_name = "arkui"
+ part_name = "ui_appearance"
+}
+
+ohos_shared_library("ui_appearance_client") {
+ sources = [
+ "src/ui_appearance_ability_client.cpp",
+ "src/ui_appearance_ability_proxy.cpp",
+ ]
+
+ public_configs = [ ":ui_appearance_service_config" ]
+ include_dirs = [ "include/" ]
+ deps = []
+ external_deps = [
+ "c_utils:utils",
+ "hiviewdfx_hilog_native:libhilog",
+ "ipc:ipc_single",
+ "safwk:system_ability_fwk",
+ "samgr:samgr_proxy",
+ ]
+ subsystem_name = "arkui"
+ part_name = "ui_appearance"
+}
diff --git a/services/include/ui_appearance_ability.h b/services/include/ui_appearance_ability.h
new file mode 100644
index 0000000..f72fc4f
--- /dev/null
+++ b/services/include/ui_appearance_ability.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2022 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 UI_APPEARANCE_ABILITY_H
+#define UI_APPEARANCE_ABILITY_H
+
+#include "system_ability.h"
+#include "appmgr/app_mgr_proxy.h"
+#include "ui_appearance_ability_stub.h"
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+class UiAppearanceAbility : public SystemAbility, public UiAppearanceAbilityStub {
+ DECLARE_SYSTEM_ABILITY(UiAppearanceAbility);
+
+public:
+ UiAppearanceAbility(int32_t saId, bool runOnCreate);
+ ~UiAppearanceAbility() = default;
+
+ int32_t SetDarkMode(DarkMode mode) override;
+ DarkMode GetDarkMode() override;
+
+protected:
+ void OnStart() override;
+ void OnStop() override;
+
+ void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override;
+ void OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override;
+
+private:
+ sptr GetAppManagerInstance();
+ bool VerifyAccessToken(const std::string& permissionName);
+ int32_t OnSetDarkMode(DarkMode mode);
+ DarkMode OnGetDarkMode();
+
+ DarkMode darkMode_ = DarkMode::ALWAYS_LIGHT;
+};
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
+#endif // UI_APPEARANCE_ABILITY_H
\ No newline at end of file
diff --git a/services/include/ui_appearance_ability_client.h b/services/include/ui_appearance_ability_client.h
new file mode 100644
index 0000000..fab3aa5
--- /dev/null
+++ b/services/include/ui_appearance_ability_client.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 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 UI_APPEARANCE_ABILITY_CLIENT_H
+#define UI_APPEARANCE_ABILITY_CLIENT_H
+
+#include "iremote_object.h"
+#include "refbase.h"
+#include "ui_appearance_ability_interface.h"
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+class UiAppearanceDeathRecipient : public IRemoteObject::DeathRecipient {
+public:
+ explicit UiAppearanceDeathRecipient() = default;
+ ~UiAppearanceDeathRecipient() = default;
+ void OnRemoteDied(const wptr& object) override;
+};
+
+class UiAppearanceAbilityClient : public RefBase {
+public:
+ UiAppearanceAbilityClient() = default;
+ ~UiAppearanceAbilityClient() = default;
+ static sptr GetInstance();
+
+ int32_t SetDarkMode(UiAppearanceAbilityInterface::DarkMode mode);
+ UiAppearanceAbilityInterface::DarkMode GetDarkMode();
+ void OnRemoteSaDied(const wptr& object);
+
+private:
+ sptr GetUiAppearanceServiceProxy();
+ static sptr CreateUiAppearanceServiceProxy();
+
+ static inline std::mutex instanceLock_;
+ static inline sptr instance_;
+ static inline sptr uiAppearanceServiceProxy_;
+ static inline sptr deathRecipient_;
+};
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
+#endif // UI_APPEARANCE_ABILITY_CLIENT_H
\ No newline at end of file
diff --git a/services/include/ui_appearance_ability_interface.h b/services/include/ui_appearance_ability_interface.h
new file mode 100644
index 0000000..fe4c1bb
--- /dev/null
+++ b/services/include/ui_appearance_ability_interface.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2022 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 UI_APPEARANCE_ABILITY_INTERFACE_H
+#define UI_APPEARANCE_ABILITY_INTERFACE_H
+
+#include
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+class UiAppearanceAbilityInterface : public IRemoteBroker {
+public:
+ enum DarkMode {
+ ALWAYS_DARK = 0,
+ ALWAYS_LIGHT = 1,
+ UNKNOWN = 2,
+ };
+
+ enum IpcCode {
+ SET_DARK_MODE = 1,
+ GET_DARK_MODE = 2,
+ };
+
+ enum ErrCode {
+ SUCCEEDED = 0,
+ PERMISSION_ERR = 201,
+ INVALID_ARG = 401,
+ SYS_ERR = 1,
+ };
+
+ virtual int32_t SetDarkMode(DarkMode mode) = 0;
+ virtual DarkMode GetDarkMode() = 0;
+
+public:
+ DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.UiAppearance.UiAppearanceAbilityInterface");
+};
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
+#endif // UI_APPEARANCE_ABILITY_INTERFACE_H
\ No newline at end of file
diff --git a/services/include/ui_appearance_ability_proxy.h b/services/include/ui_appearance_ability_proxy.h
new file mode 100644
index 0000000..e5e82c0
--- /dev/null
+++ b/services/include/ui_appearance_ability_proxy.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022 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 UI_APPEARANCE_ABILITY_PROXY_H
+#define UI_APPEARANCE_ABILITY_PROXY_H
+
+#include "iremote_proxy.h"
+#include "ui_appearance_ability_interface.h"
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+class UiAppearanceAbilityProxy : public IRemoteProxy {
+public:
+ int32_t SetDarkMode(DarkMode mode) override;
+ DarkMode GetDarkMode() override;
+
+ explicit UiAppearanceAbilityProxy(const sptr& impl)
+ : IRemoteProxy(impl)
+ {}
+ ~UiAppearanceAbilityProxy() = default;
+
+private:
+ static inline BrokerDelegator delegator_;
+};
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
+#endif // UI_APPEARANCE_ABILITY_PROXY_H
\ No newline at end of file
diff --git a/services/include/ui_appearance_ability_stub.h b/services/include/ui_appearance_ability_stub.h
new file mode 100644
index 0000000..ee61c87
--- /dev/null
+++ b/services/include/ui_appearance_ability_stub.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2022 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 UI_APPEARANCE_ABILITY_STUB_H
+#define UI_APPEARANCE_ABILITY_STUB_H
+
+#include "iremote_stub.h"
+#include "ui_appearance_ability_interface.h"
+#include "message_parcel.h"
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+class UiAppearanceAbilityStub : public IRemoteStub {
+public:
+ int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) override;
+};
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
+#endif // UI_APPEARANCE_ABILITY_STUB_H
\ No newline at end of file
diff --git a/services/include/ui_appearance_log.h b/services/include/ui_appearance_log.h
new file mode 100644
index 0000000..78d79af
--- /dev/null
+++ b/services/include/ui_appearance_log.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2022 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 UI_APPEARANCE_LOG_H
+#define UI_APPEARANCE_LOG_H
+
+#define CONFIG_HILOG
+#ifdef CONFIG_HILOG
+#include "hilog/log.h"
+
+#ifdef HILOG_FATAL
+#undef HILOG_FATAL
+#endif
+
+#ifdef HILOG_ERROR
+#undef HILOG_ERROR
+#endif
+
+#ifdef HILOG_WARN
+#undef HILOG_WARN
+#endif
+
+#ifdef HILOG_INFO
+#undef HILOG_INFO
+#endif
+
+#ifdef HILOG_DEBUG
+#undef HILOG_DEBUG
+#endif
+
+#ifdef LOG_LABEL
+#undef LOG_LABEL
+#endif
+
+static constexpr unsigned int FRAMEWORK_DOMAIN = 0xD003900;
+static constexpr unsigned int JS_DOMAIN = 0xD003B00;
+static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL_FW = { LOG_CORE, FRAMEWORK_DOMAIN, "UiAppearance" };
+static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL_JS = { LOG_CORE, JS_DOMAIN, "JSApp" };
+
+#define UIFILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
+
+#define HILOG_FATAL(fmt, ...) \
+ (void)OHOS::HiviewDFX::HiLog::Fatal( \
+ LOG_LABEL_FW, "[%{public}s(%{public}s:%{public}d)]" fmt, UIFILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define HILOG_ERROR(fmt, ...) \
+ (void)OHOS::HiviewDFX::HiLog::Error( \
+ LOG_LABEL_FW, "[%{public}s(%{public}s:%{public}d)]" fmt, UIFILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define HILOG_WARN(fmt, ...) \
+ (void)OHOS::HiviewDFX::HiLog::Warn( \
+ LOG_LABEL_FW, "[%{public}s(%{public}s:%{public}d)]" fmt, UIFILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define HILOG_INFO(fmt, ...) \
+ (void)OHOS::HiviewDFX::HiLog::Info( \
+ LOG_LABEL_FW, "[%{public}s(%{public}s:%{public}d)]" fmt, UIFILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define HILOG_DEBUG(fmt, ...) \
+ (void)OHOS::HiviewDFX::HiLog::Debug( \
+ LOG_LABEL_FW, "[%{public}s(%{public}s:%{public}d)]" fmt, UIFILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#define JS_HILOG_FATAL(fmt, ...) \
+ (void)OHOS::HiviewDFX::HiLog::Fatal( \
+ LOG_LABEL_JS, "[%{public}s(%{public}s:%{public}d)]" fmt, UIFILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define JS_HILOG_ERROR(fmt, ...) \
+ (void)OHOS::HiviewDFX::HiLog::Error( \
+ LOG_LABEL_JS, "[%{public}s(%{public}s:%{public}d)]" fmt, UIFILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define JS_HILOG_WARN(fmt, ...) \
+ (void)OHOS::HiviewDFX::HiLog::Warn( \
+ LOG_LABEL_JS, "[%{public}s(%{public}s:%{public}d)]" fmt, UIFILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define JS_HILOG_INFO(fmt, ...) \
+ (void)OHOS::HiviewDFX::HiLog::Info( \
+ LOG_LABEL_JS, "[%{public}s(%{public}s:%{public}d)]" fmt, UIFILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define JS_HILOG_DEBUG(fmt, ...) \
+ (void)OHOS::HiviewDFX::HiLog::Debug( \
+ LOG_LABEL_JS, "[%{public}s(%{public}s:%{public}d)]" fmt, UIFILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#else
+
+#define HILOG_FATAL(...)
+#define HILOG_ERROR(...)
+#define HILOG_WARN(...)
+#define HILOG_INFO(...)
+#define HILOG_DEBUG(...)
+
+#define JS_HILOG_FATAL(...)
+#define JS_HILOG_ERROR(...)
+#define JS_HILOG_WARN(...)
+#define JS_HILOG_INFO(...)
+#define JS_HILOG_DEBUG(...)
+
+#endif // CONFIG_HILOG
+
+#endif // UI_APPEARANCE_LOG_H
\ No newline at end of file
diff --git a/services/src/ui_appearance_ability.cpp b/services/src/ui_appearance_ability.cpp
new file mode 100644
index 0000000..bd0f80b
--- /dev/null
+++ b/services/src/ui_appearance_ability.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2022 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 "ui_appearance_ability.h"
+
+#include
+
+#include "accesstoken_kit.h"
+#include "ipc_skeleton.h"
+#include "iservice_registry.h"
+#include "syspara/parameter.h"
+#include "system_ability_definition.h"
+#include "ui_appearance_log.h"
+
+namespace {
+static const std::string LIGHT = "light";
+static const std::string DARK = "dark";
+static const std::string PERSIST_DARKMODE_KEY = "persist.darkmode";
+static const std::string PERMISSION_UPDATE_CONFIGURATION = "ohos.permission.UPDATE_CONFIGURATION";
+} // namespace
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+REGISTER_SYSTEM_ABILITY_BY_ID(UiAppearanceAbility, ARKUI_UI_APPEARANCE_SERVICE_ID, true);
+
+UiAppearanceAbility::UiAppearanceAbility(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate) {}
+
+sptr UiAppearanceAbility::GetAppManagerInstance()
+{
+ sptr systemAbilityManager =
+ SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
+ if (systemAbilityManager == nullptr) {
+ HILOG_ERROR("Getting systemAbilityManager failed.");
+ return nullptr;
+ }
+
+ sptr appObject = systemAbilityManager->GetSystemAbility(APP_MGR_SERVICE_ID);
+ if (appObject == nullptr) {
+ HILOG_ERROR("Get systemAbility failed.");
+ return nullptr;
+ }
+
+ sptr systemAbility = iface_cast(appObject);
+ if (systemAbility == nullptr) {
+ HILOG_ERROR("Get AppMgrProxy from SA failed.");
+ return nullptr;
+ }
+ return systemAbility;
+}
+
+bool UiAppearanceAbility::VerifyAccessToken(const std::string& permissionName)
+{
+ auto callerToken = IPCSkeleton::GetCallingTokenID();
+ int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken, permissionName);
+ if (ret == Security::AccessToken::PermissionState::PERMISSION_DENIED) {
+ HILOG_ERROR("permission %{private}s: PERMISSION_DENIED", permissionName.c_str());
+ return false;
+ }
+ return true;
+}
+
+int32_t UiAppearanceAbility::OnSetDarkMode(DarkMode mode)
+{
+ HILOG_INFO("OnSetDarkMode start.");
+ bool ret = false;
+ std::string paramValue;
+ AppExecFwk::Configuration config;
+ switch (mode) {
+ case ALWAYS_LIGHT: {
+ ret = config.AddItem(
+ AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, AppExecFwk::ConfigurationInner::COLOR_MODE_LIGHT);
+ paramValue.assign(LIGHT);
+ break;
+ }
+ case ALWAYS_DARK: {
+ ret = config.AddItem(
+ AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, AppExecFwk::ConfigurationInner::COLOR_MODE_DARK);
+ paramValue.assign(DARK);
+ break;
+ }
+ default:
+ break;
+ }
+ if (!ret) {
+ HILOG_ERROR("AddItem failed, mode = %{public}d", mode);
+ return INVALID_ARG;
+ }
+
+ auto appManagerInstance = GetAppManagerInstance();
+ if (appManagerInstance == nullptr) {
+ HILOG_ERROR("Get app manager proxy failed.");
+ return SYS_ERR;
+ }
+ auto errcode = appManagerInstance->UpdateConfiguration(config);
+ if (errcode != 0) {
+ HILOG_ERROR("update configuration failed.");
+ return SYS_ERR;
+ }
+ darkMode_ = mode;
+
+ HILOG_INFO("set parameter begin, persist param = %{public}s.", paramValue.c_str());
+ // persist to file: etc/para/ui_appearance.para
+ auto isSetPara = SetParameter(PERSIST_DARKMODE_KEY.c_str(), paramValue.c_str());
+ if (isSetPara < 0) {
+ HILOG_ERROR("set parameter failed");
+ return SYS_ERR;
+ }
+ return SUCCEEDED;
+}
+
+int32_t UiAppearanceAbility::SetDarkMode(DarkMode mode)
+{
+ // Verify permissions
+ auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
+ if (!isCallingPerm) {
+ HILOG_ERROR("permission verification failed");
+ return PERMISSION_ERR;
+ }
+ if (mode != darkMode_) {
+ return OnSetDarkMode(mode);
+ }
+ return SUCCEEDED;
+}
+
+UiAppearanceAbilityInterface::DarkMode UiAppearanceAbility::OnGetDarkMode()
+{
+ HILOG_INFO("OnGetDarkMode start.");
+ constexpr int buffSize = 64; // buff len: 64
+ char valueGet[buffSize] = { 0 };
+
+ // LIGHT is the default.
+ auto res = GetParameter(PERSIST_DARKMODE_KEY.c_str(), LIGHT.c_str(), valueGet, buffSize);
+ if (res <= 0) {
+ HILOG_ERROR("get parameter failed.");
+ return UNKNOWN;
+ }
+ if (strcmp(valueGet, DARK.c_str()) == 0) {
+ return ALWAYS_DARK;
+ } else if (strcmp(valueGet, LIGHT.c_str()) == 0) {
+ return ALWAYS_LIGHT;
+ }
+ return UNKNOWN;
+}
+
+UiAppearanceAbilityInterface::DarkMode UiAppearanceAbility::GetDarkMode()
+{
+ auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
+ if (!isCallingPerm) {
+ HILOG_ERROR("permission verification failed");
+ return UNKNOWN;
+ }
+ return darkMode_;
+}
+
+void UiAppearanceAbility::OnStart()
+{
+ HILOG_INFO("publish start.");
+
+ bool res = Publish(this); // SA registers with SAMGR
+ if (!res) {
+ HILOG_ERROR("publish failed.");
+ return;
+ }
+
+ HILOG_INFO("AddSystemAbilityListener start.");
+ AddSystemAbilityListener(APP_MGR_SERVICE_ID);
+ return;
+}
+
+void UiAppearanceAbility::OnStop()
+{
+ HILOG_INFO("UiAppearanceAbility SA stop.");
+}
+
+void UiAppearanceAbility::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
+{
+ HILOG_INFO("systemAbilityId = %{public}d added.", systemAbilityId);
+ if (systemAbilityId == APP_MGR_SERVICE_ID) {
+ darkMode_ = OnGetDarkMode();
+ if (darkMode_ == UiAppearanceAbilityInterface::DarkMode::UNKNOWN) {
+ HILOG_ERROR("get darkmode init error.");
+ darkMode_ = UiAppearanceAbilityInterface::DarkMode::ALWAYS_LIGHT;
+ }
+ auto res = OnSetDarkMode(darkMode_);
+ if (res < 0) {
+ HILOG_ERROR("set darkmode init error.");
+ }
+ }
+}
+
+void UiAppearanceAbility::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
+{
+ HILOG_INFO("systemAbilityId = %{public}d removed.", systemAbilityId);
+}
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
\ No newline at end of file
diff --git a/services/src/ui_appearance_ability_client.cpp b/services/src/ui_appearance_ability_client.cpp
new file mode 100644
index 0000000..b3698a1
--- /dev/null
+++ b/services/src/ui_appearance_ability_client.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2022 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 "ui_appearance_ability_client.h"
+
+#include "iservice_registry.h"
+#include "system_ability_definition.h"
+#include "ui_appearance_ability_proxy.h"
+#include "ui_appearance_log.h"
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+sptr UiAppearanceAbilityClient::GetInstance()
+{
+ if (!instance_) {
+ std::lock_guard autoLock(instanceLock_);
+ if (!instance_) {
+ instance_ = new UiAppearanceAbilityClient;
+ uiAppearanceServiceProxy_ = CreateUiAppearanceServiceProxy();
+ }
+ }
+ return instance_;
+}
+
+sptr UiAppearanceAbilityClient::GetUiAppearanceServiceProxy()
+{
+ if (uiAppearanceServiceProxy_ == nullptr) {
+ HILOG_ERROR("Redo CreateUiAppearanceServiceProxy");
+ uiAppearanceServiceProxy_ = CreateUiAppearanceServiceProxy();
+ }
+ return uiAppearanceServiceProxy_;
+}
+
+int32_t UiAppearanceAbilityClient::SetDarkMode(UiAppearanceAbilityInterface::DarkMode mode)
+{
+ if (!GetUiAppearanceServiceProxy()) {
+ HILOG_ERROR("SetDarkMode quit because redoing CreateUiAppearanceServiceProxy failed.");
+ return UiAppearanceAbilityInterface::ErrCode::SYS_ERR;
+ }
+ return uiAppearanceServiceProxy_->SetDarkMode(mode);
+}
+
+UiAppearanceAbilityInterface::DarkMode UiAppearanceAbilityClient::GetDarkMode()
+{
+ if (!GetUiAppearanceServiceProxy()) {
+ HILOG_ERROR("GetDarkMode quit because redoing CreateUiAppearanceServiceProxy failed.");
+ return UiAppearanceAbilityInterface::DarkMode::UNKNOWN;
+ }
+ return uiAppearanceServiceProxy_->GetDarkMode();
+}
+
+sptr UiAppearanceAbilityClient::CreateUiAppearanceServiceProxy()
+{
+ sptr systemAbilityManager =
+ SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
+ if (systemAbilityManager == nullptr) {
+ HILOG_ERROR("Get SystemAbilityManager failed.");
+ return nullptr;
+ }
+
+ sptr systemAbility = systemAbilityManager->GetSystemAbility(ARKUI_UI_APPEARANCE_SERVICE_ID);
+ if (systemAbility == nullptr) {
+ HILOG_ERROR("Get SystemAbility failed.");
+ return nullptr;
+ }
+
+ deathRecipient_ = new UiAppearanceDeathRecipient;
+ systemAbility->AddDeathRecipient(deathRecipient_);
+ sptr uiAppearanceServiceProxy =
+ iface_cast(systemAbility);
+ if (uiAppearanceServiceProxy == nullptr) {
+ HILOG_ERROR("Get uiAppearanceServiceProxy from SA failed.");
+ return nullptr;
+ }
+ HILOG_INFO("Get uiAppearanceServiceProxy successful.");
+ return uiAppearanceServiceProxy;
+}
+
+void UiAppearanceAbilityClient::OnRemoteSaDied(const wptr& remote)
+{
+ // Used for new connections after the service may be disconnected.
+ uiAppearanceServiceProxy_ = CreateUiAppearanceServiceProxy();
+}
+
+void UiAppearanceDeathRecipient::OnRemoteDied(const wptr& object)
+{
+ HILOG_INFO("UiAppearanceDeathRecipient on remote systemAbility died.");
+ UiAppearanceAbilityClient::GetInstance()->OnRemoteSaDied(object);
+}
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
diff --git a/services/src/ui_appearance_ability_proxy.cpp b/services/src/ui_appearance_ability_proxy.cpp
new file mode 100644
index 0000000..798e235
--- /dev/null
+++ b/services/src/ui_appearance_ability_proxy.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2022 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 "ui_appearance_ability_proxy.h"
+
+#include
+
+#include "message_parcel.h"
+#include "ui_appearance_log.h"
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+int32_t UiAppearanceAbilityProxy::SetDarkMode(UiAppearanceAbilityInterface::DarkMode mode)
+{
+ MessageParcel data, reply;
+ MessageOption option;
+
+ if (!data.WriteInterfaceToken(GetDescriptor())) {
+ HILOG_ERROR("Write descriptor failed!");
+ return SYS_ERR;
+ }
+ if (!data.WriteInt32(mode)) {
+ HILOG_ERROR("Write mode failed!");
+ return SYS_ERR;
+ }
+
+ auto res = Remote()->SendRequest(SET_DARK_MODE, data, reply, option);
+ if (res != ERR_NONE) {
+ HILOG_ERROR("SendRequest failed.");
+ return SYS_ERR;
+ }
+
+ return reply.ReadInt32();
+}
+
+UiAppearanceAbilityInterface::DarkMode UiAppearanceAbilityProxy::GetDarkMode()
+{
+ MessageParcel data, reply;
+ MessageOption option;
+
+ if (!data.WriteInterfaceToken(GetDescriptor())) {
+ HILOG_ERROR("Write descriptor failed!");
+ return UNKNOWN;
+ }
+
+ auto res = Remote()->SendRequest(GET_DARK_MODE, data, reply, option);
+ if (res != ERR_NONE) {
+ HILOG_ERROR("SendRequest failed.");
+ return UNKNOWN;
+ }
+
+ return static_cast(reply.ReadInt32());
+}
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
\ No newline at end of file
diff --git a/services/src/ui_appearance_ability_stub.cpp b/services/src/ui_appearance_ability_stub.cpp
new file mode 100644
index 0000000..9ec0d78
--- /dev/null
+++ b/services/src/ui_appearance_ability_stub.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022 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 "ui_appearance_ability_stub.h"
+
+#include "ui_appearance_log.h"
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+int32_t UiAppearanceAbilityStub::OnRemoteRequest(
+ uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
+{
+ bool ret = false;
+ std::u16string interfaceToken = data.ReadInterfaceToken();
+ if (interfaceToken != GetDescriptor()) {
+ HILOG_ERROR("error permission denied.");
+ return -1;
+ }
+ switch (code) {
+ case SET_DARK_MODE: {
+ UiAppearanceAbilityInterface::DarkMode mode =
+ static_cast(data.ReadInt32());
+ ret = reply.WriteInt32(SetDarkMode(mode));
+ return (ret ? 0 : -1);
+ }
+ case GET_DARK_MODE: {
+ ret = reply.WriteInt32(GetDarkMode());
+ return (ret ? 0 : -1);
+ }
+ default:
+ return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
+ }
+}
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
\ No newline at end of file
diff --git a/test/mock/include/accesstoken_kit.h b/test/mock/include/accesstoken_kit.h
new file mode 100644
index 0000000..3f9d534
--- /dev/null
+++ b/test/mock/include/accesstoken_kit.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022 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_ARKUI_UI_APPEARANCE_TEST_MOCK_ACCESSTOKEN_KIT
+#define FOUNDATION_ARKUI_UI_APPEARANCE_TEST_MOCK_ACCESSTOKEN_KIT
+
+#include
+
+namespace OHOS {
+namespace Security::AccessToken {
+typedef unsigned int AccessTokenID;
+class AccessTokenKit {
+public:
+ static int VerifyAccessToken(AccessTokenID tokenID, const std::string& permissionName);
+};
+} // namespace Security::AccessToken
+} // namespace OHOS
+#endif // FOUNDATION_ARKUI_UI_APPEARANCE_TEST_MOCK_ACCESSTOKEN_KIT
\ No newline at end of file
diff --git a/test/mock/src/accesstoken_kit.cpp b/test/mock/src/accesstoken_kit.cpp
new file mode 100644
index 0000000..1315ee8
--- /dev/null
+++ b/test/mock/src/accesstoken_kit.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022 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 "accesstoken_kit.h"
+
+namespace OHOS {
+namespace Security::AccessToken {
+int AccessTokenKit::VerifyAccessToken(AccessTokenID tokenID, const std::string& permissionName)
+{
+ return 0;
+}
+} // namespace Security::AccessToken
+} // namespace OHOS
\ No newline at end of file
diff --git a/test/mock/src/mock_app_mgr_proxy.cpp b/test/mock/src/mock_app_mgr_proxy.cpp
new file mode 100644
index 0000000..b87fab1
--- /dev/null
+++ b/test/mock/src/mock_app_mgr_proxy.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022 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 "app_mgr_proxy.h"
+
+namespace OHOS {
+namespace AppExecFwk {
+int32_t AppMgrProxy::UpdateConfiguration(const Configuration& config)
+{
+ return 0;
+}
+} // namespace AppExecFwk
+} // namespace OHOS
\ No newline at end of file
diff --git a/test/mock/src/mock_parameter.cpp b/test/mock/src/mock_parameter.cpp
new file mode 100644
index 0000000..c5ebae3
--- /dev/null
+++ b/test/mock/src/mock_parameter.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022 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
+
+#include "syspara/parameter.h"
+
+namespace {
+constexpr int32_t buffSize = 10; // buff len: 64
+char value_[buffSize] = "light";
+} // namespace
+
+int GetParameter(const char* key, const char* def, char* value, unsigned int len)
+{
+ (void)key;
+ (void)def;
+ (void)strncpy_s(value, len, value_, buffSize);
+ return 1;
+}
+
+int SetParameter(const char* key, const char* value)
+{
+ (void)key;
+ (void)strncpy_s(value_, buffSize, value, strlen(value) + 1);
+ return 0;
+}
diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn
new file mode 100644
index 0000000..1540de2
--- /dev/null
+++ b/test/unittest/BUILD.gn
@@ -0,0 +1,57 @@
+# Copyright (c) 2022 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/test.gni")
+
+ohos_unittest("ui_appearance_test") {
+ module_out_path = "ui_appearance/ui_appearance_test"
+
+ include_dirs = [
+ "../mock/include",
+ ]
+
+ sources = [
+ "ui_appearance_test.cpp",
+ "../mock/src/accesstoken_kit.cpp",
+ "../mock/src/mock_app_mgr_proxy.cpp",
+ "../mock/src/mock_parameter.cpp",
+ ]
+
+ configs = []
+ cflags = []
+ if (target_cpu == "arm") {
+ cflags += [ "-DBINDER_IPC_32BIT" ]
+ }
+ deps = [
+ "../../services:ui_appearance_service",
+ ]
+
+ external_deps = [
+ "bundle_framework:appexecfwk_core",
+ "common_event_service:cesfwk_core",
+ "common_event_service:cesfwk_innerkits",
+ "hiviewdfx_hilog_native:libhilog",
+ "init:libbegetutil",
+ "c_utils:utils",
+ "ability_base:configuration",
+ "ability_base:want",
+ "ability_runtime:app_manager",
+ "samgr:samgr_proxy",
+ "safwk:system_ability_fwk",
+ "ipc:ipc_core",
+ ]
+}
+
+group("unittest") {
+ testonly = true
+ deps = [ ":ui_appearance_test" ]
+}
diff --git a/test/unittest/ui_appearance_test.cpp b/test/unittest/ui_appearance_test.cpp
new file mode 100644
index 0000000..98ed516
--- /dev/null
+++ b/test/unittest/ui_appearance_test.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2022 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
+#include
+#include
+#include
+#include
+#include
+
+#include "accesstoken_kit.h"
+#include "syspara/parameter.h"
+#include "system_ability_definition.h"
+#include "ui_appearance_ability.h"
+#include "ui_appearance_log.h"
+
+using namespace testing::ext;
+static constexpr int UISERVER_UID = 3050;
+
+namespace OHOS {
+namespace ArkUi::UiAppearance {
+class UiAppearanceAbilityTest : public UiAppearanceAbility {
+public:
+ UiAppearanceAbilityTest() : UiAppearanceAbility(ARKUI_UI_APPEARANCE_SERVICE_ID, true) {}
+ ~UiAppearanceAbilityTest() {}
+ void OnStart() override
+ {
+ return;
+ }
+};
+
+class DarkModeTest : public testing::Test {
+public:
+ static void SetUpTestCase(void);
+ static void TearDownTestCase(void);
+ void SetUp();
+ void TearDown();
+
+ static sptr GetUiAppearanceAbilityTest()
+ {
+ return new UiAppearanceAbilityTest;
+ }
+
+private:
+ int userId_;
+};
+
+void DarkModeTest::SetUpTestCase(void) {}
+
+void DarkModeTest::TearDownTestCase(void) {}
+
+void DarkModeTest::SetUp(void)
+{
+ userId_ = geteuid();
+ seteuid(UISERVER_UID);
+}
+
+void DarkModeTest::TearDown(void)
+{
+ seteuid(userId_);
+}
+
+/**
+ * @tc.name: ui_appearance_test_001
+ * @tc.desc: Test SetDarkMode and GetDarkMode APIs when setting dark/light.
+ * @tc.type: FUNC
+ */
+HWTEST_F(DarkModeTest, ui_appearance_test_001, TestSize.Level0)
+{
+ HILOG_INFO("Test SetDarkMode and GetDarkMode APIs when setting dark/light.");
+
+ auto test = DarkModeTest::GetUiAppearanceAbilityTest();
+ auto result = test->SetDarkMode(UiAppearanceAbilityInterface::DarkMode::ALWAYS_DARK);
+ EXPECT_EQ(result, 0);
+ UiAppearanceAbilityInterface::DarkMode mode = test->GetDarkMode();
+ EXPECT_EQ(mode, UiAppearanceAbilityInterface::DarkMode::ALWAYS_DARK);
+
+ result = test->SetDarkMode(UiAppearanceAbilityInterface::DarkMode::ALWAYS_LIGHT);
+ EXPECT_EQ(result, 0);
+ mode = test->GetDarkMode();
+ EXPECT_EQ(mode, UiAppearanceAbilityInterface::DarkMode::ALWAYS_LIGHT);
+}
+
+/**
+ * @tc.name: ui_appearance_test_002
+ * @tc.desc: Test SetDarkMode and GetDarkMode APIs when repeatedly setting dark/light.
+ * @tc.type: FUNC
+ */
+HWTEST_F(DarkModeTest, ui_appearance_test_002, TestSize.Level0)
+{
+ HILOG_INFO("Test SetDarkMode and GetDarkMode APIs when repeatedly setting dark/light.");
+
+ auto test = DarkModeTest::GetUiAppearanceAbilityTest();
+ auto result = test->SetDarkMode(UiAppearanceAbilityInterface::DarkMode::ALWAYS_DARK);
+ EXPECT_EQ(result, 0);
+ UiAppearanceAbilityInterface::DarkMode mode = test->GetDarkMode();
+ EXPECT_EQ(mode, UiAppearanceAbilityInterface::DarkMode::ALWAYS_DARK);
+
+ result = test->SetDarkMode(UiAppearanceAbilityInterface::DarkMode::ALWAYS_DARK);
+ EXPECT_EQ(result, 0);
+ mode = test->GetDarkMode();
+ EXPECT_EQ(mode, UiAppearanceAbilityInterface::DarkMode::ALWAYS_DARK);
+
+ result = test->SetDarkMode(UiAppearanceAbilityInterface::DarkMode::ALWAYS_LIGHT);
+ EXPECT_EQ(result, 0);
+ mode = test->GetDarkMode();
+ EXPECT_EQ(mode, UiAppearanceAbilityInterface::DarkMode::ALWAYS_LIGHT);
+
+ result = test->SetDarkMode(UiAppearanceAbilityInterface::DarkMode::ALWAYS_LIGHT);
+ EXPECT_EQ(result, 0);
+ mode = test->GetDarkMode();
+ EXPECT_EQ(mode, UiAppearanceAbilityInterface::DarkMode::ALWAYS_LIGHT);
+}
+
+/**
+ * @tc.name: ui_appearance_test_003
+ * @tc.desc: Test the SetDarkMode API when setting an unexpected value
+ * @tc.type: FUNC
+ */
+HWTEST_F(DarkModeTest, ui_appearance_test_003, TestSize.Level0)
+{
+ HILOG_INFO("Test the SetDarkMode API when setting an unexpected value.");
+
+ int result =
+ DarkModeTest::GetUiAppearanceAbilityTest()->SetDarkMode(UiAppearanceAbilityInterface::DarkMode::UNKNOWN);
+ EXPECT_NE(result, 0);
+}
+} // namespace ArkUi::UiAppearance
+} // namespace OHOS
\ No newline at end of file