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 "global_configuration_key.h"
24 #include "ipc_skeleton.h"
25 #include "iservice_registry.h"
26 #include "matching_skills.h"
27 #include "os_account_manager.h"
28 #include "syspara/parameter.h"
29 #include "system_ability_definition.h"
30 #include "ui_appearance_log.h"
31 
32 namespace {
33 static const std::string LIGHT = "light";
34 static const std::string DARK = "dark";
35 static const std::string BASE_SCALE = "1";
36 static const std::string PERSIST_DARKMODE_KEY = "persist.ace.darkmode";
37 static const std::string PERMISSION_UPDATE_CONFIGURATION = "ohos.permission.UPDATE_CONFIGURATION";
38 // current default accountId = 0, will change when have more user.
39 static const std::string FONT_SCAL_FOR_USER0 = "persist.sys.font_scale_for_user0";
40 static const std::string FONT_Weight_SCAL_FOR_USER0 = "persist.sys.font_wght_scale_for_user0";
41 
42 static const std::string PERSIST_DARKMODE_KEY_FOR_NONE = "persist.ace.darkmode.";
43 static const std::string FONT_SCAL_FOR_NONE = "persist.sys.font_scale_for_user.";
44 static const std::string FONT_WEIGHT_SCAL_FOR_NONE = "persist.sys.font_wght_scale_for_user.";
45 
46 static const std::string FIRST_INITIALIZATION = "persist.uiAppearance.first_initialization";
47 const static int32_t USER100 = 100;
48 const static std::string FIRST_UPGRADE = "1";
49 const static std::string NOT_FIRST_UPGRADE = "0";
50 } // namespace
51 
52 namespace OHOS {
53 namespace ArkUi::UiAppearance {
54 
UserSwitchEventSubscriber(const EventFwk::CommonEventSubscribeInfo& subscriberInfo, const std::function<void(const int32_t)>& userSwitchCallback)55 UserSwitchEventSubscriber::UserSwitchEventSubscriber(const EventFwk::CommonEventSubscribeInfo& subscriberInfo,
56     const std::function<void(const int32_t)>& userSwitchCallback)
57     : EventFwk::CommonEventSubscriber(subscriberInfo), userSwitchCallback_(userSwitchCallback)
58 {}
59 
OnReceiveEvent(const EventFwk::CommonEventData& data)60 void UserSwitchEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData& data)
61 {
62     const AAFwk::Want& want = data.GetWant();
63     std::string action = want.GetAction();
64     LOGI("action:%{public}s", action.c_str());
65 
66     if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED) {
67         if (userSwitchCallback_ != nullptr) {
68             userSwitchCallback_(data.GetCode());
69         }
70     }
71 }
72 
73 REGISTER_SYSTEM_ABILITY_BY_ID(UiAppearanceAbility, ARKUI_UI_APPEARANCE_SERVICE_ID, true);
74 
UiAppearanceAbility(int32_t saId, bool runOnCreate)75 UiAppearanceAbility::UiAppearanceAbility(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate) {}
76 
GetAppManagerInstance()77 sptr<AppExecFwk::IAppMgr> UiAppearanceAbility::GetAppManagerInstance()
78 {
79     sptr<ISystemAbilityManager> systemAbilityManager =
80         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
81     if (systemAbilityManager == nullptr) {
82         LOGE("Getting systemAbilityManager failed.");
83         return nullptr;
84     }
85 
86     sptr<IRemoteObject> appObject = systemAbilityManager->GetSystemAbility(APP_MGR_SERVICE_ID);
87     if (appObject == nullptr) {
88         LOGE("Get systemAbility failed.");
89         return nullptr;
90     }
91 
92     sptr<AppExecFwk::IAppMgr> systemAbility = iface_cast<AppExecFwk::IAppMgr>(appObject);
93     if (systemAbility == nullptr) {
94         LOGE("Get AppMgrProxy from SA failed.");
95         return nullptr;
96     }
97     return systemAbility;
98 }
99 
VerifyAccessToken(const std::string& permissionName)100 bool UiAppearanceAbility::VerifyAccessToken(const std::string& permissionName)
101 {
102     auto callerToken = IPCSkeleton::GetCallingTokenID();
103     int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken, permissionName);
104     if (ret == Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
105         return true;
106     }
107     LOGE("permission %{private}s denied, callerToken : %{public}u", permissionName.c_str(), callerToken);
108     return false;
109 }
110 
OnStart()111 void UiAppearanceAbility::OnStart()
112 {
113     bool res = Publish(this); // SA registers with SAMGR
114     if (!res) {
115         LOGE("publish failed.");
116         return;
117     }
118 
119     LOGI("AddSystemAbilityListener start.");
120     AddSystemAbilityListener(APP_MGR_SERVICE_ID);
121     return;
122 }
123 
OnStop()124 void UiAppearanceAbility::OnStop()
125 {
126     LOGI("UiAppearanceAbility SA stop.");
127 }
128 
GetUserIds()129 std::vector<int32_t> UiAppearanceAbility::GetUserIds()
130 {
131     std::vector<AccountSA::OsAccountInfo> infos;
132     AccountSA::OsAccountManager::QueryAllCreatedOsAccounts(infos);
133     std::vector<int32_t> ids;
134     for (const auto& info : infos) {
135         ids.push_back(info.GetLocalId());
136     }
137     return ids;
138 }
139 
DoCompatibleProcess()140 void UiAppearanceAbility::DoCompatibleProcess()
141 {
142     LOGI("DoCompatibleProcess");
143     auto getOldParam = [this](const std::string& paramName, std::string& result) {
144         return GetParameterWrap(paramName, result);
145     };
146 
147     auto isParamAllreadaySetted = [this](const std::string& paramName) {
148         std::string value;
149         return GetParameterWrap(paramName, value);
150     };
151 
152     const std::vector<int32_t> userIds = GetUserIds();
153     std::unique_lock<std::recursive_mutex> guard(usersParamMutex_);
154     std::string darkMode = LIGHT;
155     if (getOldParam(PERSIST_DARKMODE_KEY, darkMode)) {
156         for (auto id : userIds) {
157             if (isParamAllreadaySetted(DarkModeParamAssignUser(id))) {
158                 continue;
159             }
160             SetParameterWrap(DarkModeParamAssignUser(id), darkMode);
161         }
162         LOGD(" set darkMode %{public}s", darkMode.c_str());
163     }
164     std::string fontSize = BASE_SCALE;
165     if (getOldParam(FONT_SCAL_FOR_USER0, fontSize)) {
166         for (auto id : userIds) {
167             if (isParamAllreadaySetted(FontScaleParamAssignUser(id))) {
168                 continue;
169             }
170             SetParameterWrap(FontScaleParamAssignUser(id), fontSize);
171         }
172         LOGD(" set fontSize %{public}s", fontSize.c_str());
173     }
174     std::string fontWeightSize = BASE_SCALE;
175     if (getOldParam(FONT_Weight_SCAL_FOR_USER0, fontWeightSize)) {
176         for (auto id : userIds) {
177             if (isParamAllreadaySetted(FontWeightScaleParamAssignUser(id))) {
178                 continue;
179             }
180             SetParameterWrap(FontWeightScaleParamAssignUser(id), fontWeightSize);
181         }
182         LOGD(" set fontWeightSize %{public}s", fontWeightSize.c_str());
183     }
184     SetParameterWrap(FIRST_INITIALIZATION, "0");
185     isNeedDoCompatibleProcess_ = false;
186 }
187 
DoInitProcess()188 void UiAppearanceAbility::DoInitProcess()
189 {
190     LOGI("DoInitProcess");
191     const std::vector<int32_t> userIds = GetUserIds();
192     for (auto userId : userIds) {
193         std::string darkValue = LIGHT;
194         GetParameterWrap(DarkModeParamAssignUser(userId), darkValue);
195 
196         std::string fontSize = BASE_SCALE;
197         GetParameterWrap(FontScaleParamAssignUser(userId), fontSize);
198 
199         std::string fontWeight = BASE_SCALE;
200         GetParameterWrap(FontWeightScaleParamAssignUser(userId), fontWeight);
201 
202         UiAppearanceParam tmpParam;
203         tmpParam.darkMode = darkValue == DARK ? DarkMode::ALWAYS_DARK : DarkMode::ALWAYS_LIGHT;
204         tmpParam.fontScale = fontSize;
205         tmpParam.fontWeightScale = fontWeight;
206         usersParam_[userId] = tmpParam;
207     }
208     isInitializationFinished_ = true;
209 }
210 
UpdateCurrentUserConfiguration(const int32_t userId)211 void UiAppearanceAbility::UpdateCurrentUserConfiguration(const int32_t userId)
212 {
213     UiAppearanceParam tmpParam = usersParam_[userId];
214     AppExecFwk::Configuration config;
215     config.AddItem(
216         AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, tmpParam.darkMode == DarkMode::ALWAYS_DARK ? DARK : LIGHT);
217     config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_SIZE_SCALE, tmpParam.fontScale);
218     config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_WEIGHT_SCALE, tmpParam.fontWeightScale);
219 
220     auto appManagerInstance = GetAppManagerInstance();
221     if (appManagerInstance != nullptr) {
222         appManagerInstance->UpdateConfiguration(config, userId);
223         SetParameterWrap(PERSIST_DARKMODE_KEY, tmpParam.darkMode == DarkMode::ALWAYS_DARK ? DARK : LIGHT);
224         SetParameterWrap(FONT_SCAL_FOR_USER0, tmpParam.fontScale);
225         SetParameterWrap(FONT_Weight_SCAL_FOR_USER0, tmpParam.fontWeightScale);
226         LOGD("user switch update config %{public}s", config.GetName().c_str());
227     }
228 }
229 
UserSwitchFunc(const int32_t userId)230 void UiAppearanceAbility::UserSwitchFunc(const int32_t userId)
231 {
232     std::unique_lock<std::recursive_mutex> guard(usersParamMutex_);
233     if (isNeedDoCompatibleProcess_) {
234         DoCompatibleProcess();
235     }
236     if (!isInitializationFinished_) {
237         DoInitProcess();
238     }
239     UpdateCurrentUserConfiguration(userId);
240 }
241 
SubscribeUserSwitchEvent()242 void UiAppearanceAbility::SubscribeUserSwitchEvent()
243 {
244     EventFwk::MatchingSkills matchingSkills;
245     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED);
246     EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
247     subscribeInfo.SetThreadMode(EventFwk::CommonEventSubscribeInfo::COMMON);
248 
249     userSwitchSubscriber_ = std::make_shared<UserSwitchEventSubscriber>(
250         subscribeInfo, [this](const int32_t userId) { UserSwitchFunc(userId); });
251     bool subResult = EventFwk::CommonEventManager::SubscribeCommonEvent(userSwitchSubscriber_);
252     if (!subResult) {
253         LOGW("subscribe user switch event error");
254     }
255 }
256 
OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)257 void UiAppearanceAbility::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
258 {
259     if (systemAbilityId != APP_MGR_SERVICE_ID) {
260         return;
261     }
262 
263     auto checkIfFirstUpgrade = [this]() {
264         std::string initFlag = NOT_FIRST_UPGRADE;
265         GetParameterWrap(FIRST_INITIALIZATION, initFlag);
266         if (initFlag == FIRST_UPGRADE) {
267             return true;
268         }
269         return false;
270     };
271     isNeedDoCompatibleProcess_ = checkIfFirstUpgrade();
272     SubscribeUserSwitchEvent();
273     std::unique_lock<std::recursive_mutex> guard(usersParamMutex_);
274     if (isNeedDoCompatibleProcess_ && !GetUserIds().empty()) {
275         DoCompatibleProcess();
276     }
277 
278     if (!isInitializationFinished_ && !GetUserIds().empty()) {
279         DoInitProcess();
280         int32_t userId = USER100;
281         auto errCode = AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(userId);
282         if (errCode != 0) {
283             LOGW("GetForegroundOsAccountLocalId error: %{public}d.", errCode);
284             userId = USER100;
285         }
286         UpdateCurrentUserConfiguration(userId);
287     }
288 }
289 
OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)290 void UiAppearanceAbility::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
291 {
292     LOGI("systemAbilityId = %{public}d removed.", systemAbilityId);
293 }
294 
GetCallingUserId()295 int32_t UiAppearanceAbility::GetCallingUserId()
296 {
297     const static int32_t UID_TRANSFORM_DIVISOR = 200000;
298 
299     LOGD("CallingUid = %{public}d", OHOS::IPCSkeleton::GetCallingUid());
300     int32_t userId = OHOS::IPCSkeleton::GetCallingUid() / UID_TRANSFORM_DIVISOR;
301     if (userId == 0) {
302         auto errNo = AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(userId);
303         if (errNo != 0) {
304             LOGE("CallingUid = %{public}d, GetForegroundOsAccountLocalId error:%{public}d",
305                 OHOS::IPCSkeleton::GetCallingUid(), errNo);
306             userId = USER100;
307         }
308     }
309     return userId;
310 }
311 
DarkModeParamAssignUser(const int32_t userId)312 std::string UiAppearanceAbility::DarkModeParamAssignUser(const int32_t userId)
313 {
314     return PERSIST_DARKMODE_KEY_FOR_NONE + std::to_string(userId);
315 }
FontScaleParamAssignUser(const int32_t userId)316 std::string UiAppearanceAbility::FontScaleParamAssignUser(const int32_t userId)
317 {
318     return FONT_SCAL_FOR_NONE + std::to_string(userId);
319 }
FontWeightScaleParamAssignUser(const int32_t userId)320 std::string UiAppearanceAbility::FontWeightScaleParamAssignUser(const int32_t userId)
321 {
322     return FONT_WEIGHT_SCAL_FOR_NONE + std::to_string(userId);
323 }
IsUserExist(const int32_t userId)324 bool UiAppearanceAbility::IsUserExist(const int32_t userId)
325 {
326     std::unique_lock<std::recursive_mutex> guard(usersParamMutex_);
327     return usersParam_.find(userId) != usersParam_.end();
328 }
329 
GetParameterWrap( const std::string& paramName, std::string& value, const std::string& defaultValue)330 bool UiAppearanceAbility::GetParameterWrap(
331     const std::string& paramName, std::string& value, const std::string& defaultValue)
332 {
333     char buf[256] = { 0 };
334     auto res = GetParameter(paramName.c_str(), defaultValue.c_str(), buf, sizeof(buf));
335     if (res <= 0) {
336         LOGE("get parameter %{public}s failed", paramName.c_str());
337         return false;
338     }
339     LOGD("get parameter %{public}s:%{public}s", paramName.c_str(), value.c_str());
340     value = buf;
341     return true;
342 }
GetParameterWrap(const std::string& paramName, std::string& value)343 bool UiAppearanceAbility::GetParameterWrap(const std::string& paramName, std::string& value)
344 {
345     const auto defaultValue = value;
346     return GetParameterWrap(paramName, value, defaultValue);
347 }
SetParameterWrap(const std::string& paramName, const std::string& value)348 bool UiAppearanceAbility::SetParameterWrap(const std::string& paramName, const std::string& value)
349 {
350     auto res = SetParameter(paramName.c_str(), value.c_str());
351     if (res != 0) {
352         LOGE("set parameter %{public}s failed", paramName.c_str());
353         return false;
354     }
355     LOGD("set parameter %{public}s:%{public}s", paramName.c_str(), value.c_str());
356     return true;
357 }
358 
UpdateConfiguration(const AppExecFwk::Configuration& configuration, const int32_t userId)359 bool UiAppearanceAbility::UpdateConfiguration(const AppExecFwk::Configuration& configuration, const int32_t userId)
360 {
361     auto appManagerInstance = GetAppManagerInstance();
362     if (appManagerInstance == nullptr) {
363         LOGE("Get app manager proxy failed.");
364         return false;
365     }
366 
367     LOGI("update Configuration start,userId:%{public}d config = %{public}s.", userId, configuration.GetName().c_str());
368     auto errcode = appManagerInstance->UpdateConfiguration(configuration, userId);
369     if (errcode != 0) {
370         AppExecFwk::Configuration config;
371         auto retVal = appManagerInstance->GetConfiguration(config);
372         if (retVal != 0) {
373             LOGE("get configuration failed, update error, error is %{public}d.", retVal);
374             return false;
375         }
376         std::vector<std::string> diffVe;
377         config.CompareDifferent(diffVe, configuration);
378 
379         if (!diffVe.empty()) {
380             LOGE("update configuration failed, errcode = %{public}d.", errcode);
381             return false;
382         } else {
383             LOGW("uiappearance is different against configuration. Forced to use the configuration, error is "
384                  "%{public}d.",
385                 errcode);
386         }
387     }
388     return true;
389 }
390 
OnSetDarkMode(const int32_t userId, DarkMode mode)391 int32_t UiAppearanceAbility::OnSetDarkMode(const int32_t userId, DarkMode mode)
392 {
393     bool ret = false;
394     std::string paramValue;
395     AppExecFwk::Configuration config;
396     switch (mode) {
397         case ALWAYS_LIGHT: {
398             ret = config.AddItem(
399                 AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, AppExecFwk::ConfigurationInner::COLOR_MODE_LIGHT);
400             paramValue.assign(LIGHT);
401             break;
402         }
403         case ALWAYS_DARK: {
404             ret = config.AddItem(
405                 AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE, AppExecFwk::ConfigurationInner::COLOR_MODE_DARK);
406             paramValue.assign(DARK);
407             break;
408         }
409         default:
410             break;
411     }
412     if (!ret) {
413         LOGE("AddItem failed, mode = %{public}d", mode);
414         return INVALID_ARG;
415     }
416 
417     if (!UpdateConfiguration(config, userId)) {
418         return SYS_ERR;
419     }
420 
421     std::unique_lock<std::recursive_mutex> guard(usersParamMutex_);
422     if (IsUserExist(userId)) {
423         usersParam_[userId].darkMode = mode;
424     } else {
425         UiAppearanceParam tmpParam;
426         tmpParam.darkMode = mode;
427         usersParam_[userId] = tmpParam;
428     }
429 
430     SetParameterWrap(PERSIST_DARKMODE_KEY, paramValue);
431 
432     // persist to file: etc/para/ui_appearance.para
433     auto isSetPara = SetParameterWrap(DarkModeParamAssignUser(userId), paramValue);
434     if (!isSetPara) {
435         LOGE("set parameter failed");
436         return SYS_ERR;
437     }
438     return SUCCEEDED;
439 }
440 
SetDarkMode(DarkMode mode)441 int32_t UiAppearanceAbility::SetDarkMode(DarkMode mode)
442 {
443     // Verify permissions
444     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
445     if (!isCallingPerm) {
446         LOGE("permission verification failed");
447         return PERMISSION_ERR;
448     }
449     std::unique_lock<std::recursive_mutex> guard(usersParamMutex_);
450     auto userId = GetCallingUserId();
451     auto it = usersParam_.find(userId);
452     if (it != usersParam_.end()) {
453         if (mode != it->second.darkMode) {
454             return OnSetDarkMode(userId, mode);
455         } else {
456             LOGW("current color mode is %{public}d, no need to change", mode);
457         }
458     } else {
459         return OnSetDarkMode(userId, mode);
460     }
461 
462     return SYS_ERR;
463 }
464 
InitGetDarkMode(const int32_t userId)465 UiAppearanceAbility::DarkMode UiAppearanceAbility::InitGetDarkMode(const int32_t userId)
466 {
467     std::string valueGet = LIGHT;
468 
469     // LIGHT is the default.
470     auto res = GetParameterWrap(DarkModeParamAssignUser(userId), valueGet);
471     if (!res) {
472         return ALWAYS_LIGHT;
473     }
474     if (valueGet == DARK) {
475         LOGI("current color mode is dark.");
476         return ALWAYS_DARK;
477     } else if (valueGet == LIGHT) {
478         LOGI("current color mode is light.");
479         return ALWAYS_LIGHT;
480     }
481     return ALWAYS_LIGHT;
482 }
483 
GetDarkMode()484 int32_t UiAppearanceAbility::GetDarkMode()
485 {
486     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
487     if (!isCallingPerm) {
488         LOGE("permission verification failed");
489         return PERMISSION_ERR;
490     }
491     std::unique_lock<std::recursive_mutex> guard(usersParamMutex_);
492     auto it = usersParam_.find(GetCallingUserId());
493     if (it != usersParam_.end()) {
494         return it->second.darkMode;
495     }
496     return DarkMode::ALWAYS_LIGHT;
497 }
498 
OnSetFontScale(const int32_t userId, std::string& fontScale)499 int32_t UiAppearanceAbility::OnSetFontScale(const int32_t userId, std::string& fontScale)
500 {
501     bool ret = false;
502     AppExecFwk::Configuration config;
503     ret = config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_SIZE_SCALE, fontScale);
504     if (!ret) {
505         LOGE("AddItem failed, fontScale = %{public}s", fontScale.c_str());
506         return INVALID_ARG;
507     }
508     if (!UpdateConfiguration(config, userId)) {
509         return SYS_ERR;
510     }
511 
512     std::unique_lock<std::recursive_mutex> guard(usersParamMutex_);
513     if (IsUserExist(userId)) {
514         usersParam_[userId].fontScale = fontScale;
515     } else {
516         UiAppearanceParam tmpParam;
517         tmpParam.fontScale = fontScale;
518         usersParam_[userId] = tmpParam;
519     }
520 
521     SetParameterWrap(FONT_SCAL_FOR_USER0, fontScale);
522     // persist to file: etc/para/ui_appearance.para
523     auto isSetPara = SetParameterWrap(FontScaleParamAssignUser(userId), fontScale);
524     if (!isSetPara) {
525         LOGE("set parameter failed");
526         return SYS_ERR;
527     }
528     return SUCCEEDED;
529 }
530 
SetFontScale(std::string& fontScale)531 int32_t UiAppearanceAbility::SetFontScale(std::string& fontScale)
532 {
533     // Verify permissions
534     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
535     if (!isCallingPerm) {
536         LOGE("permission verification failed");
537         return PERMISSION_ERR;
538     }
539     if (!fontScale.empty()) {
540         return OnSetFontScale(GetCallingUserId(), fontScale);
541     } else {
542         LOGE("current fontScale is empty!");
543     }
544     return SYS_ERR;
545 }
546 
GetFontScale(std::string& fontScale)547 int32_t UiAppearanceAbility::GetFontScale(std::string& fontScale)
548 {
549     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
550     if (!isCallingPerm) {
551         LOGE("permission verification failed");
552         return PERMISSION_ERR;
553     }
554     std::unique_lock<std::recursive_mutex> guard(usersParamMutex_);
555     auto it = usersParam_.find(GetCallingUserId());
556     if (it != usersParam_.end()) {
557         fontScale = it->second.fontScale;
558     } else {
559         fontScale = BASE_SCALE;
560     }
561     LOGD("get font scale :%{public}s", fontScale.c_str());
562     return SUCCEEDED;
563 }
564 
OnSetFontWeightScale(const int32_t userId, std::string& fontWeightScale)565 int32_t UiAppearanceAbility::OnSetFontWeightScale(const int32_t userId, std::string& fontWeightScale)
566 {
567     bool ret = false;
568     AppExecFwk::Configuration config;
569     ret = config.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_WEIGHT_SCALE, fontWeightScale);
570     if (!ret) {
571         LOGE("AddItem failed, fontWeightScale = %{public}s", fontWeightScale.c_str());
572         return INVALID_ARG;
573     }
574 
575     if (!UpdateConfiguration(config, userId)) {
576         return SYS_ERR;
577     }
578     std::unique_lock<std::recursive_mutex> guard(usersParamMutex_);
579     if (IsUserExist(userId)) {
580         usersParam_[userId].fontWeightScale = fontWeightScale;
581     } else {
582         UiAppearanceParam tmpParam;
583         tmpParam.fontWeightScale = fontWeightScale;
584         usersParam_[userId] = tmpParam;
585     }
586 
587     SetParameterWrap(FONT_Weight_SCAL_FOR_USER0, fontWeightScale);
588 
589     // persist to file: etc/para/ui_appearance.para
590     auto isSetPara = SetParameterWrap(FontWeightScaleParamAssignUser(userId), fontWeightScale);
591     if (!isSetPara) {
592         LOGE("set parameter failed");
593         return SYS_ERR;
594     }
595     return SUCCEEDED;
596 }
597 
SetFontWeightScale(std::string& fontWeightScale)598 int32_t UiAppearanceAbility::SetFontWeightScale(std::string& fontWeightScale)
599 {
600     // Verify permissions
601     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
602     if (!isCallingPerm) {
603         LOGE("permission verification failed");
604         return PERMISSION_ERR;
605     }
606     if (!fontWeightScale.empty()) {
607         return OnSetFontWeightScale(GetCallingUserId(), fontWeightScale);
608     } else {
609         LOGE("current fontWeightScale is empty!");
610     }
611     return SYS_ERR;
612 }
613 
GetFontWeightScale(std::string& fontWeightScale)614 int32_t UiAppearanceAbility::GetFontWeightScale(std::string& fontWeightScale)
615 {
616     auto isCallingPerm = VerifyAccessToken(PERMISSION_UPDATE_CONFIGURATION);
617     if (!isCallingPerm) {
618         LOGE("permission verification failed");
619         return PERMISSION_ERR;
620     }
621     std::unique_lock<std::recursive_mutex> guard(usersParamMutex_);
622     auto it = usersParam_.find(GetCallingUserId());
623     if (it != usersParam_.end()) {
624         fontWeightScale = it->second.fontWeightScale;
625     } else {
626         fontWeightScale = BASE_SCALE;
627     }
628     LOGD("get font weight scale :%{public}s", fontWeightScale.c_str());
629     return SUCCEEDED;
630 }
631 
632 } // namespace ArkUi::UiAppearance
633 } // namespace OHOS
634