1 /*
2 * Copyright (c) 2023-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 #include "accesstoken_kit.h"
17 #include "i18n_hilog.h"
18 #include "i18n_service_ability_load_manager.h"
19 #include "ipc_skeleton.h"
20 #include "locale_config.h"
21 #include "mem_mgr_client.h"
22 #include "mem_mgr_proxy.h"
23 #include "multi_users.h"
24 #include "os_account_manager.h"
25 #include "preferred_language.h"
26 #include "preferences.h"
27 #include "preferences_helper.h"
28 #include "system_ability_definition.h"
29 #include "tokenid_kit.h"
30 #include "i18n_service_ability.h"
31
32 namespace OHOS {
33 namespace Global {
34 namespace I18n {
35 REGISTER_SYSTEM_ABILITY_BY_ID(I18nServiceAbility, I18N_SA_ID, false);
36 static const std::string UNLOAD_TASK = "i18n_service_unload";
37 static const uint32_t DELAY_MILLISECONDS_FOR_UNLOAD_SA = 10000;
38 static const int32_t UID_TRANSFORM_DIVISOR = 200000;
39 static const int32_t USER_DEFAULT = 100;
40
I18nServiceAbility(int32_t saId,bool runOnCreate)41 I18nServiceAbility::I18nServiceAbility(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate), taskNumber(0)
42 {
43 HILOG_INFO_I18N("I18nServiceAbility object init success.");
44 }
45
~I18nServiceAbility()46 I18nServiceAbility::~I18nServiceAbility()
47 {
48 HILOG_INFO_I18N("I18nServiceAbility object release.");
49 }
50
SetSystemLanguage(const std::string & language,int32_t & code)51 ErrCode I18nServiceAbility::SetSystemLanguage(const std::string& language, int32_t& code)
52 {
53 int pid = getpid();
54 StartTask(pid);
55 I18nErrorCode errCode = CheckPermission();
56 if (errCode != I18nErrorCode::SUCCESS) {
57 HILOG_ERROR_I18N("I18nServiceAbility::SetSystemLanguage: Check permission failed.");
58 code = static_cast<int32_t>(errCode);
59 FinishTask(pid);
60 return ERR_OK;
61 }
62 #ifdef SUPPORT_MULTI_USER
63 int32_t userId = GetCallingUserId();
64 errCode = LocaleConfig::SetSystemLanguage(language, userId);
65 #else
66 errCode = LocaleConfig::SetSystemLanguage(language);
67 #endif
68 code = static_cast<int32_t>(errCode);
69 FinishTask(pid);
70 return ERR_OK;
71 }
72
SetSystemRegion(const std::string & region,int32_t & code)73 ErrCode I18nServiceAbility::SetSystemRegion(const std::string& region, int32_t& code)
74 {
75 int pid = getpid();
76 StartTask(pid);
77 I18nErrorCode errCode = CheckPermission();
78 if (errCode != I18nErrorCode::SUCCESS) {
79 HILOG_ERROR_I18N("I18nServiceAbility::SetSystemRegion: Check permission failed.");
80 code = static_cast<int32_t>(errCode);
81 FinishTask(pid);
82 return ERR_OK;
83 }
84 #ifdef SUPPORT_MULTI_USER
85 int32_t userId = GetCallingUserId();
86 errCode = LocaleConfig::SetSystemRegion(region, userId);
87 #else
88 errCode = LocaleConfig::SetSystemRegion(region);
89 #endif
90 code = static_cast<int32_t>(errCode);
91 FinishTask(pid);
92 return ERR_OK;
93 }
94
SetSystemLocale(const std::string & locale,int32_t & code)95 ErrCode I18nServiceAbility::SetSystemLocale(const std::string& locale, int32_t& code)
96 {
97 int pid = getpid();
98 StartTask(pid);
99 I18nErrorCode errCode = CheckPermission();
100 if (errCode != I18nErrorCode::SUCCESS) {
101 HILOG_ERROR_I18N("I18nServiceAbility::SetSystemLocale: Check permission failed.");
102 code = static_cast<int32_t>(errCode);
103 FinishTask(pid);
104 return ERR_OK;
105 }
106 #ifdef SUPPORT_MULTI_USER
107 int32_t userId = GetCallingUserId();
108 errCode = LocaleConfig::SetSystemLocale(locale, userId);
109 #else
110 errCode = LocaleConfig::SetSystemLocale(locale);
111 #endif
112 code = static_cast<int32_t>(errCode);
113 FinishTask(pid);
114 return ERR_OK;
115 }
116
Set24HourClock(const std::string & flag,int32_t & code)117 ErrCode I18nServiceAbility::Set24HourClock(const std::string& flag, int32_t& code)
118 {
119 int pid = getpid();
120 StartTask(pid);
121 I18nErrorCode errCode = CheckPermission();
122 if (errCode != I18nErrorCode::SUCCESS) {
123 HILOG_ERROR_I18N("I18nServiceAbility::Set24HourClock: Check permission failed.");
124 code = static_cast<int32_t>(errCode);
125 FinishTask(pid);
126 return ERR_OK;
127 }
128 #ifdef SUPPORT_MULTI_USER
129 int32_t userId = GetCallingUserId();
130 errCode = LocaleConfig::Set24HourClock(flag, userId);
131 #else
132 errCode = LocaleConfig::Set24HourClock(flag);
133 #endif
134 code = static_cast<int32_t>(errCode);
135 FinishTask(pid);
136 return ERR_OK;
137 }
138
SetUsingLocalDigit(bool flag,int32_t & code)139 ErrCode I18nServiceAbility::SetUsingLocalDigit(bool flag, int32_t& code)
140 {
141 int pid = getpid();
142 StartTask(pid);
143 I18nErrorCode errCode = CheckPermission();
144 if (errCode != I18nErrorCode::SUCCESS) {
145 HILOG_ERROR_I18N("I18nServiceAbility::SetUsingLocalDigit: Check permission failed.");
146 code = static_cast<int32_t>(errCode);
147 FinishTask(pid);
148 return ERR_OK;
149 }
150 #ifdef SUPPORT_MULTI_USER
151 int32_t userId = GetCallingUserId();
152 errCode = LocaleConfig::SetUsingLocalDigit(flag, userId);
153 #else
154 errCode = LocaleConfig::SetUsingLocalDigit(flag);
155 #endif
156 code = static_cast<int32_t>(errCode);
157 FinishTask(pid);
158 return ERR_OK;
159 }
160
AddPreferredLanguage(const std::string & language,int32_t index,int32_t & code)161 ErrCode I18nServiceAbility::AddPreferredLanguage(const std::string& language, int32_t index, int32_t& code)
162 {
163 int pid = getpid();
164 StartTask(pid);
165 I18nErrorCode errCode = CheckPermission();
166 if (errCode != I18nErrorCode::SUCCESS) {
167 HILOG_ERROR_I18N("I18nServiceAbility::AddPreferredLanguage: Check permission failed.");
168 code = static_cast<int32_t>(errCode);
169 FinishTask(pid);
170 return ERR_OK;
171 }
172 errCode = PreferredLanguage::AddPreferredLanguage(language, index);
173 code = static_cast<int32_t>(errCode);
174 FinishTask(pid);
175 return ERR_OK;
176 }
177
RemovePreferredLanguage(int32_t index,int32_t & code)178 ErrCode I18nServiceAbility::RemovePreferredLanguage(int32_t index, int32_t& code)
179 {
180 int pid = getpid();
181 StartTask(pid);
182 I18nErrorCode errCode = CheckPermission();
183 if (errCode != I18nErrorCode::SUCCESS) {
184 HILOG_ERROR_I18N("I18nServiceAbility::RemovePreferredLanguage: Check permission failed.");
185 code = static_cast<int32_t>(errCode);
186 FinishTask(pid);
187 return ERR_OK;
188 }
189 errCode = PreferredLanguage::RemovePreferredLanguage(index);
190 code = static_cast<int32_t>(errCode);
191 FinishTask(pid);
192 return ERR_OK;
193 }
194
SetTemperatureType(int32_t type,int32_t & code)195 ErrCode I18nServiceAbility::SetTemperatureType(int32_t type, int32_t& code)
196 {
197 int pid = getpid();
198 StartTask(pid);
199 I18nErrorCode errCode = CheckPermission();
200 if (errCode != I18nErrorCode::SUCCESS) {
201 HILOG_ERROR_I18N("I18nServiceAbility::SetTemperatureType: Check permission failed.");
202 code = static_cast<int32_t>(errCode);
203 FinishTask(pid);
204 return ERR_OK;
205 }
206 TemperatureType temperatureType = static_cast<TemperatureType>(type);
207 #ifdef SUPPORT_MULTI_USER
208 int32_t userId = GetCallingUserId();
209 errCode = LocaleConfig::SetTemperatureType(temperatureType, userId);
210 #else
211 errCode = LocaleConfig::SetTemperatureType(temperatureType);
212 #endif
213 code = static_cast<int32_t>(errCode);
214 FinishTask(pid);
215 return ERR_OK;
216 }
217
SetFirstDayOfWeek(int32_t type,int32_t & code)218 ErrCode I18nServiceAbility::SetFirstDayOfWeek(int32_t type, int32_t& code)
219 {
220 int pid = getpid();
221 StartTask(pid);
222 I18nErrorCode errCode = CheckPermission();
223 if (errCode != I18nErrorCode::SUCCESS) {
224 HILOG_ERROR_I18N("I18nServiceAbility::SetFirstDayOfWeek: Check permission failed.");
225 code = static_cast<int32_t>(errCode);
226 FinishTask(pid);
227 return ERR_OK;
228 }
229 WeekDay weekDay = static_cast<WeekDay>(type);
230 #ifdef SUPPORT_MULTI_USER
231 int32_t userId = GetCallingUserId();
232 errCode = LocaleConfig::SetFirstDayOfWeek(weekDay, userId);
233 #else
234 errCode = LocaleConfig::SetFirstDayOfWeek(weekDay);
235 #endif
236 code = static_cast<int32_t>(errCode);
237 FinishTask(pid);
238 return ERR_OK;
239 }
240
DelayUnloadI18nServiceAbility()241 void I18nServiceAbility::DelayUnloadI18nServiceAbility()
242 {
243 if (handler != nullptr) {
244 handler->RemoveTask(UNLOAD_TASK);
245 }
246 auto task = [this]() {
247 auto i18nSaLoadManager = DelayedSingleton<I18nServiceAbilityLoadManager>::GetInstance();
248 if (i18nSaLoadManager != nullptr) {
249 HILOG_INFO_I18N("I18nServiceAbility::UnloadI18nServiceAbility start to unload i18n sa.");
250 i18nSaLoadManager->UnloadI18nService(I18N_SA_ID);
251 }
252 };
253 if (handler != nullptr) {
254 handler->PostTask(task, UNLOAD_TASK, DELAY_MILLISECONDS_FOR_UNLOAD_SA);
255 }
256 }
257
OnStart(const SystemAbilityOnDemandReason & startReason)258 void I18nServiceAbility::OnStart(const SystemAbilityOnDemandReason& startReason)
259 {
260 HILOG_INFO_I18N("I18nServiceAbility start.");
261 i18nServiceEvent = std::make_unique<I18nServiceEvent>();
262 if (i18nServiceEvent != nullptr) {
263 i18nServiceEvent->SubscriberEvent();
264 i18nServiceEvent->CheckStartReason(startReason);
265 }
266 #ifdef SUPPORT_MULTI_USER
267 MultiUsers::InitMultiUser();
268 #endif
269 bool status = Publish(this);
270 if (status) {
271 HILOG_INFO_I18N("I18nServiceAbility Publish success.");
272 } else {
273 HILOG_INFO_I18N("I18nServiceAbility Publish failed.");
274 }
275 handler = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::Create(true));
276 DelayUnloadI18nServiceAbility();
277 int pid = getpid();
278 Memory::MemMgrClient::GetInstance().NotifyProcessStatus(pid, 1, 1, I18N_SA_ID);
279 }
280
OnStop()281 void I18nServiceAbility::OnStop()
282 {
283 int pid = getpid();
284 Memory::MemMgrClient::GetInstance().NotifyProcessStatus(pid, 1, 0, I18N_SA_ID);
285 HILOG_INFO_I18N("I18nServiceAbility Stop.");
286 }
287
OnIdle(const SystemAbilityOnDemandReason & idleReason)288 int32_t I18nServiceAbility::OnIdle(const SystemAbilityOnDemandReason& idleReason)
289 {
290 if (UpdateTaskNumber(ModifyTaskNumber::QUERY) == 0) {
291 HILOG_INFO_I18N("I18nServiceAbility::OnIdle: Immediately unload.");
292 return 0;
293 }
294 HILOG_INFO_I18N("I18nServiceAbility::OnIdle: Delay unload.");
295 return DELAY_MILLISECONDS_FOR_UNLOAD_SA;
296 }
297
UpdateTaskNumber(ModifyTaskNumber action)298 int32_t I18nServiceAbility::UpdateTaskNumber(ModifyTaskNumber action)
299 {
300 std::lock_guard<std::mutex> taskLock(taskNumberMutex);
301 taskNumber += static_cast<int32_t>(action);
302 return taskNumber;
303 }
304
StartTask(int32_t pid)305 void I18nServiceAbility::StartTask(int32_t pid)
306 {
307 if (Memory::MemMgrClient::GetInstance().SetCritical(pid, true, I18N_SA_ID) != 0) {
308 HILOG_ERROR_I18N("I18nServiceAbility::StartTask: Set critical true failed.");
309 }
310 UpdateTaskNumber(ModifyTaskNumber::INCREASE);
311 DelayUnloadI18nServiceAbility();
312 }
313
FinishTask(int32_t pid)314 void I18nServiceAbility::FinishTask(int32_t pid)
315 {
316 if (Memory::MemMgrClient::GetInstance().SetCritical(pid, false, I18N_SA_ID) != 0) {
317 HILOG_ERROR_I18N("I18nServiceAbility::StartTask: Set critical true failed.");
318 }
319 UpdateTaskNumber(ModifyTaskNumber::DECREASE);
320 }
321
GetCallingUserId()322 int32_t I18nServiceAbility::GetCallingUserId()
323 {
324 int32_t userId = OHOS::IPCSkeleton::GetCallingUid() / UID_TRANSFORM_DIVISOR;
325 if (userId == 0) {
326 auto err = OHOS::AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(userId);
327 if (err != 0) {
328 HILOG_ERROR_I18N("I18nServiceAbility::GetCallingUserId: GetForegroundOsAccountLocalId failed.");
329 userId = USER_DEFAULT;
330 }
331 }
332 return userId;
333 }
334
335 /**
336 * check whether request process has correct tokenType and permission.
337 */
CheckPermission()338 I18nErrorCode I18nServiceAbility::CheckPermission()
339 {
340 uint64_t callerFullToken = IPCSkeleton::GetCallingFullTokenID();
341 uint32_t callerToken = IPCSkeleton::GetCallingTokenID();
342 bool isSystemApp = Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(callerFullToken);
343 Security::AccessToken::ATokenTypeEnum tokenType =
344 Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken);
345 bool isShell = tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL;
346 bool isNative = tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE;
347 if (!isSystemApp && !isShell && !isNative) {
348 HILOG_ERROR_I18N("I18nServiceAbility caller process is not System app, Shell or Native.");
349 return I18nErrorCode::NOT_SYSTEM_APP;
350 }
351 int result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken,
352 "ohos.permission.UPDATE_CONFIGURATION");
353 if (result != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
354 HILOG_ERROR_I18N("I18nServiceAbility caller process doesn't have UPDATE_CONFIGURATION permission.");
355 return I18nErrorCode::NO_PERMISSION;
356 }
357 return I18nErrorCode::SUCCESS;
358 }
359 } // namespace I18n
360 } // namespace Global
361 } // namespace OHOS