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