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