• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #ifdef SUPPORT_GRAPHICS
17 #include "app_mgr_client.h"
18 #include "ability_manager_client.h"
19 #include <common_event_manager.h>
20 #include <common_event_publish_info.h>
21 #include <common_event_support.h>
22 #endif
23 #include "i18n_hilog.h"
24 #include "locale_config.h"
25 #include "os_account_manager.h"
26 #include "parameter.h"
27 #include "utils.h"
28 
29 #include "multi_users.h"
30 
31 namespace OHOS {
32 namespace Global {
33 namespace I18n {
34 const std::string MultiUsers::MULTI_USERS_LANGUAGE_KEY = "languageData";
35 const std::string MultiUsers::MULTI_USERS_LOCALE_KEY = "localeData";
36 const std::string MultiUsers::MULTI_USERS_HOUR_KEY = "is24HourData";
37 const std::string MultiUsers::INIT_KEY = "init";
38 const std::string MultiUsers::PREFERENCE_PATH = "/data/service/el1/public/i18n/global/GlobalParamData";
39 const int32_t MultiUsers::DEFAULT_LOCAL_ID = 100;
40 const int MultiUsers::CONFIG_LEN = 128;
41 std::shared_ptr<NativePreferences::Preferences> MultiUsers::preferences = nullptr;
42 
InitMultiUser()43 void MultiUsers::InitMultiUser()
44 {
45     InitPreferences();
46     if (preferences == nullptr) {
47         HILOG_ERROR_I18N("InitMultiUser: InitPreferences failed");
48         return;
49     }
50     bool init = preferences->GetBool(INIT_KEY, false);
51     std::string localId;
52     I18nErrorCode errCode = GetForegroundLocalId(localId);
53     if (errCode != I18nErrorCode::SUCCESS) {
54         HILOG_ERROR_I18N("InitMultiUser: get foreground local id failed");
55         return;
56     }
57     if (!init) {
58         AddUser(localId);
59         preferences->PutBool(INIT_KEY, true);
60         preferences->Flush();
61         HILOG_INFO_I18N("InitMultiUser: init multi user data success");
62     }
63 }
64 
SwitchUser(const std::string & curLocalId)65 void MultiUsers::SwitchUser(const std::string& curLocalId)
66 {
67     if (!IsValidLocalId(curLocalId)) {
68         HILOG_ERROR_I18N("SwitchUser: curLocalId is an invalid LocalId");
69         return;
70     }
71     I18nErrorCode errCode = LoadGlobalParam(curLocalId);
72     if (errCode != I18nErrorCode::SUCCESS) {
73         HILOG_ERROR_I18N("SwitchUser: load global params failed");
74     }
75 }
76 
AddUser(const std::string & localId)77 void MultiUsers::AddUser(const std::string& localId)
78 {
79     if (!IsValidLocalId(localId)) {
80         HILOG_ERROR_I18N("AddUser: localId is invalid");
81         return;
82     }
83     I18nErrorCode errCode = SaveGlobalParam(localId);
84     if (errCode != I18nErrorCode::SUCCESS) {
85         HILOG_ERROR_I18N("AddUser: add global param failed");
86     }
87 }
88 
RemoveUser(const std::string & localId)89 void MultiUsers::RemoveUser(const std::string& localId)
90 {
91     if (!IsValidLocalId(localId)) {
92         HILOG_ERROR_I18N("RemoveUser: localId is invalid");
93         return;
94     }
95     I18nErrorCode errCode = RemoveGlobalParam(localId);
96     if (errCode != I18nErrorCode::SUCCESS) {
97         HILOG_ERROR_I18N("RemoveUser: remove global param failed");
98     }
99 }
100 
GetForegroundLocalId(std::string & localId)101 I18nErrorCode MultiUsers::GetForegroundLocalId(std::string& localId)
102 {
103     int id = 0;
104     int errCode = OHOS::AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(id);
105     if (errCode != 0) {
106         HILOG_ERROR_I18N("GetForegroundLocalId: get foreground locale Id failed, errCode is %{public}d", errCode);
107         return I18nErrorCode::FAILED;
108     }
109     localId = std::to_string(id);
110     return I18nErrorCode::SUCCESS;
111 }
112 
SaveLanguage(const std::string & localId,const std::string & language)113 I18nErrorCode MultiUsers::SaveLanguage(const std::string& localId, const std::string& language)
114 {
115     std::string foregroundLocalId = localId;
116     I18nErrorCode errCode = I18nErrorCode::SUCCESS;
117     if (localId.empty()) {
118         errCode = MultiUsers::GetForegroundLocalId(foregroundLocalId);
119     }
120     if (errCode != I18nErrorCode::SUCCESS) {
121         HILOG_ERROR_I18N("SaveLanguage: get foreground locale Id failed");
122         return I18nErrorCode::FAILED;
123     }
124 
125     errCode =
126         WriteMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, language, foregroundLocalId, false);
127     if (errCode != I18nErrorCode::SUCCESS) {
128         HILOG_ERROR_I18N("SaveLanguage: save language failed");
129         return I18nErrorCode::FAILED;
130     }
131     return I18nErrorCode::SUCCESS;
132 }
133 
SaveLocale(const std::string & localId,const std::string & locale)134 I18nErrorCode MultiUsers::SaveLocale(const std::string& localId, const std::string& locale)
135 {
136     std::string foregroundLocalId = localId;
137     I18nErrorCode errCode = I18nErrorCode::SUCCESS;
138     if (localId.empty()) {
139         errCode = MultiUsers::GetForegroundLocalId(foregroundLocalId);
140     }
141     if (errCode != I18nErrorCode::SUCCESS) {
142         HILOG_ERROR_I18N("SaveLocale: get foreground locale Id failed");
143         return I18nErrorCode::FAILED;
144     }
145 
146     errCode =
147         WriteMultiUsersParameter(MULTI_USERS_LOCALE_KEY, locale, foregroundLocalId, false);
148     if (errCode != I18nErrorCode::SUCCESS) {
149         HILOG_ERROR_I18N("SaveLocale: save locale failed");
150         return I18nErrorCode::FAILED;
151     }
152     return I18nErrorCode::SUCCESS;
153 }
154 
SaveIs24Hour(const std::string & localId,const std::string & is24Hour)155 I18nErrorCode MultiUsers::SaveIs24Hour(const std::string& localId, const std::string& is24Hour)
156 {
157     std::string foregroundLocalId = localId;
158     I18nErrorCode errCode = I18nErrorCode::SUCCESS;
159     if (localId.empty()) {
160         errCode = MultiUsers::GetForegroundLocalId(foregroundLocalId);
161     }
162     if (errCode != I18nErrorCode::SUCCESS) {
163         HILOG_ERROR_I18N("SaveLanguage: get foreground locale Id failed");
164         return I18nErrorCode::FAILED;
165     }
166     errCode =
167         WriteMultiUsersParameter(MULTI_USERS_HOUR_KEY, is24Hour, foregroundLocalId, false);
168     if (errCode != I18nErrorCode::SUCCESS) {
169         HILOG_ERROR_I18N("SaveIs24Hour: save is24Hour failed");
170         return I18nErrorCode::FAILED;
171     }
172     return I18nErrorCode::SUCCESS;
173 }
174 
GetLanguageFromUserId(int32_t userId)175 std::string MultiUsers::GetLanguageFromUserId(int32_t userId)
176 {
177     std::string localId = std::to_string(userId);
178     std::string locale = ReadMultiUsersParameter(MULTI_USERS_LOCALE_KEY, localId);
179     std::string language = ReadMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, localId);
180     if (locale.empty() || language.empty()) {
181         HILOG_ERROR_I18N("MultiUsers::GetLanguageFromUserId: Get language from userId %{public}d failed, "
182             "locale %{public}s, language %{public}s.", userId, locale.c_str(), language.c_str());
183         return LocaleConfig::GetEffectiveLanguage();
184     }
185     return LocaleConfig::ComputeEffectiveLanguage(locale, language);
186 }
187 
GetSystemLanguageFromUserId(int32_t userId)188 std::string MultiUsers::GetSystemLanguageFromUserId(int32_t userId)
189 {
190     if (userId == -1) {
191         return LocaleConfig::GetSystemLanguage();
192     }
193     std::string localId = std::to_string(userId);
194     std::string language = ReadMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, localId);
195     if (language.empty()) {
196         HILOG_ERROR_I18N("MultiUsers::GetSystemLanguageFromUserId: Get language failed.");
197         return LocaleConfig::GetSystemLanguage();
198     }
199     return language;
200 }
201 
GetSystemLocaleFromUserId(int32_t userId)202 std::string MultiUsers::GetSystemLocaleFromUserId(int32_t userId)
203 {
204     if (userId == -1) {
205         return LocaleConfig::GetEffectiveLocale();
206     }
207     std::string localId = std::to_string(userId);
208     std::string locale = ReadMultiUsersParameter(MULTI_USERS_LOCALE_KEY, localId);
209     if (locale.empty()) {
210         HILOG_ERROR_I18N("MultiUsers::GetSystemLocaleFromUserId: Get locale failed.");
211         return LocaleConfig::GetEffectiveLocale();
212     }
213     return locale;
214 }
215 
SaveGlobalParam(const std::string & localId)216 I18nErrorCode MultiUsers::SaveGlobalParam(const std::string& localId)
217 {
218     std::string language = LocaleConfig::GetSystemLanguage();
219     std::string locale = LocaleConfig::GetEffectiveLocale();
220     std::string is24Hour = ReadSystemParameter(LocaleConfig::HOUR_KEY.c_str(), CONFIG_LEN);
221     if (is24Hour.empty()) {
222         HILOG_ERROR_I18N("SaveIs24Hour: Get is24Hour failed");
223         return I18nErrorCode::FAILED;
224     }
225     I18nErrorCode errCode = SaveLanguage(localId, language);
226     if (errCode != I18nErrorCode::SUCCESS) {
227         HILOG_ERROR_I18N("SaveGlobalParam: save language failed");
228         return I18nErrorCode::FAILED;
229     }
230     errCode = SaveLocale(localId, locale);
231     if (errCode != I18nErrorCode::SUCCESS) {
232         HILOG_ERROR_I18N("SaveGlobalParam: save locale failed");
233         return I18nErrorCode::FAILED;
234     }
235     errCode = SaveIs24Hour(localId, is24Hour);
236     if (errCode != I18nErrorCode::SUCCESS) {
237         HILOG_ERROR_I18N("SaveGlobalParam: save is24Hour failed");
238         return I18nErrorCode::FAILED;
239     }
240     return I18nErrorCode::SUCCESS;
241 }
242 
LoadGlobalParam(const std::string & localId)243 I18nErrorCode MultiUsers::LoadGlobalParam(const std::string& localId)
244 {
245     std::string newLocale = ReadMultiUsersParameter(MULTI_USERS_LOCALE_KEY, localId);
246     if (!newLocale.empty() && SetParameter(LocaleConfig::LOCALE_KEY.c_str(), newLocale.c_str()) != 0) {
247         HILOG_ERROR_I18N("LoadGlobalParam: set locale failed");
248         return I18nErrorCode::FAILED;
249     }
250 
251     std::string newLanguage = ReadMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, localId);
252     if (!newLanguage.empty() && SetParameter(LocaleConfig::LANGUAGE_KEY.c_str(), newLanguage.c_str()) != 0) {
253         HILOG_ERROR_I18N("LoadGlobalParam: set language failed");
254         return I18nErrorCode::FAILED;
255     }
256 
257     std::string newIs24Hour = ReadMultiUsersParameter(MULTI_USERS_HOUR_KEY, localId);
258     if (!newIs24Hour.empty() && SetParameter(LocaleConfig::HOUR_KEY.c_str(), newIs24Hour.c_str()) != 0) {
259         HILOG_ERROR_I18N("LoadGlobalParam: set is24Hour failed");
260         return I18nErrorCode::FAILED;
261     }
262 #ifdef SUPPORT_GRAPHICS
263     int32_t status = 0;
264     int32_t userId = ConvertString2Int(localId, status);
265     if (status == -1) {
266         HILOG_ERROR_I18N("LoadGlobalParam: convert userId failed");
267         return I18nErrorCode::FAILED;
268     }
269     std::string effectiveLanguage = LocaleConfig::ComputeEffectiveLanguage(newLocale, newLanguage);
270     UpdateConfiguration(newLocale, effectiveLanguage, newIs24Hour, userId);
271     return PublishCommonEvent(userId);
272 #endif
273     return I18nErrorCode::SUCCESS;
274 }
275 
RemoveGlobalParam(const std::string & localId)276 I18nErrorCode MultiUsers::RemoveGlobalParam(const std::string& localId)
277 {
278     I18nErrorCode errCode = WriteMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, "", localId, true);
279     if (errCode != I18nErrorCode::SUCCESS) {
280         HILOG_ERROR_I18N("RemoveGlobalParam: remove language failed");
281         return I18nErrorCode::FAILED;
282     }
283 
284     errCode = WriteMultiUsersParameter(MULTI_USERS_LOCALE_KEY, "", localId, true);
285     if (errCode != I18nErrorCode::SUCCESS) {
286         HILOG_ERROR_I18N("RemoveGlobalParam: remove locale failed");
287         return I18nErrorCode::FAILED;
288     }
289 
290     errCode = WriteMultiUsersParameter(MULTI_USERS_HOUR_KEY, "", localId, true);
291     if (errCode != I18nErrorCode::SUCCESS) {
292         HILOG_ERROR_I18N("RemoveGlobalParam: remove is24Hour failed");
293         return I18nErrorCode::FAILED;
294     }
295 
296     return I18nErrorCode::SUCCESS;
297 }
298 
ReadMultiUsersParameter(const std::string & paramKey,const std::string & localId)299 std::string MultiUsers::ReadMultiUsersParameter(const std::string& paramKey, const std::string& localId)
300 {
301     std::string param = GetParamFromPreferences(paramKey);
302     if (param.empty()) {
303         return "";
304     }
305     std::vector<std::string> multiUsersParam;
306     Split(param, ";", multiUsersParam);
307     for (auto& userParam : multiUsersParam) {
308         std::vector<std::string> content;
309         Split(userParam, ":", content);
310         // 2 is number of param
311         if (content.size() != 2) {
312             continue;
313         }
314         if (content[0] == localId) {
315             return content[1];
316         }
317     }
318     return "";
319 }
320 
WriteMultiUsersParameter(const std::string & paramKey,const std::string & paramValue,const std::string & localId,bool isDel)321 I18nErrorCode MultiUsers::WriteMultiUsersParameter(const std::string& paramKey, const std::string& paramValue,
322     const std::string& localId, bool isDel)
323 {
324     std::string param = GetParamFromPreferences(paramKey);
325     std::vector<std::string> multiUsersParam;
326     Split(param, ";", multiUsersParam);
327     std::vector<std::string> newMultiUsersParam;
328     bool userIsExist = false;
329     for (auto& userParam : multiUsersParam) {
330         std::vector<std::string> content;
331         Split(userParam, ":", content);
332         // 2 is number of param
333         if (content.size() != 2) {
334             continue;
335         }
336         std::string userLocalId = content[0];
337         if (!isDel && userLocalId == localId) {
338             content[1] = paramValue;
339             Merge(content, ":", userParam);
340             userIsExist = true;
341         }
342         newMultiUsersParam.emplace_back(userParam);
343         if (isDel && userLocalId == localId) {
344             newMultiUsersParam.pop_back();
345         }
346     }
347     if (!isDel && !userIsExist) {
348         newMultiUsersParam.push_back(localId + ":" + paramValue);
349     }
350     std::string newParam;
351     Merge(newMultiUsersParam, ";", newParam);
352     if (SetParamFromPreferences(paramKey, newParam) != I18nErrorCode::SUCCESS) {
353         HILOG_ERROR_I18N("WriteMultiUsersParameter: set param %{public}s failed", paramKey.c_str());
354         return I18nErrorCode::FAILED;
355     }
356     return I18nErrorCode::SUCCESS;
357 }
358 
IsValidLocalId(const std::string & localId)359 bool MultiUsers::IsValidLocalId(const std::string& localId)
360 {
361     if (std::atoi(localId.c_str()) < DEFAULT_LOCAL_ID) {
362         HILOG_ERROR_I18N("IsValidLocalId: invalid local ID");
363         return false;
364     }
365     return true;
366 }
367 
InitPreferences()368 void MultiUsers::InitPreferences()
369 {
370     if (preferences == nullptr) {
371         HILOG_INFO_I18N("InitPreferences: preferences Init");
372         OHOS::NativePreferences::Options opt(PREFERENCE_PATH);
373         int status = 0;
374         preferences = NativePreferences::PreferencesHelper::GetPreferences(opt, status);
375         if (status != 0) {
376             HILOG_ERROR_I18N("InitPreferences: get preferences failed");
377             preferences = nullptr;
378         }
379     }
380 }
381 
GetParamFromPreferences(const std::string & paramKey)382 std::string MultiUsers::GetParamFromPreferences(const std::string& paramKey)
383 {
384     InitPreferences();
385     if (preferences == nullptr) {
386         HILOG_ERROR_I18N("GetParamFromPreferences: preferences is nullptr");
387         return "";
388     }
389     return preferences->GetString(paramKey, "");
390 }
391 
SetParamFromPreferences(const std::string & paramKey,const std::string & paramValue)392 I18nErrorCode MultiUsers::SetParamFromPreferences(const std::string& paramKey, const std::string& paramValue)
393 {
394     InitPreferences();
395     if (preferences == nullptr) {
396         HILOG_ERROR_I18N("SetParamFromPreferences: preferences is nullptr");
397         return I18nErrorCode::FAILED;
398     }
399     int status = preferences->PutString(paramKey, paramValue);
400     if (status != 0) {
401         HILOG_ERROR_I18N("SetParamFromPreferences: put param %{public}s failed", paramKey.c_str());
402         return I18nErrorCode::FAILED;
403     }
404     preferences->Flush();
405     return I18nErrorCode::SUCCESS;
406 }
407 
408 #ifdef SUPPORT_GRAPHICS
UpdateConfiguration(const std::string & locale,const std::string & language,const std::string & is24Hour,int32_t userId)409 void MultiUsers::UpdateConfiguration(const std::string& locale, const std::string& language,
410     const std::string& is24Hour, int32_t userId)
411 {
412     AppExecFwk::Configuration configuration;
413     configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_LOCALE, locale);
414     configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE, language);
415     configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_HOUR, is24Hour);
416     auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
417 
418     AppExecFwk::AppMgrResultCode status = appMgrClient->UpdateConfiguration(configuration, userId);
419     if (status != AppExecFwk::AppMgrResultCode::RESULT_OK) {
420         HILOG_ERROR_I18N("MultiUsers::UpdateConfiguration: Update configuration userId %{public}d failed.", userId);
421         return;
422     }
423     HILOG_INFO_I18N("MultiUsers::UpdateConfiguration: Update configuration userId %{public}d success.", userId);
424 }
425 
PublishCommonEvent(int32_t userId)426 I18nErrorCode MultiUsers::PublishCommonEvent(int32_t userId)
427 {
428     OHOS::AAFwk::Want localeChangeWant;
429     localeChangeWant.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED);
430     OHOS::EventFwk::CommonEventData localeChangeEvent(localeChangeWant);
431     if (!OHOS::EventFwk::CommonEventManager::PublishCommonEventAsUser(localeChangeEvent, userId)) {
432         HILOG_ERROR_I18N("MultiUsers::PublishCommonEvent: Failed to publish locale change event, userId %{public}d.",
433             userId);
434         return I18nErrorCode::PUBLISH_COMMON_EVENT_FAILED;
435     }
436 
437     OHOS::AAFwk::Want is24HourChangeWant;
438     is24HourChangeWant.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED);
439     OHOS::EventFwk::CommonEventData is24HourChangeEvent(is24HourChangeWant);
440     is24HourChangeEvent.SetData(LocaleConfig::HOUR_EVENT_DATA);
441     if (!OHOS::EventFwk::CommonEventManager::PublishCommonEventAsUser(is24HourChangeEvent, userId)) {
442         HILOG_ERROR_I18N("MultiUsers::PublishCommonEvent: Failed to publish is24Hour change event, userId %{public}d.",
443             userId);
444         return I18nErrorCode::PUBLISH_COMMON_EVENT_FAILED;
445     }
446 
447     HILOG_INFO_I18N("MultiUsers::PublishCommonEvent: Publish event finished,  userId %{public}d.", userId);
448     return I18nErrorCode::SUCCESS;
449 }
450 #endif
451 } // namespace I18n
452 } // namespace Global
453 } // namespace OHOS
454