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
SaveGlobalParam(const std::string & localId)175 I18nErrorCode MultiUsers::SaveGlobalParam(const std::string& localId)
176 {
177 std::string language = LocaleConfig::GetSystemLanguage();
178 std::string locale = LocaleConfig::GetSystemLocale();
179 std::string is24Hour = ReadSystemParameter(LocaleConfig::HOUR_KEY.c_str(), CONFIG_LEN);
180 if (is24Hour.empty()) {
181 HILOG_ERROR_I18N("SaveIs24Hour: Get is24Hour failed");
182 return I18nErrorCode::FAILED;
183 }
184 I18nErrorCode errCode = SaveLanguage(localId, language);
185 if (errCode != I18nErrorCode::SUCCESS) {
186 HILOG_ERROR_I18N("SaveGlobalParam: save language failed");
187 return I18nErrorCode::FAILED;
188 }
189 errCode = SaveLocale(localId, locale);
190 if (errCode != I18nErrorCode::SUCCESS) {
191 HILOG_ERROR_I18N("SaveGlobalParam: save locale failed");
192 return I18nErrorCode::FAILED;
193 }
194 errCode = SaveIs24Hour(localId, is24Hour);
195 if (errCode != I18nErrorCode::SUCCESS) {
196 HILOG_ERROR_I18N("SaveGlobalParam: save is24Hour failed");
197 return I18nErrorCode::FAILED;
198 }
199 return I18nErrorCode::SUCCESS;
200 }
201
LoadGlobalParam(const std::string & localId)202 I18nErrorCode MultiUsers::LoadGlobalParam(const std::string& localId)
203 {
204 std::string newLocale = ReadMultiUsersParameter(MULTI_USERS_LOCALE_KEY, localId);
205 if (!newLocale.empty() && SetParameter(LocaleConfig::LOCALE_KEY.c_str(), newLocale.c_str()) != 0) {
206 HILOG_ERROR_I18N("LoadGlobalParam: set locale failed");
207 return I18nErrorCode::FAILED;
208 }
209
210 std::string newLanguage = ReadMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, localId);
211 if (!newLanguage.empty() && SetParameter(LocaleConfig::LANGUAGE_KEY.c_str(), newLanguage.c_str()) != 0) {
212 HILOG_ERROR_I18N("LoadGlobalParam: set language failed");
213 return I18nErrorCode::FAILED;
214 }
215
216 std::string newIs24Hour = ReadMultiUsersParameter(MULTI_USERS_HOUR_KEY, localId);
217 if (!newIs24Hour.empty() && SetParameter(LocaleConfig::HOUR_KEY.c_str(), newIs24Hour.c_str()) != 0) {
218 HILOG_ERROR_I18N("LoadGlobalParam: set is24Hour failed");
219 return I18nErrorCode::FAILED;
220 }
221 #ifdef SUPPORT_GRAPHICS
222 int32_t status = 0;
223 int32_t userId = ConvertString2Int(localId, status);
224 if (status == -1) {
225 HILOG_ERROR_I18N("LoadGlobalParam: convert userId failed");
226 return I18nErrorCode::FAILED;
227 }
228 UpdateConfiguration(newLocale, newIs24Hour, userId);
229 return PublishCommonEvent(userId);
230 #endif
231 return I18nErrorCode::SUCCESS;
232 }
233
RemoveGlobalParam(const std::string & localId)234 I18nErrorCode MultiUsers::RemoveGlobalParam(const std::string& localId)
235 {
236 I18nErrorCode errCode = WriteMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, "", localId, true);
237 if (errCode != I18nErrorCode::SUCCESS) {
238 HILOG_ERROR_I18N("RemoveGlobalParam: remove language failed");
239 return I18nErrorCode::FAILED;
240 }
241
242 errCode = WriteMultiUsersParameter(MULTI_USERS_LOCALE_KEY, "", localId, true);
243 if (errCode != I18nErrorCode::SUCCESS) {
244 HILOG_ERROR_I18N("RemoveGlobalParam: remove locale failed");
245 return I18nErrorCode::FAILED;
246 }
247
248 errCode = WriteMultiUsersParameter(MULTI_USERS_HOUR_KEY, "", localId, true);
249 if (errCode != I18nErrorCode::SUCCESS) {
250 HILOG_ERROR_I18N("RemoveGlobalParam: remove is24Hour failed");
251 return I18nErrorCode::FAILED;
252 }
253
254 return I18nErrorCode::SUCCESS;
255 }
256
ReadMultiUsersParameter(const std::string & paramKey,const std::string & localId)257 std::string MultiUsers::ReadMultiUsersParameter(const std::string& paramKey, const std::string& localId)
258 {
259 std::string param = GetParamFromPreferences(paramKey);
260 if (param.empty()) {
261 return "";
262 }
263 std::vector<std::string> multiUsersParam;
264 Split(param, ";", multiUsersParam);
265 for (auto& userParam : multiUsersParam) {
266 std::vector<std::string> content;
267 Split(userParam, ":", content);
268 // 2 is number of param
269 if (content.size() != 2) {
270 continue;
271 }
272 if (content[0] == localId) {
273 return content[1];
274 }
275 }
276 return "";
277 }
278
WriteMultiUsersParameter(const std::string & paramKey,const std::string & paramValue,const std::string & localId,bool isDel)279 I18nErrorCode MultiUsers::WriteMultiUsersParameter(const std::string& paramKey, const std::string& paramValue,
280 const std::string& localId, bool isDel)
281 {
282 std::string param = GetParamFromPreferences(paramKey);
283 std::vector<std::string> multiUsersParam;
284 Split(param, ";", multiUsersParam);
285 std::vector<std::string> newMultiUsersParam;
286 bool userIsExist = false;
287 for (auto& userParam : multiUsersParam) {
288 std::vector<std::string> content;
289 Split(userParam, ":", content);
290 // 2 is number of param
291 if (content.size() != 2) {
292 continue;
293 }
294 std::string userLocalId = content[0];
295 if (!isDel && userLocalId == localId) {
296 content[1] = paramValue;
297 Merge(content, ":", userParam);
298 userIsExist = true;
299 }
300 newMultiUsersParam.emplace_back(userParam);
301 if (isDel && userLocalId == localId) {
302 newMultiUsersParam.pop_back();
303 }
304 }
305 if (!isDel && !userIsExist) {
306 newMultiUsersParam.push_back(localId + ":" + paramValue);
307 }
308 std::string newParam;
309 Merge(newMultiUsersParam, ";", newParam);
310 if (SetParamFromPreferences(paramKey, newParam) != I18nErrorCode::SUCCESS) {
311 HILOG_ERROR_I18N("WriteMultiUsersParameter: set param %{public}s failed", paramKey.c_str());
312 return I18nErrorCode::FAILED;
313 }
314 return I18nErrorCode::SUCCESS;
315 }
316
IsValidLocalId(const std::string & localId)317 bool MultiUsers::IsValidLocalId(const std::string& localId)
318 {
319 if (std::atoi(localId.c_str()) < DEFAULT_LOCAL_ID) {
320 HILOG_ERROR_I18N("IsValidLocalId: invalid local ID");
321 return false;
322 }
323 return true;
324 }
325
InitPreferences()326 void MultiUsers::InitPreferences()
327 {
328 if (preferences == nullptr) {
329 HILOG_INFO_I18N("InitPreferences: preferences Init");
330 OHOS::NativePreferences::Options opt(PREFERENCE_PATH);
331 int status = 0;
332 preferences = NativePreferences::PreferencesHelper::GetPreferences(opt, status);
333 if (status != 0) {
334 HILOG_ERROR_I18N("InitPreferences: get preferences failed");
335 preferences = nullptr;
336 }
337 }
338 }
339
GetParamFromPreferences(const std::string & paramKey)340 std::string MultiUsers::GetParamFromPreferences(const std::string& paramKey)
341 {
342 InitPreferences();
343 if (preferences == nullptr) {
344 HILOG_ERROR_I18N("GetParamFromPreferences: preferences is nullptr");
345 return "";
346 }
347 return preferences->GetString(paramKey, "");
348 }
349
SetParamFromPreferences(const std::string & paramKey,const std::string & paramValue)350 I18nErrorCode MultiUsers::SetParamFromPreferences(const std::string& paramKey, const std::string& paramValue)
351 {
352 InitPreferences();
353 if (preferences == nullptr) {
354 HILOG_ERROR_I18N("SetParamFromPreferences: preferences is nullptr");
355 return I18nErrorCode::FAILED;
356 }
357 int status = preferences->PutString(paramKey, paramValue);
358 if (status != 0) {
359 HILOG_ERROR_I18N("SetParamFromPreferences: put param %{public}s failed", paramKey.c_str());
360 return I18nErrorCode::FAILED;
361 }
362 preferences->Flush();
363 return I18nErrorCode::SUCCESS;
364 }
365
366 #ifdef SUPPORT_GRAPHICS
UpdateConfiguration(const std::string & locale,const std::string & is24Hour,int32_t userId)367 void MultiUsers::UpdateConfiguration(const std::string& locale, const std::string& is24Hour,
368 int32_t userId)
369 {
370 AppExecFwk::Configuration configuration;
371 configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE, locale);
372 configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_HOUR, is24Hour);
373 auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
374
375 AppExecFwk::AppMgrResultCode status = appMgrClient->UpdateConfiguration(configuration, userId);
376 if (status != AppExecFwk::AppMgrResultCode::RESULT_OK) {
377 HILOG_ERROR_I18N("MultiUsers::UpdateConfiguration: Update configuration userId %{public}d failed.", userId);
378 return;
379 }
380 HILOG_INFO_I18N("MultiUsers::UpdateConfiguration: Update configuration userId %{public}d success.", userId);
381 }
382
PublishCommonEvent(int32_t userId)383 I18nErrorCode MultiUsers::PublishCommonEvent(int32_t userId)
384 {
385 OHOS::AAFwk::Want localeChangeWant;
386 localeChangeWant.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED);
387 OHOS::EventFwk::CommonEventData localeChangeEvent(localeChangeWant);
388 if (!OHOS::EventFwk::CommonEventManager::PublishCommonEventAsUser(localeChangeEvent, userId)) {
389 HILOG_ERROR_I18N("MultiUsers::PublishCommonEvent: Failed to publish locale change event, userId %{public}d.",
390 userId);
391 return I18nErrorCode::PUBLISH_COMMON_EVENT_FAILED;
392 }
393
394 OHOS::AAFwk::Want is24HourChangeWant;
395 is24HourChangeWant.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED);
396 OHOS::EventFwk::CommonEventData is24HourChangeEvent(is24HourChangeWant);
397 is24HourChangeEvent.SetData(LocaleConfig::HOUR_EVENT_DATA);
398 if (!OHOS::EventFwk::CommonEventManager::PublishCommonEventAsUser(is24HourChangeEvent, userId)) {
399 HILOG_ERROR_I18N("MultiUsers::PublishCommonEvent: Failed to publish is24Hour change event, userId %{public}d.",
400 userId);
401 return I18nErrorCode::PUBLISH_COMMON_EVENT_FAILED;
402 }
403
404 HILOG_INFO_I18N("MultiUsers::PublishCommonEvent: Publish event finished, userId %{public}d.", userId);
405 return I18nErrorCode::SUCCESS;
406 }
407 #endif
408 } // namespace I18n
409 } // namespace Global
410 } // namespace OHOS
411