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
32namespace {
33static const std::string LIGHT = "light";
34static const std::string DARK = "dark";
35static const std::string BASE_SCALE = "1";
36static const std::string PERSIST_DARKMODE_KEY = "persist.ace.darkmode";
37static const std::string PERMISSION_UPDATE_CONFIGURATION = "ohos.permission.UPDATE_CONFIGURATION";
38// current default accountId = 0, will change when have more user.
39static const std::string FONT_SCAL_FOR_USER0 = "persist.sys.font_scale_for_user0";
40static const std::string FONT_Weight_SCAL_FOR_USER0 = "persist.sys.font_wght_scale_for_user0";
41
42static const std::string PERSIST_DARKMODE_KEY_FOR_NONE = "persist.ace.darkmode.";
43static const std::string FONT_SCAL_FOR_NONE = "persist.sys.font_scale_for_user.";
44static const std::string FONT_WEIGHT_SCAL_FOR_NONE = "persist.sys.font_wght_scale_for_user.";
45
46static const std::string FIRST_INITIALIZATION = "persist.uiAppearance.first_initialization";
47const static int32_t USER100 = 100;
48const static std::string FIRST_UPGRADE = "1";
49const static std::string NOT_FIRST_UPGRADE = "0";
50} // namespace
51
52namespace OHOS {
53namespace ArkUi::UiAppearance {
54
55UserSwitchEventSubscriber::UserSwitchEventSubscriber(const EventFwk::CommonEventSubscribeInfo& subscriberInfo,
56    const std::function<void(const int32_t)>& userSwitchCallback)
57    : EventFwk::CommonEventSubscriber(subscriberInfo), userSwitchCallback_(userSwitchCallback)
58{}
59
60void 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
73REGISTER_SYSTEM_ABILITY_BY_ID(UiAppearanceAbility, ARKUI_UI_APPEARANCE_SERVICE_ID, true);
74
75UiAppearanceAbility::UiAppearanceAbility(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate) {}
76
77sptr<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
100bool 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
111void 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
124void UiAppearanceAbility::OnStop()
125{
126    LOGI("UiAppearanceAbility SA stop.");
127}
128
129std::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
140void 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
188void 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
211void 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
230void 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
242void 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
257void 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
290void UiAppearanceAbility::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
291{
292    LOGI("systemAbilityId = %{public}d removed.", systemAbilityId);
293}
294
295int32_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
312std::string UiAppearanceAbility::DarkModeParamAssignUser(const int32_t userId)
313{
314    return PERSIST_DARKMODE_KEY_FOR_NONE + std::to_string(userId);
315}
316std::string UiAppearanceAbility::FontScaleParamAssignUser(const int32_t userId)
317{
318    return FONT_SCAL_FOR_NONE + std::to_string(userId);
319}
320std::string UiAppearanceAbility::FontWeightScaleParamAssignUser(const int32_t userId)
321{
322    return FONT_WEIGHT_SCAL_FOR_NONE + std::to_string(userId);
323}
324bool 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
330bool 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}
343bool UiAppearanceAbility::GetParameterWrap(const std::string& paramName, std::string& value)
344{
345    const auto defaultValue = value;
346    return GetParameterWrap(paramName, value, defaultValue);
347}
348bool 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
359bool 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
391int32_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
441int32_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
465UiAppearanceAbility::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
484int32_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
499int32_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
531int32_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
547int32_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
565int32_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
598int32_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
614int32_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