• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ui_appearance_ability.h"
17 
18 #include <string>
19 
20 #include "accesstoken_kit.h"
21 #include "common_event_manager.h"
22 #include "common_event_support.h"
23 #include "dark_mode_manager.h"
24 #include "global_configuration_key.h"
25 #include "ipc_skeleton.h"
26 #include "iservice_registry.h"
27 #include "matching_skills.h"
28 #include "os_account_manager.h"
29 #include "system_ability_definition.h"
30 #include "ui_appearance_log.h"
31 #include "parameter_wrap.h"
32 
33 namespace {
34 static const std::string LIGHT = "light";
35 static const std::string DARK = "dark";
36 static const std::string BASE_SCALE = "1";
37 static const std::string PERSIST_DARKMODE_KEY = "persist.ace.darkmode";
38 static const std::string PERMISSION_UPDATE_CONFIGURATION = "ohos.permission.UPDATE_CONFIGURATION";
39 // current default accountId = 0, will change when have more user.
40 static const std::string FONT_SCAL_FOR_USER0 = "persist.sys.font_scale_for_user0";
41 static const std::string FONT_Weight_SCAL_FOR_USER0 = "persist.sys.font_wght_scale_for_user0";
42 
43 static const std::string PERSIST_DARKMODE_KEY_FOR_NONE = "persist.ace.darkmode.";
44 static const std::string FONT_SCAL_FOR_NONE = "persist.sys.font_scale_for_user.";
45 static const std::string FONT_WEIGHT_SCAL_FOR_NONE = "persist.sys.font_wght_scale_for_user.";
46 
47 static const std::string FIRST_INITIALIZATION = "persist.uiAppearance.first_initialization";
48 const static int32_t USER100 = 100;
49 const static int32_t USER0 = 0;
50 const static std::string FIRST_UPGRADE = "1";
51 const static std::string NOT_FIRST_UPGRADE = "0";
52 } // namespace
53 
54 namespace OHOS {
55 namespace ArkUi::UiAppearance {
56 
UiAppearanceEventSubscriber(const EventFwk::CommonEventSubscribeInfo & subscriberInfo,const std::function<void (const int32_t)> & userSwitchCallback)57 UiAppearanceEventSubscriber::UiAppearanceEventSubscriber(const EventFwk::CommonEventSubscribeInfo& subscriberInfo,
58     const std::function<void(const int32_t)>& userSwitchCallback)
59     : EventFwk::CommonEventSubscriber(subscriberInfo), userSwitchCallback_(userSwitchCallback)
60 {}
61 
OnReceiveEvent(const EventFwk::CommonEventData & data)62 void UiAppearanceEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData& data)
63 {
64     const AAFwk::Want& want = data.GetWant();
65     std::string action = want.GetAction();
66     LOGI("action:%{public}s", action.c_str());
67 
68     if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED) {
69         if (userSwitchCallback_ != nullptr) {
70             userSwitchCallback_(data.GetCode());
71         }
72     } else if (action == EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED) {
73         TimeChangeCallback();
74     } else if (action == EventFwk::CommonEventSupport::COMMON_EVENT_TIMEZONE_CHANGED) {
75         TimeChangeCallback();
76     } else if (action == EventFwk::CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED) {
77         BootCompetedCallback();
78     } else if (action == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF) {
79         DarkModeManager::GetInstance().ScreenOffCallback();
80     } else if (action == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON) {
81         DarkModeManager::GetInstance().ScreenOnCallback();
82     }
83 }
84 
TimeChangeCallback()85 void UiAppearanceEventSubscriber::TimeChangeCallback()
86 {
87     DarkModeManager::GetInstance().RestartTimer();
88 }
89 
BootCompetedCallback()90 void UiAppearanceEventSubscriber::BootCompetedCallback()
91 {
92     std::call_once(bootCompleteFlag_, [] () {
93         std::vector<int32_t> ids;
94         AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
95         int32_t userId;
96         if (ids.empty()) {
97             LOGE("no active user.");
98             userId = USER100;
99         } else {
100             userId = ids[0];
101         }
102         DarkModeManager &manager = DarkModeManager::GetInstance();
103         manager.OnSwitchUser(userId);
104         bool isDarkMode = false;
105         manager.LoadUserSettingData(userId, true, isDarkMode);
106     });
107 }
108 
109 REGISTER_SYSTEM_ABILITY_BY_ID(UiAppearanceAbility, ARKUI_UI_APPEARANCE_SERVICE_ID, true);
110 
UiAppearanceAbility(int32_t saId,bool runOnCreate)111 UiAppearanceAbility::UiAppearanceAbility(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate) {}
112 
GetAppManagerInstance()113 sptr<AppExecFwk::IAppMgr> UiAppearanceAbility::GetAppManagerInstance()
114 {
115     sptr<ISystemAbilityManager> systemAbilityManager =
116         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
117     if (systemAbilityManager == nullptr) {
118         LOGE("Getting systemAbilityManager failed.");
119         return nullptr;
120     }
121 
122     sptr<IRemoteObject> appObject = systemAbilityManager->GetSystemAbility(APP_MGR_SERVICE_ID);
123     if (appObject == nullptr) {
124         LOGE("Get systemAbility failed.");
125         return nullptr;
126     }
127 
128     sptr<AppExecFwk::IAppMgr> systemAbility = iface_cast<AppExecFwk::IAppMgr>(appObject);
129     if (systemAbility == nullptr) {
130         LOGE("Get AppMgrProxy from SA failed.");
131         return nullptr;
132     }
133     return systemAbility;
134 }
135 
VerifyAccessToken(const std::string & permissionName)136 bool UiAppearanceAbility::VerifyAccessToken(const std::string& permissionName)
137 {
138     auto callerToken = IPCSkeleton::GetCallingTokenID();
139     int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken, permissionName);
140     if (ret == Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
141         return true;
142     }
143     LOGE("permission %{private}s denied, callerToken : %{public}u", permissionName.c_str(), callerToken);
144     return false;
145 }
146 
OnStart()147 void UiAppearanceAbility::OnStart()
148 {
149     bool res = Publish(this); // SA registers with SAMGR
150     if (!res) {
151         LOGE("publish failed.");
152         return;
153     }
154 
155     LOGI("AddSystemAbilityListener start.");
156     AddSystemAbilityListener(APP_MGR_SERVICE_ID);
157     return;
158 }
159 
OnStop()160 void UiAppearanceAbility::OnStop()
161 {
162     LOGI("UiAppearanceAbility SA stop.");
163 }
164 
GetUserIds()165 std::list<int32_t> UiAppearanceAbility::GetUserIds()
166 {
167     std::vector<AccountSA::OsAccountInfo> infos;
168     auto errCode = AccountSA::OsAccountManager::QueryAllCreatedOsAccounts(infos);
169     if (errCode != 0) {
170         LOGW("QueryAllCreatedOsAccounts error: %{public}d.", errCode);
171         return {};
172     }
173     std::list<int32_t> ids;
174     for (const auto& info : infos) {
175         ids.push_back(info.GetLocalId());
176     }
177     return ids;
178 }
179 
DoCompatibleProcess()180 void UiAppearanceAbility::DoCompatibleProcess()
181 {
182     LOGI("DoCompatibleProcess");
183     auto getOldParam = [this](const std::string& paramName, std::string& result) {
184         return GetParameterWrap(paramName, result);
185     };
186 
187     auto isParamAllreadaySetted = [this](const std::string& paramName) {
188         std::string value;
189         return GetParameterWrap(paramName, value);
190     };
191 
192     const std::list<int32_t> userIds = GetUserIds();
193     std::string darkMode = LIGHT;
194     if (getOldParam(PERSIST_DARKMODE_KEY, darkMode)) {
195         for (auto id : userIds) {
196             if (isParamAllreadaySetted(DarkModeParamAssignUser(id))) {
197                 continue;
198             }
199             SetParameterWrap(DarkModeParamAssignUser(id), darkMode);
200             LOGI("userId:%{public}d set darkMode %{public}s", id, darkMode.c_str());
201         }
202     }
203     std::string fontSize = BASE_SCALE;
204     if (getOldParam(FONT_SCAL_FOR_USER0, fontSize)) {
205         for (auto id : userIds) {
206             if (isParamAllreadaySetted(FontScaleParamAssignUser(id))) {
207                 continue;
208             }
209             SetParameterWrap(FontScaleParamAssignUser(id), fontSize);
210             LOGI("userId:%{public}d set fontSize %{public}s", id, fontSize.c_str());
211         }
212     }
213     std::string fontWeightSize = BASE_SCALE;
214     if (getOldParam(FONT_Weight_SCAL_FOR_USER0, fontWeightSize)) {
215         for (auto id : userIds) {
216             if (isParamAllreadaySetted(FontWeightScaleParamAssignUser(id))) {
217                 continue;
218             }
219             SetParameterWrap(FontWeightScaleParamAssignUser(id), fontWeightSize);
220             LOGI("userId:%{public}d set fontWeightSize %{public}s", id, fontWeightSize.c_str());
221         }
222     }
223     SetParameterWrap(FIRST_INITIALIZATION, "0");
224     isNeedDoCompatibleProcess_ = false;
225 }
226 
DoInitProcess()227 void UiAppearanceAbility::DoInitProcess()
228 {
229     LOGI("DoInitProcess");
230     const std::list<int32_t> userIds = GetUserIds();
231     for (auto userId : userIds) {
232         std::string darkValue = LIGHT;
233         GetParameterWrap(DarkModeParamAssignUser(userId), darkValue);
234 
235         std::string fontSize = BASE_SCALE;
236         GetParameterWrap(FontScaleParamAssignUser(userId), fontSize);
237 
238         std::string fontWeight = BASE_SCALE;
239         GetParameterWrap(FontWeightScaleParamAssignUser(userId), fontWeight);
240 
241         UiAppearanceParam tmpParam;
242         tmpParam.darkMode = darkValue == DARK ? DarkMode::ALWAYS_DARK : DarkMode::ALWAYS_LIGHT;
243         tmpParam.fontScale = fontSize;
244         tmpParam.fontWeightScale = fontWeight;
245         {
246             std::lock_guard<std::mutex> guard(usersParamMutex_);
247             usersParam_[userId] = tmpParam;
248         }
249         LOGI("init userId:%{public}d, darkMode:%{public}s, fontSize:%{public}s, fontWeight:%{public}s", userId,
250             darkValue.c_str(), fontSize.c_str(), fontWeight.c_str());
251     }
252     isInitializationFinished_ = true;
253 }
254 
UpdateCurrentUserConfiguration(const int32_t userId,const bool isForceUpdate)255 void UiAppearanceAbility::UpdateCurrentUserConfiguration(const int32_t userId, const bool isForceUpdate)
256 {
257     UiAppearanceParam tmpParam;
258     {
259         std::lock_guard<std::mutex> guard(usersParamMutex_);
260         tmpParam = usersParam_[userId];
261     }
262     AppExecFwk::Configuration config;
263     config.AddItem(
264         AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, tmpParam.darkMode == DarkMode::ALWAYS_DARK ? DARK : LIGHT);
265     config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_SIZE_SCALE, tmpParam.fontScale);
266     config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_WEIGHT_SCALE, tmpParam.fontWeightScale);
267 
268     auto appManagerInstance = GetAppManagerInstance();
269     if (!appManagerInstance) {
270         LOGE("GetAppManagerInstance error userId:%{public}d", userId);
271         return;
272     }
273 
274     {
275         std::lock_guard<std::mutex> onceFlagGuard(userSwitchUpdateConfigurationOnceFlagMutex_);
276         if (isForceUpdate ||
277             userSwitchUpdateConfigurationOnceFlag_.find(userId) == userSwitchUpdateConfigurationOnceFlag_.end()) {
278             appManagerInstance->UpdateConfiguration(config, userId);
279             LOGI("update userId:%{public}d configuration:%{public}s", userId, config.GetName().c_str());
280             userSwitchUpdateConfigurationOnceFlag_.insert(userId);
281         } else {
282             appManagerInstance->UpdateConfiguration(config, USER0);
283             LOGI("update userId:%{public}d configuration:%{public}s", USER0, config.GetName().c_str());
284         }
285     }
286 
287     SetParameterWrap(PERSIST_DARKMODE_KEY, tmpParam.darkMode == DarkMode::ALWAYS_DARK ? DARK : LIGHT);
288     SetParameterWrap(FONT_SCAL_FOR_USER0, tmpParam.fontScale);
289     SetParameterWrap(FONT_Weight_SCAL_FOR_USER0, tmpParam.fontWeightScale);
290 }
291 
UserSwitchFunc(const int32_t userId)292 void UiAppearanceAbility::UserSwitchFunc(const int32_t userId)
293 {
294     DarkModeManager& manager = DarkModeManager::GetInstance();
295     manager.OnSwitchUser(userId);
296     bool isDarkMode = false;
297     int32_t code = manager.LoadUserSettingData(userId, false, isDarkMode);
298 
299     if (isNeedDoCompatibleProcess_) {
300         DoCompatibleProcess();
301     }
302     if (!isInitializationFinished_) {
303         DoInitProcess();
304     }
305 
306     bool isForceUpdate = false;
307     if (code == ERR_OK && manager.IsColorModeNormal(userId)) {
308         DarkMode darkMode = isDarkMode ? ALWAYS_DARK : ALWAYS_LIGHT;
309         std::lock_guard<std::mutex> guard(usersParamMutex_);
310         if (usersParam_[userId].darkMode != darkMode) {
311             usersParam_[userId].darkMode = darkMode;
312             isForceUpdate = true;
313         }
314     }
315 
316     UpdateCurrentUserConfiguration(userId, isForceUpdate);
317 }
318 
SubscribeCommonEvent()319 void UiAppearanceAbility::SubscribeCommonEvent()
320 {
321     EventFwk::MatchingSkills matchingSkills;
322     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED);
323     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED);
324     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED);
325     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_TIMEZONE_CHANGED);
326     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_ON);
327     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF);
328     EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
329     subscribeInfo.SetThreadMode(EventFwk::CommonEventSubscribeInfo::COMMON);
330 
331     uiAppearanceEventSubscriber_ = std::make_shared<UiAppearanceEventSubscriber>(
332         subscribeInfo, [this](const int32_t userId) { UserSwitchFunc(userId); });
333     bool subResult = EventFwk::CommonEventManager::SubscribeCommonEvent(uiAppearanceEventSubscriber_);
334     if (!subResult) {
335         LOGW("subscribe user switch event error");
336     }
337 }
338 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)339 void UiAppearanceAbility::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
340 {
341     if (systemAbilityId != APP_MGR_SERVICE_ID) {
342         return;
343     }
344 
345     auto checkIfFirstUpgrade = [this]() {
346         std::string initFlag = NOT_FIRST_UPGRADE;
347         GetParameterWrap(FIRST_INITIALIZATION, initFlag);
348         if (initFlag == FIRST_UPGRADE) {
349             return true;
350         }
351         return false;
352     };
353     isNeedDoCompatibleProcess_ = checkIfFirstUpgrade();
354     DarkModeManager::GetInstance().Initialize(
355         [this](bool isDarkMode, int32_t userId) { UpdateDarkModeCallback(isDarkMode, userId); });
356     SubscribeCommonEvent();
357     if (isNeedDoCompatibleProcess_ && !GetUserIds().empty()) {
358         DoCompatibleProcess();
359     }
360 
361     if (!isInitializationFinished_ && !GetUserIds().empty()) {
362         DoInitProcess();
363         int32_t userId = USER100;
364         auto errCode = AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(userId);
365         if (errCode != 0) {
366             LOGW("GetForegroundOsAccountLocalId error: %{public}d.", errCode);
367             userId = USER100;
368         }
369         UpdateCurrentUserConfiguration(userId, false);
370     }
371 }
372 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)373 void UiAppearanceAbility::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
374 {
375     LOGI("systemAbilityId = %{public}d removed.", systemAbilityId);
376 }
377 
GetCallingUserId()378 int32_t UiAppearanceAbility::GetCallingUserId()
379 {
380     const static int32_t UID_TRANSFORM_DIVISOR = 200000;
381 
382     LOGD("CallingUid = %{public}d", OHOS::IPCSkeleton::GetCallingUid());
383     int32_t userId = OHOS::IPCSkeleton::GetCallingUid() / UID_TRANSFORM_DIVISOR;
384     if (userId == 0) {
385         auto errNo = AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(userId);
386         if (errNo != 0) {
387             LOGE("CallingUid = %{public}d, GetForegroundOsAccountLocalId error:%{public}d",
388                 OHOS::IPCSkeleton::GetCallingUid(), errNo);
389             userId = USER100;
390         }
391     }
392     return userId;
393 }
394 
DarkModeParamAssignUser(const int32_t userId)395 std::string UiAppearanceAbility::DarkModeParamAssignUser(const int32_t userId)
396 {
397     return PERSIST_DARKMODE_KEY_FOR_NONE + std::to_string(userId);
398 }
FontScaleParamAssignUser(const int32_t userId)399 std::string UiAppearanceAbility::FontScaleParamAssignUser(const int32_t userId)
400 {
401     return FONT_SCAL_FOR_NONE + std::to_string(userId);
402 }
FontWeightScaleParamAssignUser(const int32_t userId)403 std::string UiAppearanceAbility::FontWeightScaleParamAssignUser(const int32_t userId)
404 {
405     return FONT_WEIGHT_SCAL_FOR_NONE + std::to_string(userId);
406 }
407 
UpdateConfiguration(const AppExecFwk::Configuration & configuration,const int32_t userId)408 bool UiAppearanceAbility::UpdateConfiguration(const AppExecFwk::Configuration& configuration, const int32_t userId)
409 {
410     auto appManagerInstance = GetAppManagerInstance();
411     if (appManagerInstance == nullptr) {
412         LOGE("Get app manager proxy failed.");
413         return false;
414     }
415 
416     LOGI("update Configuration start,userId:%{public}d config = %{public}s.", userId, configuration.GetName().c_str());
417     auto errcode = appManagerInstance->UpdateConfiguration(configuration, userId);
418     if (errcode != 0) {
419         AppExecFwk::Configuration config;
420         auto retVal = appManagerInstance->GetConfiguration(config);
421         if (retVal != 0) {
422             LOGE("get configuration failed, update error, error is %{public}d.", retVal);
423             return false;
424         }
425         std::vector<std::string> diffVe;
426         config.CompareDifferent(diffVe, configuration);
427 
428         if (!diffVe.empty()) {
429             LOGE("update configuration failed, errcode = %{public}d.", errcode);
430             return false;
431         } else {
432             LOGW("uiappearance is different against configuration. Forced to use the configuration, error is "
433                  "%{public}d.",
434                 errcode);
435         }
436     }
437     return true;
438 }
439 
OnSetDarkMode(const int32_t userId,DarkMode mode)440 int32_t UiAppearanceAbility::OnSetDarkMode(const int32_t userId, DarkMode mode)
441 {
442     LOGI("setDarkMode, userId:%{public}d, mode: %{public}d", userId, mode);
443     bool ret = false;
444     std::string paramValue;
445     AppExecFwk::Configuration config;
446     switch (mode) {
447         case ALWAYS_LIGHT: {
448             ret = config.AddItem(
449                 AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, AppExecFwk::ConfigurationInner::COLOR_MODE_LIGHT);
450             paramValue.assign(LIGHT);
451             break;
452         }
453         case ALWAYS_DARK: {
454             ret = config.AddItem(
455                 AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, AppExecFwk::ConfigurationInner::COLOR_MODE_DARK);
456             paramValue.assign(DARK);
457             break;
458         }
459         default:
460             break;
461     }
462     if (!ret) {
463         LOGE("AddItem failed, mode = %{public}d", mode);
464         return INVALID_ARG;
465     }
466 
467     if (!UpdateConfiguration(config, userId)) {
468         return SYS_ERR;
469     }
470 
471     DarkModeManager::GetInstance().DoSwitchTemporaryColorMode(userId, mode == ALWAYS_DARK ? true : false);
472 
473     {
474         std::lock_guard<std::mutex> guard(usersParamMutex_);
475         usersParam_[userId].darkMode = mode;
476     }
477 
478     SetParameterWrap(PERSIST_DARKMODE_KEY, paramValue);
479 
480     // persist to file: etc/para/ui_appearance.para
481     auto isSetPara = SetParameterWrap(DarkModeParamAssignUser(userId), paramValue);
482     if (!isSetPara) {
483         LOGE("set parameter failed");
484         return SYS_ERR;
485     }
486     DarkModeManager::GetInstance().NotifyDarkModeUpdate(userId, mode == ALWAYS_DARK);
487     return SUCCEEDED;
488 }
489 
SetDarkMode(int32_t mode,int32_t & funcResult)490 ErrCode UiAppearanceAbility::SetDarkMode(int32_t mode, int32_t& funcResult)
491 {
492     // Verify permissions
493     DarkMode darkMode = static_cast<DarkMode>(mode);
494     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
495     if (!isCallingPerm) {
496         LOGE("permission verification failed");
497         funcResult = PERMISSION_ERR;
498         return funcResult;
499     }
500 
501     auto userId = GetCallingUserId();
502     DarkMode currentDarkMode = DarkMode::ALWAYS_LIGHT;
503     {
504         std::lock_guard<std::mutex> guard(usersParamMutex_);
505         auto it = usersParam_.find(userId);
506         if (it != usersParam_.end()) {
507             currentDarkMode = it->second.darkMode;
508         }
509     }
510     if (darkMode != currentDarkMode) {
511         funcResult = OnSetDarkMode(userId, darkMode);
512         return funcResult;
513     } else {
514         LOGW("current color mode is %{public}d, no need to change", darkMode);
515         funcResult = SYS_ERR;
516         return funcResult;
517     }
518 }
519 
InitGetDarkMode(const int32_t userId)520 DarkMode UiAppearanceAbility::InitGetDarkMode(const int32_t userId)
521 {
522     std::string valueGet = LIGHT;
523 
524     // LIGHT is the default.
525     auto res = GetParameterWrap(DarkModeParamAssignUser(userId), valueGet);
526     if (!res) {
527         return ALWAYS_LIGHT;
528     }
529     if (valueGet == DARK) {
530         LOGI("current color mode is dark.");
531         return ALWAYS_DARK;
532     } else if (valueGet == LIGHT) {
533         LOGI("current color mode is light.");
534         return ALWAYS_LIGHT;
535     }
536     return ALWAYS_LIGHT;
537 }
538 
GetDarkMode(int32_t & funcResult)539 ErrCode UiAppearanceAbility::GetDarkMode(int32_t& funcResult)
540 {
541     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
542     if (!isCallingPerm) {
543         LOGE("permission verification failed");
544         funcResult = PERMISSION_ERR;
545         return funcResult;
546     }
547 
548     {
549         std::lock_guard<std::mutex> guard(usersParamMutex_);
550         auto it = usersParam_.find(GetCallingUserId());
551         if (it != usersParam_.end()) {
552             funcResult = it->second.darkMode;
553             return SUCCEEDED;
554         }
555     }
556 
557     funcResult = DarkMode::ALWAYS_LIGHT;
558     return SUCCEEDED;
559 }
560 
OnSetFontScale(const int32_t userId,const std::string & fontScale)561 int32_t UiAppearanceAbility::OnSetFontScale(const int32_t userId, const std::string& fontScale)
562 {
563     bool ret = false;
564     AppExecFwk::Configuration config;
565     ret = config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_SIZE_SCALE, fontScale);
566     if (!ret) {
567         LOGE("AddItem failed, fontScale = %{public}s", fontScale.c_str());
568         return INVALID_ARG;
569     }
570     if (!UpdateConfiguration(config, userId)) {
571         return SYS_ERR;
572     }
573 
574     {
575         std::lock_guard<std::mutex> guard(usersParamMutex_);
576         usersParam_[userId].fontScale = fontScale;
577     }
578 
579     SetParameterWrap(FONT_SCAL_FOR_USER0, fontScale);
580     // persist to file: etc/para/ui_appearance.para
581     auto isSetPara = SetParameterWrap(FontScaleParamAssignUser(userId), fontScale);
582     if (!isSetPara) {
583         LOGE("set parameter failed");
584         return SYS_ERR;
585     }
586     return SUCCEEDED;
587 }
588 
SetFontScale(const std::string & fontScale,int32_t & funcResult)589 ErrCode UiAppearanceAbility::SetFontScale(const std::string& fontScale, int32_t& funcResult)
590 {
591     // Verify permissions
592     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
593     if (!isCallingPerm) {
594         LOGE("permission verification failed");
595         funcResult = PERMISSION_ERR;
596         return funcResult;
597     }
598     if (!fontScale.empty()) {
599         funcResult = OnSetFontScale(GetCallingUserId(), fontScale);
600         return funcResult;
601     } else {
602         LOGE("current fontScale is empty!");
603     }
604     funcResult = SYS_ERR;
605     return funcResult;
606 }
607 
GetFontScale(std::string & fontScale,int32_t & funcResult)608 ErrCode UiAppearanceAbility::GetFontScale(std::string& fontScale, int32_t& funcResult)
609 {
610     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
611     if (!isCallingPerm) {
612         LOGE("permission verification failed");
613         funcResult = PERMISSION_ERR;
614         return funcResult;
615     }
616     {
617         std::lock_guard<std::mutex> guard(usersParamMutex_);
618         auto it = usersParam_.find(GetCallingUserId());
619         if (it != usersParam_.end()) {
620             fontScale = it->second.fontScale;
621         } else {
622             fontScale = BASE_SCALE;
623         }
624     }
625     LOGD("get font scale :%{public}s", fontScale.c_str());
626     funcResult = SUCCEEDED;
627     return funcResult;
628 }
629 
OnSetFontWeightScale(const int32_t userId,const std::string & fontWeightScale)630 int32_t UiAppearanceAbility::OnSetFontWeightScale(const int32_t userId, const std::string& fontWeightScale)
631 {
632     bool ret = false;
633     AppExecFwk::Configuration config;
634     ret = config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_WEIGHT_SCALE, fontWeightScale);
635     if (!ret) {
636         LOGE("AddItem failed, fontWeightScale = %{public}s", fontWeightScale.c_str());
637         return INVALID_ARG;
638     }
639 
640     if (!UpdateConfiguration(config, userId)) {
641         return SYS_ERR;
642     }
643 
644     {
645         std::lock_guard<std::mutex> guard(usersParamMutex_);
646         usersParam_[userId].fontWeightScale = fontWeightScale;
647     }
648 
649     SetParameterWrap(FONT_Weight_SCAL_FOR_USER0, fontWeightScale);
650 
651     // persist to file: etc/para/ui_appearance.para
652     auto isSetPara = SetParameterWrap(FontWeightScaleParamAssignUser(userId), fontWeightScale);
653     if (!isSetPara) {
654         LOGE("set parameter failed");
655         return SYS_ERR;
656     }
657     return SUCCEEDED;
658 }
659 
SetFontWeightScale(const std::string & fontWeightScale,int32_t & funcResult)660 ErrCode UiAppearanceAbility::SetFontWeightScale(const std::string& fontWeightScale, int32_t& funcResult)
661 {
662     // Verify permissions
663     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
664     if (!isCallingPerm) {
665         LOGE("permission verification failed");
666         funcResult = PERMISSION_ERR;
667         return funcResult;
668     }
669     if (!fontWeightScale.empty()) {
670         funcResult = OnSetFontWeightScale(GetCallingUserId(), fontWeightScale);
671         return funcResult;
672     } else {
673         LOGE("current fontWeightScale is empty!");
674     }
675     funcResult = SYS_ERR;
676     return funcResult;
677 }
678 
GetFontWeightScale(std::string & fontWeightScale,int32_t & funcResult)679 ErrCode UiAppearanceAbility::GetFontWeightScale(std::string& fontWeightScale, int32_t& funcResult)
680 {
681     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
682     if (!isCallingPerm) {
683         LOGE("permission verification failed");
684         funcResult = PERMISSION_ERR;
685         return funcResult;
686     }
687 
688     {
689         std::lock_guard<std::mutex> guard(usersParamMutex_);
690         auto it = usersParam_.find(GetCallingUserId());
691         if (it != usersParam_.end()) {
692             fontWeightScale = it->second.fontWeightScale;
693         } else {
694             fontWeightScale = BASE_SCALE;
695         }
696     }
697 
698     LOGD("get font weight scale :%{public}s", fontWeightScale.c_str());
699     funcResult = SUCCEEDED;
700     return funcResult;
701 }
702 
UpdateDarkModeCallback(const bool isDarkMode,const int32_t userId)703 void UiAppearanceAbility::UpdateDarkModeCallback(const bool isDarkMode, const int32_t userId)
704 {
705     bool ret = false;
706     std::string paramValue;
707     AppExecFwk::Configuration config;
708     if (isDarkMode) {
709         ret = config.AddItem(
710             AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, AppExecFwk::ConfigurationInner::COLOR_MODE_DARK);
711         paramValue.assign(DARK);
712     } else {
713         ret = config.AddItem(
714             AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, AppExecFwk::ConfigurationInner::COLOR_MODE_LIGHT);
715         paramValue.assign(LIGHT);
716     }
717     if (!ret) {
718         LOGE("AddItem failed, isDarkMode: %{public}d, userId: %{public}d", isDarkMode, userId);
719         return;
720     }
721 
722     if (!UpdateConfiguration(config, userId)) {
723         return;
724     }
725 
726     {
727         std::lock_guard<std::mutex> guard(usersParamMutex_);
728         usersParam_[userId].darkMode = isDarkMode ? ALWAYS_DARK : ALWAYS_LIGHT;
729     }
730 
731     SetParameterWrap(PERSIST_DARKMODE_KEY, paramValue);
732     if (!SetParameterWrap(DarkModeParamAssignUser(userId), paramValue)) {
733         LOGE("set parameter failed");
734     }
735 }
736 } // namespace ArkUi::UiAppearance
737 } // namespace OHOS
738