• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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