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