• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2  * Copyright (C) 2021 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 "input_method_system_ability.h"
17 
18 #include <unistd.h>
19 #include <algorithm>
20 
21 #include "ability_connect_callback_proxy.h"
22 #include "ability_manager_errors.h"
23 #include "ability_manager_interface.h"
24 #include "application_info.h"
25 #include "combination_key.h"
26 #include "common_event_support.h"
27 #include "errors.h"
28 #include "full_ime_info_manager.h"
29 #include "global.h"
30 #include "im_common_event_manager.h"
31 #include "ime_cfg_manager.h"
32 #include "ime_info_inquirer.h"
33 #include "input_client_info.h"
34 #include "input_method_utils.h"
35 #include "input_type_manager.h"
36 #include "ipc_skeleton.h"
37 #include "iservice_registry.h"
38 #include "itypes_util.h"
39 #include "key_event.h"
40 #include "mem_mgr_client.h"
41 #include "message_handler.h"
42 #include "native_token_info.h"
43 #include "os_account_adapter.h"
44 #include "scene_board_judgement.h"
45 #include "system_ability_definition.h"
46 #ifdef IMF_SCREENLOCK_MGR_ENABLE
47 #include "screenlock_manager.h"
48 #endif
49 #include "system_language_observer.h"
50 #include "user_session_manager.h"
51 #include "wms_connection_observer.h"
52 
53 namespace OHOS {
54 namespace MiscServices {
55 using namespace MessageID;
56 using namespace AppExecFwk;
57 using namespace Security::AccessToken;
58 REGISTER_SYSTEM_ABILITY_BY_ID(InputMethodSystemAbility, INPUT_METHOD_SYSTEM_ABILITY_ID, true);
59 constexpr std::int32_t INIT_INTERVAL = 10000L;
60 constexpr const char *UNDEFINED = "undefined";
61 static const std::string PERMISSION_CONNECT_IME_ABILITY = "ohos.permission.CONNECT_IME_ABILITY";
62 std::shared_ptr<AppExecFwk::EventHandler> InputMethodSystemAbility::serviceHandler_;
63 
InputMethodSystemAbility(int32_t systemAbilityId,bool runOnCreate)64 InputMethodSystemAbility::InputMethodSystemAbility(int32_t systemAbilityId, bool runOnCreate)
65     : SystemAbility(systemAbilityId, runOnCreate), state_(ServiceRunningState::STATE_NOT_START)
66 {
67 }
68 
InputMethodSystemAbility()69 InputMethodSystemAbility::InputMethodSystemAbility() : state_(ServiceRunningState::STATE_NOT_START)
70 {
71 }
72 
~InputMethodSystemAbility()73 InputMethodSystemAbility::~InputMethodSystemAbility()
74 {
75     stop_ = true;
76     Message *msg = new Message(MessageID::MSG_ID_QUIT_WORKER_THREAD, nullptr);
77     MessageHandler::Instance()->SendMessage(msg);
78     if (workThreadHandler.joinable()) {
79         workThreadHandler.join();
80     }
81 }
82 
OnStart()83 void InputMethodSystemAbility::OnStart()
84 {
85     IMSA_HILOGI("InputMethodSystemAbility::OnStart start.");
86     if (!InputMethodSysEvent::GetInstance().StartTimerForReport()) {
87         IMSA_HILOGE("start sysevent timer failed!");
88     }
89     if (state_ == ServiceRunningState::STATE_RUNNING) {
90         IMSA_HILOGI("imsa service is already running.");
91         return;
92     }
93     InitServiceHandler();
94     Initialize();
95     int32_t ret = Init();
96     if (ret != ErrorCode::NO_ERROR) {
97         InputMethodSysEvent::GetInstance().ServiceFaultReporter("imf", ret);
98         auto callback = [=]() { Init(); };
99         serviceHandler_->PostTask(callback, INIT_INTERVAL);
100         IMSA_HILOGE("init failed. try again 10s later!");
101     }
102     InitHiTrace();
103     InputMethodSyncTrace tracer("InputMethodController Attach trace.");
104     InputmethodDump::GetInstance().AddDumpAllMethod([this](int fd) { this->DumpAllMethod(fd); });
105     IMSA_HILOGI("start imsa service success.");
106     return;
107 }
108 
IsValidBundleName(const std::string & bundleName)109 bool InputMethodSystemAbility::IsValidBundleName(const std::string &bundleName)
110 {
111     if (bundleName.empty()) {
112         IMSA_HILOGE("bundleName is empty.");
113         return false;
114     }
115     std::vector<Property> props;
116     auto ret = ListInputMethod(InputMethodStatus::ALL, props);
117     if (ret != ErrorCode::NO_ERROR) {
118         IMSA_HILOGE("ListInputMethod failed, ret=%{public}d", ret);
119         return false;
120     }
121 
122     for (auto &prop : props) {
123         if (prop.name == bundleName) {
124             return true;
125         }
126     }
127     return false;
128 }
129 
GetRestoreBundleName(MessageParcel & data)130 std::string InputMethodSystemAbility::GetRestoreBundleName(MessageParcel &data)
131 {
132     std::string jsonString = data.ReadString();
133     if (jsonString.empty()) {
134         IMSA_HILOGE("jsonString is empty.");
135         return "";
136     }
137     IMSA_HILOGI("restore jsonString=%{public}s", jsonString.c_str());
138 
139     cJSON *root = cJSON_Parse(jsonString.c_str());
140     if (root == NULL) {
141         IMSA_HILOGE("cJSON_Parse fail");
142         return "";
143     }
144     std::string bundleName = "";
145     cJSON *item = NULL;
146     cJSON_ArrayForEach(item, root)
147     {
148         cJSON *type = cJSON_GetObjectItem(item, "type");
149         cJSON *detail = cJSON_GetObjectItem(item, "detail");
150         if (type == NULL || detail == NULL) {
151             IMSA_HILOGE("type or detail is null");
152             continue;
153         }
154 
155         if (strcmp(type->valuestring, "default_input_method") == 0) {
156             bundleName = std::string(detail->valuestring);
157             break;
158         }
159     }
160     cJSON_Delete(root);
161     return bundleName;
162 }
163 
RestoreInputmethod(std::string & bundleName)164 int32_t InputMethodSystemAbility::RestoreInputmethod(std::string &bundleName)
165 {
166     std::shared_ptr<Property> prop = GetCurrentInputMethod();
167     if (prop == nullptr) {
168         IMSA_HILOGE("GetCurrentInputMethod failed");
169         return ErrorCode::ERROR_NULL_POINTER;
170     }
171     std::string currentInputMethod = prop->name;
172     if (currentInputMethod == bundleName) {
173         IMSA_HILOGW("currentInputMethod=%{public}s, has been set", currentInputMethod.c_str());
174         return ErrorCode::NO_ERROR;
175     }
176 
177     int32_t userId = GetCallingUserId();
178     bool result = SettingsDataUtils::GetInstance()->EnableIme(userId, bundleName);
179     if (!result) {
180         IMSA_HILOGE("EnableIme failed");
181         return ErrorCode::ERROR_ENABLE_IME;
182     }
183 
184     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
185     if (session == nullptr) {
186         IMSA_HILOGE("session[ userId=%{public}d ] is nullptr", userId);
187         return ErrorCode::ERROR_NULL_POINTER;
188     }
189     SwitchInfo switchInfo = { std::chrono::system_clock::now(), bundleName, "" };
190     switchInfo.timestamp = std::chrono::system_clock::now();
191     session->GetSwitchQueue().Push(switchInfo);
192     auto ret = OnSwitchInputMethod(userId, switchInfo, SwitchTrigger::IMSA);
193     if (ret != ErrorCode::NO_ERROR) {
194         IMSA_HILOGE("SwitchInputMethod failed, ret=%{public}d.", ret);
195         return ret;
196     }
197     IMSA_HILOGI("restore success");
198     return ErrorCode::NO_ERROR;
199 }
200 
OnExtension(const std::string & extension,MessageParcel & data,MessageParcel & reply)201 int32_t InputMethodSystemAbility::OnExtension(const std::string &extension, MessageParcel &data, MessageParcel &reply)
202 {
203     IMSA_HILOGI("extension=%{public}s", extension.c_str());
204     if (extension == "restore") {
205         (void)data.ReadFileDescriptor();
206         std::string bundleName = GetRestoreBundleName(data);
207         if (!IsValidBundleName(bundleName)) {
208             IMSA_HILOGE("bundleName=%{public}s is invalid", bundleName.c_str());
209             return ErrorCode::ERROR_BAD_PARAMETERS;
210         }
211 
212         return RestoreInputmethod(bundleName);
213     }
214     return 0;
215 }
216 
Dump(int fd,const std::vector<std::u16string> & args)217 int InputMethodSystemAbility::Dump(int fd, const std::vector<std::u16string> &args)
218 {
219     IMSA_HILOGD("InputMethodSystemAbility::Dump start.");
220     std::vector<std::string> argsStr;
221     for (auto item : args) {
222         argsStr.emplace_back(Str16ToStr8(item));
223     }
224     InputmethodDump::GetInstance().Dump(fd, argsStr);
225     return ERR_OK;
226 }
227 
DumpAllMethod(int fd)228 void InputMethodSystemAbility::DumpAllMethod(int fd)
229 {
230     IMSA_HILOGD("InputMethodSystemAbility::DumpAllMethod start.");
231     auto ids = OsAccountAdapter::QueryActiveOsAccountIds();
232     if (ids.empty()) {
233         dprintf(fd, "\n - InputMethodSystemAbility::DumpAllMethod get Active Id failed.\n");
234         return;
235     }
236     dprintf(fd, "\n - DumpAllMethod get Active Id succeed,count=%zu,", ids.size());
237     for (auto id : ids) {
238         const auto &params = ImeInfoInquirer::GetInstance().GetDumpInfo(id);
239         if (params.empty()) {
240             IMSA_HILOGD("userId: %{public}d the IME properties is empty.", id);
241             dprintf(fd, "\n - The IME properties about the Active Id %d is empty.\n", id);
242             continue;
243         }
244         dprintf(fd, "\n - The Active Id:%d get input method:\n%s\n", id, params.c_str());
245     }
246     IMSA_HILOGD("InputMethodSystemAbility::DumpAllMethod end.");
247 }
248 
Init()249 int32_t InputMethodSystemAbility::Init()
250 {
251     bool isSuccess = Publish(this);
252     if (!isSuccess) {
253         return -1;
254     }
255     state_ = ServiceRunningState::STATE_RUNNING;
256     ImeCfgManager::GetInstance().Init();
257     ImeInfoInquirer::GetInstance().InitSystemConfig();
258     InitMonitors();
259     return ErrorCode::NO_ERROR;
260 }
261 
UpdateUserInfo(int32_t userId)262 void InputMethodSystemAbility::UpdateUserInfo(int32_t userId)
263 {
264     IMSA_HILOGI("%{public}d switch to %{public}d.", userId_, userId);
265     userId_ = userId;
266     UserSessionManager::GetInstance().AddUserSession(userId_);
267     InputMethodSysEvent::GetInstance().SetUserId(userId_);
268     if (enableImeOn_.load()) {
269         EnableImeDataParser::GetInstance()->OnUserChanged(userId_);
270     }
271     if (enableSecurityMode_.load()) {
272         SecurityModeParser::GetInstance()->UpdateFullModeList(userId_);
273     }
274     UpdateUserLockState();
275 }
276 
UpdateUserLockState()277 void InputMethodSystemAbility::UpdateUserLockState()
278 {
279     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
280     if (session == nullptr) {
281         UserSessionManager::GetInstance().AddUserSession(userId_);
282     }
283     session = UserSessionManager::GetInstance().GetUserSession(userId_);
284     if (session == nullptr) {
285         IMSA_HILOGE("%{public}d session is nullptr!", userId_);
286         return;
287     }
288     session->UpdateUserLockState();
289 }
290 
OnStop()291 void InputMethodSystemAbility::OnStop()
292 {
293     IMSA_HILOGI("OnStop start.");
294     FreezeManager::SetEventHandler(nullptr);
295     serviceHandler_ = nullptr;
296     state_ = ServiceRunningState::STATE_NOT_START;
297     Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 0, INPUT_METHOD_SYSTEM_ABILITY_ID);
298 }
299 
InitServiceHandler()300 void InputMethodSystemAbility::InitServiceHandler()
301 {
302     IMSA_HILOGI("InitServiceHandler start.");
303     if (serviceHandler_ != nullptr) {
304         IMSA_HILOGE("InputMethodSystemAbility already init.");
305         return;
306     }
307     std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("OS_InputMethodSystemAbility");
308     serviceHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
309     FreezeManager::SetEventHandler(serviceHandler_);
310 
311     IMSA_HILOGI("InitServiceHandler succeeded.");
312 }
313 
314 /**
315  * Initialization of Input method management service
316  * \n It's called after the service starts, before any transaction.
317  */
Initialize()318 void InputMethodSystemAbility::Initialize()
319 {
320     IMSA_HILOGI("InputMethodSystemAbility::Initialize.");
321     // init work thread to handle the messages
322     workThreadHandler = std::thread([this] { this->WorkThread(); });
323     identityChecker_ = std::make_shared<IdentityCheckerImpl>();
324     userId_ = OsAccountAdapter::MAIN_USER_ID;
325     UserSessionManager::GetInstance().SetEventHandler(serviceHandler_);
326     UserSessionManager::GetInstance().AddUserSession(userId_);
327     InputMethodSysEvent::GetInstance().SetUserId(userId_);
328     isScbEnable_.store(Rosen::SceneBoardJudgement::IsSceneBoardEnabled());
329 }
330 
SubscribeCommonEvent()331 void InputMethodSystemAbility::SubscribeCommonEvent()
332 {
333     sptr<ImCommonEventManager> imCommonEventManager = ImCommonEventManager::GetInstance();
334     bool isSuccess = imCommonEventManager->SubscribeEvent();
335     if (isSuccess) {
336         IMSA_HILOGI("initialize subscribe service event success.");
337         return;
338     }
339 
340     IMSA_HILOGE("failed, try again 10s later");
341     auto callback = [this]() { SubscribeCommonEvent(); };
342     serviceHandler_->PostTask(callback, INIT_INTERVAL);
343 }
344 
PrepareInput(int32_t userId,InputClientInfo & clientInfo)345 int32_t InputMethodSystemAbility::PrepareInput(int32_t userId, InputClientInfo &clientInfo)
346 {
347     auto ret = GenerateClientInfo(userId, clientInfo);
348     if (ret != ErrorCode::NO_ERROR) {
349         return ret;
350     }
351     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
352     if (session == nullptr) {
353         IMSA_HILOGE("%{public}d session is nullptr", userId);
354         return ErrorCode::ERROR_NULL_POINTER;
355     }
356     return session->OnPrepareInput(clientInfo);
357 }
358 
GenerateClientInfo(int32_t userId,InputClientInfo & clientInfo)359 int32_t InputMethodSystemAbility::GenerateClientInfo(int32_t userId, InputClientInfo &clientInfo)
360 {
361     if (clientInfo.client == nullptr || clientInfo.channel == nullptr) {
362         IMSA_HILOGE("client or channel is nullptr!");
363         return ErrorCode::ERROR_NULL_POINTER;
364     }
365     auto deathRecipient = new (std::nothrow) InputDeathRecipient();
366     if (deathRecipient == nullptr) {
367         IMSA_HILOGE("failed to new deathRecipient!");
368         return ErrorCode::ERROR_EX_NULL_POINTER;
369     }
370     clientInfo.pid = IPCSkeleton::GetCallingPid();
371     clientInfo.uid = IPCSkeleton::GetCallingUid();
372     clientInfo.userID = userId;
373     clientInfo.deathRecipient = deathRecipient;
374     auto tokenId = IPCSkeleton::GetCallingTokenID();
375     if (identityChecker_->IsFocusedUIExtension(tokenId)) {
376         clientInfo.uiExtensionTokenId = tokenId;
377     }
378     return ErrorCode::NO_ERROR;
379 }
380 
ReleaseInput(sptr<IInputClient> client)381 int32_t InputMethodSystemAbility::ReleaseInput(sptr<IInputClient> client)
382 {
383     if (client == nullptr) {
384         IMSA_HILOGE("client is nullptr!");
385         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
386     }
387     auto userId = GetCallingUserId();
388     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
389     if (session == nullptr) {
390         IMSA_HILOGE("%{public}d session is nullptr", userId);
391         return ErrorCode::ERROR_NULL_POINTER;
392     }
393     return session->OnReleaseInput(client);
394 }
395 
StartInput(InputClientInfo & inputClientInfo,sptr<IRemoteObject> & agent)396 int32_t InputMethodSystemAbility::StartInput(InputClientInfo &inputClientInfo, sptr<IRemoteObject> &agent)
397 {
398     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
399     if (!identityChecker_->IsBroker(tokenId) && !identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)) {
400         return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
401     }
402     auto userId = GetCallingUserId();
403     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
404     if (session == nullptr) {
405         IMSA_HILOGE("%{public}d session is nullptr", userId);
406         return ErrorCode::ERROR_NULL_POINTER;
407     }
408     if (session->GetCurrentClientPid() != IPCSkeleton::GetCallingPid()
409         && session->GetInactiveClientPid() != IPCSkeleton::GetCallingPid()) {
410         // notify inputStart when caller pid different from both current client and inactive client
411         inputClientInfo.isNotifyInputStart = true;
412     }
413     if (session->CheckPwdInputPatternConv(inputClientInfo)) {
414         inputClientInfo.needHide = true;
415         inputClientInfo.isNotifyInputStart = true;
416     }
417     if (!session->IsProxyImeEnable()) {
418         auto ret = CheckInputTypeOption(userId, inputClientInfo);
419         if (ret != ErrorCode::NO_ERROR) {
420             IMSA_HILOGE("%{public}d failed to CheckInputTypeOption.", userId);
421             return ret;
422         }
423     }
424     inputClientInfo.config.inputAttribute.bundleName = identityChecker_->GetBundleNameByToken(tokenId);
425     int32_t ret = PrepareInput(userId, inputClientInfo);
426     if (ret != ErrorCode::NO_ERROR) {
427         IMSA_HILOGE("failed to PrepareInput");
428         return ret;
429     }
430     return session->OnStartInput(inputClientInfo, agent);
431 }
432 
CheckInputTypeOption(int32_t userId,InputClientInfo & inputClientInfo)433 int32_t InputMethodSystemAbility::CheckInputTypeOption(int32_t userId, InputClientInfo &inputClientInfo)
434 {
435     IMSA_HILOGI("SecurityFlag: %{public}d, IsSameTextInput: %{public}d, IsStarted: %{public}d, "
436                 "IsSecurityImeStarted: %{public}d.",
437         inputClientInfo.config.inputAttribute.GetSecurityFlag(), !inputClientInfo.isNotifyInputStart,
438         InputTypeManager::GetInstance().IsStarted(), InputTypeManager::GetInstance().IsSecurityImeStarted());
439     if (inputClientInfo.config.inputAttribute.GetSecurityFlag()) {
440         if (!InputTypeManager::GetInstance().IsStarted()) {
441             IMSA_HILOGD("SecurityFlag, input type is not started, start.");
442             // if need to switch ime, no need to hide panel first.
443             NeedHideWhenSwitchInputType(userId, inputClientInfo.needHide);
444             return StartInputType(userId, InputType::SECURITY_INPUT);
445         }
446         if (!inputClientInfo.isNotifyInputStart) {
447             IMSA_HILOGD("SecurityFlag, same textField, input type is started, not deal.");
448             return ErrorCode::NO_ERROR;
449         }
450         if (!InputTypeManager::GetInstance().IsSecurityImeStarted()) {
451             IMSA_HILOGD("SecurityFlag, new textField, input type is started, but it is not security, switch.");
452             NeedHideWhenSwitchInputType(userId, inputClientInfo.needHide);
453             return StartInputType(userId, InputType::SECURITY_INPUT);
454         }
455         IMSA_HILOGD("SecurityFlag, other condition, not deal.");
456         return ErrorCode::NO_ERROR;
457     }
458     if (!inputClientInfo.isNotifyInputStart) {
459         IMSA_HILOGD("NormalFlag, same textField, not deal.");
460         return ErrorCode::NO_ERROR;
461     }
462     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
463     if (session == nullptr) {
464         IMSA_HILOGE("%{public}d session is nullptr", userId);
465         return ErrorCode::ERROR_NULL_POINTER;
466     }
467     if (InputTypeManager::GetInstance().IsStarted()) {
468         IMSA_HILOGD("NormalFlag, diff textField, input type started, restore.");
469         session->RestoreCurrentImeSubType();
470     }
471     return session->RestoreCurrentIme();
472 }
473 
ShowInput(sptr<IInputClient> client,int32_t requestKeyboardReason)474 int32_t InputMethodSystemAbility::ShowInput(sptr<IInputClient> client, int32_t requestKeyboardReason)
475 {
476     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
477     auto userId = GetCallingUserId();
478     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
479     if (session == nullptr) {
480         IMSA_HILOGE("%{public}d session is nullptr", userId);
481         return ErrorCode::ERROR_NULL_POINTER;
482     }
483     if (!identityChecker_->IsBroker(tokenId)) {
484         if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
485             return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
486         }
487     }
488     if (client == nullptr) {
489         IMSA_HILOGE("client is nullptr");
490         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
491     }
492     return session->OnShowInput(client, requestKeyboardReason);
493 }
494 
HideInput(sptr<IInputClient> client)495 int32_t InputMethodSystemAbility::HideInput(sptr<IInputClient> client)
496 {
497     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
498     auto userId = GetCallingUserId();
499     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
500     if (session == nullptr) {
501         IMSA_HILOGE("%{public}d session is nullptr", userId);
502         return ErrorCode::ERROR_NULL_POINTER;
503     }
504     if (!identityChecker_->IsBroker(tokenId)) {
505         if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
506             return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
507         }
508     }
509     if (client == nullptr) {
510         IMSA_HILOGE("client is nullptr");
511         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
512     }
513     return session->OnHideInput(client);
514 }
515 
StopInputSession()516 int32_t InputMethodSystemAbility::StopInputSession()
517 {
518     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
519     auto userId = GetCallingUserId();
520     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
521     if (session == nullptr) {
522         IMSA_HILOGE("%{public}d session is nullptr", userId);
523         return ErrorCode::ERROR_NULL_POINTER;
524     }
525     if (!identityChecker_->IsBroker(tokenId)) {
526         if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
527             return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
528         }
529     }
530     return session->OnHideCurrentInput();
531 }
532 
RequestShowInput()533 int32_t InputMethodSystemAbility::RequestShowInput()
534 {
535     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
536     if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)
537         && !identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
538         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
539     }
540     auto userId = GetCallingUserId();
541     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
542     if (session == nullptr) {
543         IMSA_HILOGE("%{public}d session is nullptr", userId);
544         return ErrorCode::ERROR_NULL_POINTER;
545     }
546     return session->OnRequestShowInput();
547 }
548 
RequestHideInput()549 int32_t InputMethodSystemAbility::RequestHideInput()
550 {
551     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
552     if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)
553         && !identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
554         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
555     }
556     auto userId = GetCallingUserId();
557     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
558     if (session == nullptr) {
559         IMSA_HILOGE("%{public}d session is nullptr", userId);
560         return ErrorCode::ERROR_NULL_POINTER;
561     }
562     return session->OnRequestHideInput();
563 }
564 
SetCoreAndAgent(const sptr<IInputMethodCore> & core,const sptr<IRemoteObject> & agent)565 int32_t InputMethodSystemAbility::SetCoreAndAgent(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
566 {
567     IMSA_HILOGD("InputMethodSystemAbility start.");
568     auto userId = GetCallingUserId();
569     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
570     if (session == nullptr) {
571         IMSA_HILOGE("%{public}d session is nullptr", userId);
572         return ErrorCode::ERROR_NULL_POINTER;
573     }
574     if (identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
575         return session->OnRegisterProxyIme(core, agent);
576     }
577     if (!IsCurrentIme(userId)) {
578         IMSA_HILOGE("not current ime, userId:%{public}d", userId);
579         return ErrorCode::ERROR_NOT_CURRENT_IME;
580     }
581     return session->OnSetCoreAndAgent(core, agent);
582 }
583 
InitConnect()584 int32_t InputMethodSystemAbility::InitConnect()
585 {
586     IMSA_HILOGD("InputMethodSystemAbility init connect.");
587     auto userId = GetCallingUserId();
588     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
589     if (session == nullptr) {
590         IMSA_HILOGE("%{public}d session is nullptr", userId);
591         return ErrorCode::ERROR_NULL_POINTER;
592     }
593     if (!IsCurrentIme(userId)) {
594         return ErrorCode::ERROR_NOT_CURRENT_IME;
595     }
596     return session->InitConnect(IPCSkeleton::GetCallingPid());
597 }
598 
HideCurrentInput()599 int32_t InputMethodSystemAbility::HideCurrentInput()
600 {
601     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
602     auto userId = GetCallingUserId();
603     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
604     if (session == nullptr) {
605         IMSA_HILOGE("%{public}d session is nullptr", userId);
606         return ErrorCode::ERROR_NULL_POINTER;
607     }
608     if (identityChecker_->IsBroker(tokenId)) {
609         return session->OnHideCurrentInput();
610     }
611     if (!identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
612         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
613     }
614     return session->OnHideCurrentInput();
615 }
616 
ShowCurrentInput()617 int32_t InputMethodSystemAbility::ShowCurrentInput()
618 {
619     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
620     auto userId = GetCallingUserId();
621     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
622     if (session == nullptr) {
623         IMSA_HILOGE("%{public}d session is nullptr", userId);
624         return ErrorCode::ERROR_NULL_POINTER;
625     }
626     if (identityChecker_->IsBroker(tokenId)) {
627         return session->OnShowCurrentInput();
628     }
629     if (!identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
630         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
631     }
632     return session->OnShowCurrentInput();
633 }
634 
PanelStatusChange(const InputWindowStatus & status,const ImeWindowInfo & info)635 int32_t InputMethodSystemAbility::PanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info)
636 {
637     auto userId = GetCallingUserId();
638     if (!IsCurrentIme(userId)) {
639         IMSA_HILOGE("not current ime!");
640         return ErrorCode::ERROR_NOT_CURRENT_IME;
641     }
642     auto commonEventManager = ImCommonEventManager::GetInstance();
643     if (commonEventManager != nullptr) {
644         auto ret = ImCommonEventManager::GetInstance()->PublishPanelStatusChangeEvent(userId, status, info);
645         IMSA_HILOGD("public panel status change event: %{public}d", ret);
646     }
647     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
648     if (session == nullptr) {
649         IMSA_HILOGE("%{public}d session is nullptr", userId);
650         return ErrorCode::ERROR_NULL_POINTER;
651     }
652     return session->OnPanelStatusChange(status, info);
653 }
654 
UpdateListenEventFlag(InputClientInfo & clientInfo,uint32_t eventFlag)655 int32_t InputMethodSystemAbility::UpdateListenEventFlag(InputClientInfo &clientInfo, uint32_t eventFlag)
656 {
657     IMSA_HILOGI("finalEventFlag: %{public}u, eventFlag: %{public}u.", clientInfo.eventFlag, eventFlag);
658     if (EventStatusManager::IsImeHideOn(eventFlag) || EventStatusManager::IsImeShowOn(eventFlag) ||
659         EventStatusManager::IsInputStatusChangedOn(eventFlag)) {
660         if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) &&
661             !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
662             IMSA_HILOGE("not system application!");
663             return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
664         }
665     }
666     auto userId = GetCallingUserId();
667     auto ret = GenerateClientInfo(userId, clientInfo);
668     if (ret != ErrorCode::NO_ERROR) {
669         return ret;
670     }
671     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
672     if (session == nullptr) {
673         IMSA_HILOGE("%{public}d session is nullptr", userId);
674         return ErrorCode::ERROR_NULL_POINTER;
675     }
676     return session->OnUpdateListenEventFlag(clientInfo);
677 }
678 
SetCallingWindow(uint32_t windowId,sptr<IInputClient> client)679 int32_t InputMethodSystemAbility::SetCallingWindow(uint32_t windowId, sptr<IInputClient> client)
680 {
681     IMSA_HILOGD("IMF SA setCallingWindow enter");
682     auto callingUserId = GetCallingUserId();
683     auto session = UserSessionManager::GetInstance().GetUserSession(callingUserId);
684     if (session == nullptr) {
685         IMSA_HILOGE("%{public}d session is nullptr!", callingUserId);
686         return ErrorCode::ERROR_NULL_POINTER;
687     }
688     return session->OnSetCallingWindow(windowId, client);
689 }
690 
GetInputStartInfo(bool & isInputStart,uint32_t & callingWndId,int32_t & requestKeyboardReason)691 int32_t InputMethodSystemAbility::GetInputStartInfo(bool& isInputStart,
692     uint32_t& callingWndId, int32_t &requestKeyboardReason)
693 {
694     if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) &&
695         !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
696         IMSA_HILOGE("not system application!");
697         return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
698     }
699     auto callingUserId = GetCallingUserId();
700     auto session = UserSessionManager::GetInstance().GetUserSession(callingUserId);
701     if (session == nullptr) {
702         IMSA_HILOGE("%{public}d session is nullptr!", callingUserId);
703         return false;
704     }
705     return session->GetInputStartInfo(isInputStart, callingWndId, requestKeyboardReason);
706 }
707 
IsCurrentIme()708 bool InputMethodSystemAbility::IsCurrentIme()
709 {
710     return IsCurrentIme(GetCallingUserId());
711 }
712 
IsInputTypeSupported(InputType type)713 bool InputMethodSystemAbility::IsInputTypeSupported(InputType type)
714 {
715     return InputTypeManager::GetInstance().IsSupported(type);
716 }
717 
StartInputType(InputType type)718 int32_t InputMethodSystemAbility::StartInputType(InputType type)
719 {
720     return StartInputType(GetCallingUserId(), type);
721 }
722 
ExitCurrentInputType()723 int32_t InputMethodSystemAbility::ExitCurrentInputType()
724 {
725     auto userId = GetCallingUserId();
726     auto ret = IsDefaultImeFromTokenId(userId, IPCSkeleton::GetCallingTokenID());
727     if (ret != ErrorCode::NO_ERROR) {
728         IMSA_HILOGE("not default ime.");
729         return ErrorCode::ERROR_NOT_DEFAULT_IME;
730     }
731     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
732     if (session == nullptr) {
733         IMSA_HILOGE("%{public}d session is nullptr", userId);
734         return ErrorCode::ERROR_NULL_POINTER;
735     }
736     if (session->CheckSecurityMode()) {
737         return StartInputType(userId, InputType::SECURITY_INPUT);
738     }
739     auto typeIme = InputTypeManager::GetInstance().GetCurrentIme();
740     auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
741     if (cfgIme->bundleName == typeIme.bundleName) {
742         return session->RestoreCurrentImeSubType();
743     }
744     return session->RestoreCurrentIme();
745 }
746 
IsDefaultIme()747 int32_t InputMethodSystemAbility::IsDefaultIme()
748 {
749     return IsDefaultImeFromTokenId(GetCallingUserId(), IPCSkeleton::GetCallingTokenID());
750 }
751 
IsSystemApp()752 bool InputMethodSystemAbility::IsSystemApp()
753 {
754     return identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID());
755 }
756 
IsDefaultImeFromTokenId(int32_t userId,uint32_t tokenId)757 int32_t InputMethodSystemAbility::IsDefaultImeFromTokenId(int32_t userId, uint32_t tokenId)
758 {
759     auto prop = std::make_shared<Property>();
760     auto ret = ImeInfoInquirer::GetInstance().GetDefaultInputMethod(userId, prop);
761     if (ret != ErrorCode::NO_ERROR || prop == nullptr) {
762         IMSA_HILOGE("failed to get default ime!");
763         return ErrorCode::ERROR_PERSIST_CONFIG;
764     }
765     if (!identityChecker_->IsBundleNameValid(tokenId, prop->name)) {
766         return ErrorCode::ERROR_NOT_DEFAULT_IME;
767     }
768     return ErrorCode::NO_ERROR;
769 }
770 
IsCurrentImeByPid(int32_t pid)771 bool InputMethodSystemAbility::IsCurrentImeByPid(int32_t pid)
772 {
773     if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) &&
774         !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
775         IMSA_HILOGE("not system application or system ability!");
776         return false;
777     }
778     auto userId = GetCallingUserId();
779     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
780     if (session == nullptr) {
781         IMSA_HILOGE("%{public}d session is nullptr", userId);
782         return false;
783     }
784     return session->IsCurrentImeByPid(pid);
785 }
786 
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)787 int32_t InputMethodSystemAbility::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
788 {
789     if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
790         IMSA_HILOGE("not system application!");
791         return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
792     }
793     auto userId = GetCallingUserId();
794     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
795     if (session == nullptr) {
796         IMSA_HILOGE("%{public}d session is nullptr", userId);
797         return ErrorCode::ERROR_NULL_POINTER;
798     }
799     return session->IsPanelShown(panelInfo, isShown);
800 }
801 
DisplayOptionalInputMethod()802 int32_t InputMethodSystemAbility::DisplayOptionalInputMethod()
803 {
804     IMSA_HILOGD("InputMethodSystemAbility start.");
805     return OnDisplayOptionalInputMethod();
806 }
807 
SwitchInputMethod(const std::string & bundleName,const std::string & subName,SwitchTrigger trigger)808 int32_t InputMethodSystemAbility::SwitchInputMethod(
809     const std::string &bundleName, const std::string &subName, SwitchTrigger trigger)
810 {
811     // IMSA not check permission, add this verify for prevent counterfeit
812     if (trigger == SwitchTrigger::IMSA) {
813         IMSA_HILOGW("caller counterfeit!");
814         return ErrorCode::ERROR_BAD_PARAMETERS;
815     }
816     SwitchInfo switchInfo = { std::chrono::system_clock::now(), bundleName, subName };
817     int32_t userId = GetCallingUserId();
818     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
819     if (session == nullptr) {
820         IMSA_HILOGE("%{public}d session is nullptr", userId);
821         return ErrorCode::ERROR_NULL_POINTER;
822     }
823     if (enableImeOn_.load() && !EnableImeDataParser::GetInstance()->CheckNeedSwitch(switchInfo, userId)) {
824         IMSA_HILOGW("Enable mode off or switch is not enable, stopped!");
825         return ErrorCode::ERROR_ENABLE_IME;
826     }
827     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
828     if (switchInfo.subName.empty() && switchInfo.bundleName == currentImeCfg->bundleName) {
829         switchInfo.subName = currentImeCfg->subName;
830     }
831     switchInfo.timestamp = std::chrono::system_clock::now();
832     session->GetSwitchQueue().Push(switchInfo);
833     return InputTypeManager::GetInstance().IsInputType({ bundleName, subName })
834                ? OnStartInputType(userId, switchInfo, true)
835                : OnSwitchInputMethod(userId, switchInfo, trigger);
836 }
837 
EnableIme(const std::string & bundleName)838 bool InputMethodSystemAbility::EnableIme(const std::string &bundleName)
839 {
840     if (CheckEnableAndSwitchPermission() != ErrorCode::NO_ERROR) {
841         IMSA_HILOGE("Check enable ime value failed!");
842         return false;
843     }
844     int32_t userId = GetCallingUserId();
845     return SettingsDataUtils::GetInstance()->EnableIme(userId, bundleName);
846 }
847 
OnSwitchInputMethod(int32_t userId,const SwitchInfo & switchInfo,SwitchTrigger trigger)848 int32_t InputMethodSystemAbility::OnSwitchInputMethod(int32_t userId, const SwitchInfo &switchInfo,
849     SwitchTrigger trigger)
850 {
851     InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::CHANGE_IME);
852     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
853     if (session == nullptr) {
854         IMSA_HILOGE("%{public}d session is nullptr", userId);
855         return ErrorCode::ERROR_NULL_POINTER;
856     }
857     if (!session->GetSwitchQueue().IsReady(switchInfo)) {
858         IMSA_HILOGD("start wait.");
859         session->GetSwitchQueue().Wait(switchInfo);
860     }
861     IMSA_HILOGI("start switch %{public}s|%{public}s.", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
862     int32_t ret = CheckSwitchPermission(userId, switchInfo, trigger);
863     if (ret != ErrorCode::NO_ERROR) {
864         InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ErrorCode::ERROR_STATUS_PERMISSION_DENIED,
865             switchInfo.bundleName, "switch input method failed!");
866         session->GetSwitchQueue().Pop();
867         return ret;
868     }
869     auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId, switchInfo.bundleName, switchInfo.subName);
870     if (info == nullptr) {
871         session->GetSwitchQueue().Pop();
872         return ErrorCode::ERROR_BAD_PARAMETERS;
873     }
874     InputTypeManager::GetInstance().Set(false);
875     {
876         InputMethodSyncTrace tracer("InputMethodSystemAbility_OnSwitchInputMethod");
877         std::string targetImeName = info->prop.name + "/" + info->prop.id;
878         ImeCfgManager::GetInstance().ModifyImeCfg({ userId, targetImeName, info->subProp.id, true });
879         auto targetIme = std::make_shared<ImeNativeCfg>(ImeNativeCfg {
880             targetImeName, info->prop.name, switchInfo.subName.empty() ? "" : info->subProp.id, info->prop.id });
881         if (!session->StartIme(targetIme)) {
882             InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, switchInfo.bundleName,
883                 "switch input method failed!");
884             session->GetSwitchQueue().Pop();
885             return ErrorCode::ERROR_IME_START_FAILED;
886         }
887         GetValidSubtype(switchInfo.subName, info);
888         session->NotifyImeChangeToClients(info->prop, info->subProp);
889         ret = session->SwitchSubtype(info->subProp);
890     }
891     session->GetSwitchQueue().Pop();
892     ret = info->isSpecificSubName ? ret : ErrorCode::NO_ERROR;
893     if (ret != ErrorCode::NO_ERROR) {
894         InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, switchInfo.bundleName,
895             "switch input method subtype failed!");
896     }
897     return ret;
898 }
899 
GetValidSubtype(const std::string & subName,const std::shared_ptr<ImeInfo> & info)900 void InputMethodSystemAbility::GetValidSubtype(const std::string &subName, const std::shared_ptr<ImeInfo> &info)
901 {
902     if (subName.empty()) {
903         IMSA_HILOGW("undefined subtype");
904         info->subProp.id = UNDEFINED;
905         info->subProp.name = UNDEFINED;
906     }
907 }
908 
OnStartInputType(int32_t userId,const SwitchInfo & switchInfo,bool isCheckPermission)909 int32_t InputMethodSystemAbility::OnStartInputType(int32_t userId, const SwitchInfo &switchInfo,
910     bool isCheckPermission)
911 {
912     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
913     if (session == nullptr) {
914         IMSA_HILOGE("%{public}d session is nullptr", userId);
915         return ErrorCode::ERROR_NULL_POINTER;
916     }
917     if (!session->GetSwitchQueue().IsReady(switchInfo)) {
918         IMSA_HILOGD("start wait.");
919         session->GetSwitchQueue().Wait(switchInfo);
920     }
921     IMSA_HILOGD("start switch %{public}s|%{public}s.", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
922     if (isCheckPermission && !IsStartInputTypePermitted(userId)) {
923         IMSA_HILOGE("not permitted to start input type!");
924         session->GetSwitchQueue().Pop();
925         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
926     }
927     if (!IsNeedSwitch(userId, switchInfo.bundleName, switchInfo.subName)) {
928         IMSA_HILOGI("no need to switch.");
929         session->GetSwitchQueue().Pop();
930         return ErrorCode::NO_ERROR;
931     }
932     int32_t ret = SwitchInputType(userId, switchInfo);
933     session->GetSwitchQueue().Pop();
934     return ret;
935 }
936 
IsNeedSwitch(int32_t userId,const std::string & bundleName,const std::string & subName)937 bool InputMethodSystemAbility::IsNeedSwitch(int32_t userId, const std::string &bundleName,
938     const std::string &subName)
939 {
940     if (InputTypeManager::GetInstance().IsStarted()) {
941         ImeIdentification target = { bundleName, subName };
942         return !(target == InputTypeManager::GetInstance().GetCurrentIme());
943     }
944     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
945     IMSA_HILOGI("currentIme: %{public}s/%{public}s, targetIme: %{public}s/%{public}s.",
946         currentImeCfg->bundleName.c_str(), currentImeCfg->subName.c_str(), bundleName.c_str(), subName.c_str());
947     if ((subName.empty() && bundleName == currentImeCfg->bundleName) ||
948         (!subName.empty() && subName == currentImeCfg->subName && currentImeCfg->bundleName == bundleName)) {
949         IMSA_HILOGI("no need to switch");
950         return false;
951     }
952     return true;
953 }
954 
Switch(int32_t userId,const std::string & bundleName,const std::shared_ptr<ImeInfo> & info)955 int32_t InputMethodSystemAbility::Switch(int32_t userId, const std::string &bundleName,
956     const std::shared_ptr<ImeInfo> &info)
957 {
958     auto currentImeBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
959     if (bundleName != currentImeBundleName) {
960         IMSA_HILOGI("switch input method to: %{public}s", bundleName.c_str());
961         return SwitchExtension(userId, info);
962     }
963     auto currentInputType = InputTypeManager::GetInstance().GetCurrentIme();
964     auto isInputTypeStarted = InputTypeManager::GetInstance().IsStarted();
965     if (isInputTypeStarted && bundleName != currentInputType.bundleName) {
966         IMSA_HILOGI("right click on state, switch input method to: %{public}s", bundleName.c_str());
967         return SwitchExtension(userId, info);
968     }
969     return SwitchSubType(userId, info);
970 }
971 
972 // Switch the current InputMethodExtension to the new InputMethodExtension
SwitchExtension(int32_t userId,const std::shared_ptr<ImeInfo> & info)973 int32_t InputMethodSystemAbility::SwitchExtension(int32_t userId, const std::shared_ptr<ImeInfo> &info)
974 {
975     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
976     if (session == nullptr) {
977         IMSA_HILOGE("%{public}d session is nullptr", userId);
978         return ErrorCode::ERROR_NULL_POINTER;
979     }
980     std::string targetImeName = info->prop.name + "/" + info->prop.id;
981     ImeCfgManager::GetInstance().ModifyImeCfg({ userId, targetImeName, info->subProp.id, false });
982     ImeNativeCfg targetIme = { targetImeName, info->prop.name, info->subProp.id, info->prop.id };
983     if (!session->StartIme(std::make_shared<ImeNativeCfg>(targetIme))) {
984         IMSA_HILOGE("start input method failed!");
985         return ErrorCode::ERROR_IME_START_FAILED;
986     }
987     session->NotifyImeChangeToClients(info->prop, info->subProp);
988     GetValidSubtype("", info);
989     session->SwitchSubtype(info->subProp);
990     return ErrorCode::NO_ERROR;
991 }
992 
993 // Inform current InputMethodExtension to switch subtype
SwitchSubType(int32_t userId,const std::shared_ptr<ImeInfo> & info)994 int32_t InputMethodSystemAbility::SwitchSubType(int32_t userId, const std::shared_ptr<ImeInfo> &info)
995 {
996     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
997     if (session == nullptr) {
998         IMSA_HILOGE("%{public}d session is nullptr", userId);
999         return ErrorCode::ERROR_NULL_POINTER;
1000     }
1001     auto ret = session->SwitchSubtype(info->subProp);
1002     if (ret != ErrorCode::NO_ERROR) {
1003         IMSA_HILOGE("failed to inform ime to switch subtype, ret: %{public}d!", ret);
1004         return ret;
1005     }
1006     auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->imeId;
1007     ImeCfgManager::GetInstance().ModifyImeCfg({ userId, currentIme, info->subProp.id, false });
1008     session->NotifyImeChangeToClients(info->prop, info->subProp);
1009     return ErrorCode::NO_ERROR;
1010 }
1011 
SwitchInputType(int32_t userId,const SwitchInfo & switchInfo)1012 int32_t InputMethodSystemAbility::SwitchInputType(int32_t userId, const SwitchInfo &switchInfo)
1013 {
1014     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1015     if (session == nullptr) {
1016         IMSA_HILOGE("%{public}d session is nullptr", userId);
1017         return ErrorCode::ERROR_NULL_POINTER;
1018     }
1019     auto targetIme = session->GetImeNativeCfg(userId, switchInfo.bundleName, switchInfo.subName);
1020     if (targetIme == nullptr) {
1021         IMSA_HILOGE("targetIme is nullptr!");
1022         return ErrorCode::ERROR_NULL_POINTER;
1023     }
1024     if (!session->StartIme(targetIme)) {
1025         IMSA_HILOGE("start input method failed!");
1026         return ErrorCode::ERROR_IME_START_FAILED;
1027     }
1028     int32_t ret = session->SwitchSubtype({ .name = switchInfo.bundleName, .id = switchInfo.subName });
1029     if (ret != ErrorCode::NO_ERROR) {
1030         IMSA_HILOGE("switch subtype failed!");
1031         return ret;
1032     }
1033     InputTypeManager::GetInstance().Set(true, { switchInfo.bundleName, switchInfo.subName });
1034     return ErrorCode::NO_ERROR;
1035 }
1036 
1037 // Deprecated because of no permission check, kept for compatibility
HideCurrentInputDeprecated()1038 int32_t InputMethodSystemAbility::HideCurrentInputDeprecated()
1039 {
1040     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
1041     int32_t userId = GetCallingUserId();
1042     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1043     if (session == nullptr) {
1044         IMSA_HILOGE("%{public}d session is nullptr", userId);
1045         return ErrorCode::ERROR_NULL_POINTER;
1046     }
1047     if (!identityChecker_->IsBroker(tokenId)) {
1048         if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
1049             return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
1050         }
1051     }
1052     return session->OnHideCurrentInput();
1053 }
1054 
ShowCurrentInputDeprecated()1055 int32_t InputMethodSystemAbility::ShowCurrentInputDeprecated()
1056 {
1057     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
1058     int32_t userId = GetCallingUserId();
1059     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1060     if (session == nullptr) {
1061         IMSA_HILOGE("%{public}d session is nullptr", userId);
1062         return ErrorCode::ERROR_NULL_POINTER;
1063     }
1064     if (!identityChecker_->IsBroker(tokenId)) {
1065         if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
1066             return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
1067         }
1068     }
1069     return session->OnShowCurrentInput();
1070 }
1071 
GetCurrentInputMethod()1072 std::shared_ptr<Property> InputMethodSystemAbility::GetCurrentInputMethod()
1073 {
1074     return ImeInfoInquirer::GetInstance().GetCurrentInputMethod(GetCallingUserId());
1075 }
1076 
IsDefaultImeSet()1077 bool InputMethodSystemAbility::IsDefaultImeSet()
1078 {
1079     return ImeInfoInquirer::GetInstance().IsDefaultImeSet(GetCallingUserId());
1080 }
1081 
GetCurrentInputMethodSubtype()1082 std::shared_ptr<SubProperty> InputMethodSystemAbility::GetCurrentInputMethodSubtype()
1083 {
1084     return ImeInfoInquirer::GetInstance().GetCurrentSubtype(GetCallingUserId());
1085 }
1086 
GetDefaultInputMethod(std::shared_ptr<Property> & prop,bool isBrief)1087 int32_t InputMethodSystemAbility::GetDefaultInputMethod(std::shared_ptr<Property> &prop, bool isBrief)
1088 {
1089     return ImeInfoInquirer::GetInstance().GetDefaultInputMethod(GetCallingUserId(), prop, isBrief);
1090 }
1091 
GetInputMethodConfig(OHOS::AppExecFwk::ElementName & inputMethodConfig)1092 int32_t InputMethodSystemAbility::GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig)
1093 {
1094     return ImeInfoInquirer::GetInstance().GetInputMethodConfig(GetCallingUserId(), inputMethodConfig);
1095 }
1096 
ListInputMethod(InputMethodStatus status,std::vector<Property> & props)1097 int32_t InputMethodSystemAbility::ListInputMethod(InputMethodStatus status, std::vector<Property> &props)
1098 {
1099     return ImeInfoInquirer::GetInstance().ListInputMethod(GetCallingUserId(), status, props, enableImeOn_.load());
1100 }
1101 
ListCurrentInputMethodSubtype(std::vector<SubProperty> & subProps)1102 int32_t InputMethodSystemAbility::ListCurrentInputMethodSubtype(std::vector<SubProperty> &subProps)
1103 {
1104     return ImeInfoInquirer::GetInstance().ListCurrentInputMethodSubtype(GetCallingUserId(), subProps);
1105 }
1106 
ListInputMethodSubtype(const std::string & bundleName,std::vector<SubProperty> & subProps)1107 int32_t InputMethodSystemAbility::ListInputMethodSubtype(
1108     const std::string &bundleName, std::vector<SubProperty> &subProps)
1109 {
1110     return ImeInfoInquirer::GetInstance().ListInputMethodSubtype(GetCallingUserId(), bundleName, subProps);
1111 }
1112 
1113 /**
1114  * Work Thread of input method management service
1115  * \n Remote commands which may change the state or data in the service will be handled sequentially in this thread.
1116  */
WorkThread()1117 void InputMethodSystemAbility::WorkThread()
1118 {
1119     pthread_setname_np(pthread_self(), "OS_IMSAWorkThread");
1120     while (!stop_) {
1121         Message *msg = MessageHandler::Instance()->GetMessage();
1122         switch (msg->msgId_) {
1123             case MSG_ID_USER_START: {
1124                 OnUserStarted(msg);
1125                 break;
1126             }
1127             case MSG_ID_USER_REMOVED: {
1128                 OnUserRemoved(msg);
1129                 break;
1130             }
1131             case MSG_ID_USER_STOP: {
1132                 OnUserStop(msg);
1133                 break;
1134             }
1135             case MSG_ID_HIDE_KEYBOARD_SELF: {
1136                 OnHideKeyboardSelf(msg);
1137                 break;
1138             }
1139             case MSG_ID_BUNDLE_SCAN_FINISHED: {
1140                 break;
1141             }
1142             case MSG_ID_DATA_SHARE_READY: {
1143                 HandleDataShareReady();
1144                 break;
1145             }
1146             case MSG_ID_PACKAGE_ADDED:
1147             case MSG_ID_PACKAGE_CHANGED:
1148             case MSG_ID_PACKAGE_REMOVED: {
1149                 HandlePackageEvent(msg);
1150                 break;
1151             }
1152             case MSG_ID_SYS_LANGUAGE_CHANGED: {
1153                 FullImeInfoManager::GetInstance().Update();
1154                 break;
1155             }
1156             case MSG_ID_BOOT_COMPLETED:
1157             case MSG_ID_OS_ACCOUNT_STARTED: {
1158                 FullImeInfoManager::GetInstance().Init();
1159                 break;
1160             }
1161             case MSG_ID_USER_UNLOCKED: {
1162                 OnUserUnlocked(msg);
1163                 break;
1164             }
1165             default: {
1166                 IMSA_HILOGD("the message is %{public}d.", msg->msgId_);
1167                 break;
1168             }
1169         }
1170         delete msg;
1171     }
1172 }
1173 
1174 /**
1175  * Called when a user is started. (EVENT_USER_STARTED is received)
1176  * \n Run in work thread of input method management service
1177  * \param msg the parameters are saved in msg->msgContent_
1178  * \return ErrorCode
1179  */
OnUserStarted(const Message * msg)1180 int32_t InputMethodSystemAbility::OnUserStarted(const Message *msg)
1181 {
1182     if (msg->msgContent_ == nullptr) {
1183         IMSA_HILOGE("msgContent_ is nullptr.");
1184         return ErrorCode::ERROR_NULL_POINTER;
1185     }
1186     auto newUserId = msg->msgContent_->ReadInt32();
1187     FullImeInfoManager::GetInstance().Add(newUserId);
1188     // if scb enable, deal when receive wmsConnected.
1189     if (isScbEnable_.load()) {
1190         return ErrorCode::NO_ERROR;
1191     }
1192     if (newUserId == userId_) {
1193         return ErrorCode::NO_ERROR;
1194     }
1195     HandleUserSwitched(newUserId);
1196     return ErrorCode::NO_ERROR;
1197 }
1198 
OnUserRemoved(const Message * msg)1199 int32_t InputMethodSystemAbility::OnUserRemoved(const Message *msg)
1200 {
1201     if (msg == nullptr || msg->msgContent_ == nullptr) {
1202         IMSA_HILOGE("Aborted! Message is nullptr.");
1203         return ErrorCode::ERROR_NULL_POINTER;
1204     }
1205     auto userId = msg->msgContent_->ReadInt32();
1206     IMSA_HILOGI("start: %{public}d", userId);
1207     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1208     if (session != nullptr) {
1209         session->StopCurrentIme();
1210         UserSessionManager::GetInstance().RemoveUserSession(userId);
1211     }
1212     ImeCfgManager::GetInstance().DeleteImeCfg(userId);
1213     FullImeInfoManager::GetInstance().Delete(userId);
1214     return ErrorCode::NO_ERROR;
1215 }
1216 
OnUserStop(const Message * msg)1217 int32_t InputMethodSystemAbility::OnUserStop(const Message *msg)
1218 {
1219     if (msg == nullptr || msg->msgContent_ == nullptr) {
1220         IMSA_HILOGE("Aborted! Message is nullptr.");
1221         return ErrorCode::ERROR_NULL_POINTER;
1222     }
1223     auto userId = msg->msgContent_->ReadInt32();
1224     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1225     if (session == nullptr) {
1226         IMSA_HILOGE("%{public}d session is nullptr", userId);
1227         return ErrorCode::ERROR_NULL_POINTER;
1228     }
1229     session->StopCurrentIme();
1230     return ErrorCode::NO_ERROR;
1231 }
1232 
OnHideKeyboardSelf(const Message * msg)1233 int32_t InputMethodSystemAbility::OnHideKeyboardSelf(const Message *msg)
1234 {
1235     if (msg == nullptr || msg->msgContent_ == nullptr) {
1236         IMSA_HILOGE("Aborted! Message is nullptr.");
1237         return ErrorCode::ERROR_NULL_POINTER;
1238     }
1239     auto userId = msg->msgContent_->ReadInt32();
1240     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1241     if (session == nullptr) {
1242         IMSA_HILOGE("%{public}d session is nullptr", userId);
1243         return ErrorCode::ERROR_NULL_POINTER;
1244     }
1245     session->OnHideSoftKeyBoardSelf();
1246     return ErrorCode::NO_ERROR;
1247 }
1248 
HandlePackageEvent(const Message * msg)1249 int32_t InputMethodSystemAbility::HandlePackageEvent(const Message *msg)
1250 {
1251     MessageParcel *data = msg->msgContent_;
1252     if (data == nullptr) {
1253         IMSA_HILOGD("data is nullptr.");
1254         return ErrorCode::ERROR_NULL_POINTER;
1255     }
1256     int32_t userId = 0;
1257     std::string packageName;
1258     if (!ITypesUtil::Unmarshal(*data, userId, packageName)) {
1259         IMSA_HILOGE("failed to read message parcel");
1260         return ErrorCode::ERROR_EX_PARCELABLE;
1261     }
1262     if (msg->msgId_ == MSG_ID_PACKAGE_CHANGED) {
1263         return FullImeInfoManager::GetInstance().Update(userId, packageName);
1264     }
1265     if (msg->msgId_ == MSG_ID_PACKAGE_ADDED) {
1266         return FullImeInfoManager::GetInstance().Add(userId, packageName);
1267     }
1268     if (msg->msgId_ == MSG_ID_PACKAGE_REMOVED) {
1269         return OnPackageRemoved(userId, packageName);
1270     }
1271     return ErrorCode::NO_ERROR;
1272 }
1273 
1274 /**
1275  *  Called when a package is removed.
1276  *  \n Run in work thread of input method management service
1277  *  \param msg the parameters are saved in msg->msgContent_
1278  *  \return ErrorCode::NO_ERROR
1279  *  \return ErrorCode::ERROR_USER_NOT_UNLOCKED user not unlocked
1280  *  \return ErrorCode::ERROR_BAD_PARAMETERS bad parameter
1281  */
OnPackageRemoved(int32_t userId,const std::string & packageName)1282 int32_t InputMethodSystemAbility::OnPackageRemoved(int32_t userId, const std::string &packageName)
1283 {
1284     FullImeInfoManager::GetInstance().Delete(userId, packageName);
1285     // if the app that doesn't belong to current user is removed, ignore it
1286     if (userId != userId_) {
1287         IMSA_HILOGD("userId: %{public}d, currentUserId: %{public}d.", userId, userId_);
1288         return ErrorCode::NO_ERROR;
1289     }
1290     auto currentImeBundle = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
1291     if (packageName == currentImeBundle) {
1292         // Switch to the default ime
1293         IMSA_HILOGI("user[%{public}d] ime: %{public}s is uninstalled.", userId, packageName.c_str());
1294         auto info = ImeInfoInquirer::GetInstance().GetDefaultImeInfo(userId);
1295         if (info == nullptr) {
1296             return ErrorCode::ERROR_PERSIST_CONFIG;
1297         }
1298         int32_t ret = SwitchExtension(userId, info);
1299         IMSA_HILOGI("switch ret: %{public}d", ret);
1300     }
1301     return ErrorCode::NO_ERROR;
1302 }
1303 
OnUserUnlocked(const Message * msg)1304 void InputMethodSystemAbility::OnUserUnlocked(const Message *msg)
1305 {
1306     if (msg == nullptr || msg->msgContent_ == nullptr) {
1307         IMSA_HILOGE("message is nullptr");
1308         return;
1309     }
1310     int32_t userId = 0;
1311     if (!ITypesUtil::Unmarshal(*msg->msgContent_, userId)) {
1312         IMSA_HILOGE("failed to read message");
1313         return;
1314     }
1315     IMSA_HILOGI("userId: %{public}d", userId);
1316     if (userId != userId_) {
1317         return;
1318     }
1319     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1320     if (session == nullptr) {
1321         UserSessionManager::GetInstance().AddUserSession(userId_);
1322     }
1323     session = UserSessionManager::GetInstance().GetUserSession(userId_);
1324     if (session == nullptr) {
1325         IMSA_HILOGE("%{public}d session is nullptr!", userId_);
1326         return;
1327     }
1328     session->OnUserUnlocked();
1329 }
1330 
OnDisplayOptionalInputMethod()1331 int32_t InputMethodSystemAbility::OnDisplayOptionalInputMethod()
1332 {
1333     IMSA_HILOGD("InputMethodSystemAbility::OnDisplayOptionalInputMethod start.");
1334     auto abilityManager = GetAbilityManagerService();
1335     if (abilityManager == nullptr) {
1336         IMSA_HILOGE("InputMethodSystemAbility::get ability manager failed");
1337         return ErrorCode::ERROR_EX_SERVICE_SPECIFIC;
1338     }
1339     AAFwk::Want want;
1340     want.SetAction(SELECT_DIALOG_ACTION);
1341     want.SetElementName(SELECT_DIALOG_HAP, SELECT_DIALOG_ABILITY);
1342     int32_t ret = abilityManager->StartAbility(want);
1343     if (ret != ErrorCode::NO_ERROR && ret != START_SERVICE_ABILITY_ACTIVATING) {
1344         IMSA_HILOGE("start InputMethod ability failed, err: %{public}d", ret);
1345         return ErrorCode::ERROR_EX_SERVICE_SPECIFIC;
1346     }
1347     IMSA_HILOGI("start InputMethod ability success.");
1348     return ErrorCode::NO_ERROR;
1349 }
1350 
GetAbilityManagerService()1351 sptr<AAFwk::IAbilityManager> InputMethodSystemAbility::GetAbilityManagerService()
1352 {
1353     IMSA_HILOGD("InputMethodSystemAbility::GetAbilityManagerService start");
1354     auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1355     if (systemAbilityManager == nullptr) {
1356         IMSA_HILOGE("SystemAbilityManager is nullptr.");
1357         return nullptr;
1358     }
1359 
1360     auto abilityMsObj = systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID);
1361     if (abilityMsObj == nullptr) {
1362         IMSA_HILOGE("Failed to get ability manager service.");
1363         return nullptr;
1364     }
1365 
1366     return iface_cast<AAFwk::IAbilityManager>(abilityMsObj);
1367 }
1368 
SwitchByCombinationKey(uint32_t state)1369 int32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state)
1370 {
1371     IMSA_HILOGD("InputMethodSystemAbility::SwitchByCombinationKey start.");
1372     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1373     if (session == nullptr) {
1374         IMSA_HILOGE("%{public}d session is nullptr", userId_);
1375         return ErrorCode::ERROR_NULL_POINTER;
1376     }
1377     if (session->IsProxyImeEnable()) {
1378         IMSA_HILOGI("proxy enable, not switch.");
1379         return ErrorCode::NO_ERROR;
1380     }
1381     if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_MODE, state)) {
1382         IMSA_HILOGI("switch mode.");
1383         return SwitchMode();
1384     }
1385     if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_LANGUAGE, state)) {
1386         IMSA_HILOGI("switch language.");
1387         return SwitchLanguage();
1388     }
1389     bool isScreenLocked = false;
1390 #ifdef IMF_SCREENLOCK_MGR_ENABLE
1391     if (ScreenLock::ScreenLockManager::GetInstance()->IsScreenLocked()) {
1392         IMSA_HILOGI("isScreenLocked  now.");
1393         isScreenLocked = true;
1394     }
1395 #endif
1396     if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_IME, state) && !isScreenLocked) {
1397         IMSA_HILOGI("switch ime.");
1398         DealSwitchRequest();
1399         return ErrorCode::NO_ERROR;
1400     }
1401     IMSA_HILOGE("keycode is undefined");
1402     return ErrorCode::ERROR_EX_UNSUPPORTED_OPERATION;
1403 }
1404 
DealSecurityChange()1405 void InputMethodSystemAbility::DealSecurityChange()
1406 {
1407     {
1408         std::lock_guard<std::mutex> lock(modeChangeMutex_);
1409         if (isChangeHandling_) {
1410             IMSA_HILOGI("already has mode change task.");
1411             hasPendingChanges_ = true;
1412             return;
1413         } else {
1414             isChangeHandling_ = true;
1415             hasPendingChanges_ = true;
1416         }
1417     }
1418     auto changeTask = [this]() {
1419         pthread_setname_np(pthread_self(), "SecurityChange");
1420         auto checkChangeCount = [this]() {
1421             std::lock_guard<std::mutex> lock(modeChangeMutex_);
1422             if (hasPendingChanges_) {
1423                 return true;
1424             }
1425             isChangeHandling_ = false;
1426             return false;
1427         };
1428         do {
1429             OnSecurityModeChange();
1430         } while (checkChangeCount());
1431     };
1432     std::thread(changeTask).detach();
1433 }
1434 
DealSwitchRequest()1435 void InputMethodSystemAbility::DealSwitchRequest()
1436 {
1437     {
1438         std::lock_guard<std::mutex> lock(switchImeMutex_);
1439         // 0 means current swich ime task count.
1440         if (switchTaskExecuting_.load()) {
1441             IMSA_HILOGI("already has switch ime task.");
1442             ++targetSwitchCount_;
1443             return;
1444         } else {
1445             switchTaskExecuting_.store(true);
1446             ++targetSwitchCount_;
1447         }
1448     }
1449     auto switchTask = [this]() {
1450         auto checkSwitchCount = [this]() {
1451             std::lock_guard<std::mutex> lock(switchImeMutex_);
1452             if (targetSwitchCount_ > 0) {
1453                 return true;
1454             }
1455             switchTaskExecuting_.store(false);
1456             return false;
1457         };
1458         do {
1459             SwitchType();
1460         } while (checkSwitchCount());
1461     };
1462     // 0 means delay time is 0.
1463     serviceHandler_->PostTask(switchTask, "SwitchImeTask", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1464 }
1465 
SwitchMode()1466 int32_t InputMethodSystemAbility::SwitchMode()
1467 {
1468     auto bundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
1469     auto subName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->subName;
1470     auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, bundleName, subName);
1471     if (info == nullptr) {
1472         IMSA_HILOGE("current ime is abnormal!");
1473         return ErrorCode::ERROR_BAD_PARAMETERS;
1474     }
1475     if (info->isNewIme) {
1476         IMSA_HILOGD("the switching operation is handed over to ime.");
1477         return ErrorCode::NO_ERROR;
1478     }
1479     auto condition = info->subProp.mode == "upper" ? Condition::LOWER : Condition::UPPER;
1480     auto target = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(info->subProps, condition);
1481     if (target == nullptr) {
1482         IMSA_HILOGE("target is empty!");
1483         return ErrorCode::ERROR_BAD_PARAMETERS;
1484     }
1485     SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
1486     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1487     if (session == nullptr) {
1488         IMSA_HILOGE("%{public}d session is nullptr", userId_);
1489         return ErrorCode::ERROR_NULL_POINTER;
1490     }
1491     session->GetSwitchQueue().Push(switchInfo);
1492     return OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
1493 }
1494 
SwitchLanguage()1495 int32_t InputMethodSystemAbility::SwitchLanguage()
1496 {
1497     auto bundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
1498     auto subName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->subName;
1499     auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, bundleName, subName);
1500     if (info == nullptr) {
1501         IMSA_HILOGE("current ime is abnormal!");
1502         return ErrorCode::ERROR_BAD_PARAMETERS;
1503     }
1504     if (info->isNewIme) {
1505         IMSA_HILOGD("the switching operation is handed over to ime.");
1506         return ErrorCode::NO_ERROR;
1507     }
1508     if (info->subProp.language != "chinese" && info->subProp.language != "english") {
1509         return ErrorCode::NO_ERROR;
1510     }
1511     auto condition = info->subProp.language == "chinese" ? Condition::ENGLISH : Condition::CHINESE;
1512     auto target = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(info->subProps, condition);
1513     if (target == nullptr) {
1514         IMSA_HILOGE("target is empty!");
1515         return ErrorCode::ERROR_BAD_PARAMETERS;
1516     }
1517     SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
1518     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1519     if (session == nullptr) {
1520         IMSA_HILOGE("%{public}d session is nullptr", userId_);
1521         return ErrorCode::ERROR_NULL_POINTER;
1522     }
1523     session->GetSwitchQueue().Push(switchInfo);
1524     return OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
1525 }
1526 
SwitchType()1527 int32_t InputMethodSystemAbility::SwitchType()
1528 {
1529     SwitchInfo switchInfo = { std::chrono::system_clock::now(), "", "" };
1530     uint32_t cacheCount = 0;
1531     {
1532         std::lock_guard<std::mutex> lock(switchImeMutex_);
1533         cacheCount = targetSwitchCount_.exchange(0);
1534     }
1535     int32_t ret =
1536         ImeInfoInquirer::GetInstance().GetSwitchInfoBySwitchCount(switchInfo, userId_, enableImeOn_.load(), cacheCount);
1537     if (ret != ErrorCode::NO_ERROR) {
1538         IMSA_HILOGE("get next SwitchInfo failed, stop switching ime.");
1539         return ret;
1540     }
1541     IMSA_HILOGD("switch to: %{public}s.", switchInfo.bundleName.c_str());
1542     switchInfo.timestamp = std::chrono::system_clock::now();
1543     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1544     if (session == nullptr) {
1545         IMSA_HILOGE("%{public}d session is nullptr", userId_);
1546         return ErrorCode::ERROR_NULL_POINTER;
1547     }
1548     session->GetSwitchQueue().Push(switchInfo);
1549     return OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
1550 }
1551 
InitMonitors()1552 void InputMethodSystemAbility::InitMonitors()
1553 {
1554     int32_t ret = InitAccountMonitor();
1555     IMSA_HILOGI("init account monitor, ret: %{public}d.", ret);
1556     SubscribeCommonEvent();
1557     ret = InitMemMgrMonitor();
1558     IMSA_HILOGI("init MemMgr monitor, ret: %{public}d.", ret);
1559     ret = InitKeyEventMonitor();
1560     IMSA_HILOGI("init KeyEvent monitor, ret: %{public}d.", ret);
1561     ret = InitWmsMonitor();
1562     IMSA_HILOGI("init wms monitor, ret: %{public}d.", ret);
1563     InitSystemLanguageMonitor();
1564 }
1565 
HandleDataShareReady()1566 void InputMethodSystemAbility::HandleDataShareReady()
1567 {
1568     if (ImeInfoInquirer::GetInstance().IsEnableInputMethod()) {
1569         IMSA_HILOGW("Enter enable mode.");
1570         RegisterEnableImeObserver();
1571         EnableImeDataParser::GetInstance()->Initialize(userId_);
1572         enableImeOn_.store(true);
1573     }
1574     if (ImeInfoInquirer::GetInstance().IsEnableSecurityMode()) {
1575         IMSA_HILOGW("Enter security mode.");
1576         RegisterSecurityModeObserver();
1577         SecurityModeParser::GetInstance()->Initialize(userId_);
1578         enableSecurityMode_.store(true);
1579     }
1580     FullImeInfoManager::GetInstance().Init();
1581 }
1582 
InitAccountMonitor()1583 int32_t InputMethodSystemAbility::InitAccountMonitor()
1584 {
1585     IMSA_HILOGI("InputMethodSystemAbility::InitAccountMonitor start.");
1586     return ImCommonEventManager::GetInstance()->SubscribeAccountManagerService([this]() { HandleOsAccountStarted(); });
1587 }
1588 
InitKeyEventMonitor()1589 int32_t InputMethodSystemAbility::InitKeyEventMonitor()
1590 {
1591     IMSA_HILOGI("InputMethodSystemAbility::InitKeyEventMonitor start.");
1592     bool ret = ImCommonEventManager::GetInstance()->SubscribeKeyboardEvent(
1593         [this](uint32_t keyCode) { return SwitchByCombinationKey(keyCode); });
1594     return ret ? ErrorCode::NO_ERROR : ErrorCode::ERROR_SERVICE_START_FAILED;
1595 }
1596 
InitWmsMonitor()1597 bool InputMethodSystemAbility::InitWmsMonitor()
1598 {
1599     return ImCommonEventManager::GetInstance()->SubscribeWindowManagerService([this]() { HandleWmsStarted(); });
1600 }
1601 
InitMemMgrMonitor()1602 bool InputMethodSystemAbility::InitMemMgrMonitor()
1603 {
1604     return ImCommonEventManager::GetInstance()->SubscribeMemMgrService([this]() { HandleMemStarted(); });
1605 }
1606 
InitWmsConnectionMonitor()1607 void InputMethodSystemAbility::InitWmsConnectionMonitor()
1608 {
1609     WmsConnectionMonitorManager::GetInstance().RegisterWMSConnectionChangedListener(
1610         [this](bool isConnected, int32_t userId, int32_t screenId) {
1611             isConnected ? HandleWmsConnected(userId, screenId) : HandleWmsDisconnected(userId, screenId);
1612         });
1613 }
1614 
InitSystemLanguageMonitor()1615 void InputMethodSystemAbility::InitSystemLanguageMonitor()
1616 {
1617     SystemLanguageObserver::GetInstance().Watch();
1618 }
1619 
InitFocusChangedMonitor()1620 void InputMethodSystemAbility::InitFocusChangedMonitor()
1621 {
1622     FocusMonitorManager::GetInstance().RegisterFocusChangedListener(
1623         [this](bool isOnFocused, int32_t pid, int32_t uid) { HandleFocusChanged(isOnFocused, pid, uid); });
1624 }
1625 
RegisterEnableImeObserver()1626 void InputMethodSystemAbility::RegisterEnableImeObserver()
1627 {
1628     int32_t ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(EnableImeDataParser::ENABLE_IME,
1629         [this]() { DatashareCallback(EnableImeDataParser::ENABLE_IME); });
1630     IMSA_HILOGI("register enable ime observer, ret: %{public}d.", ret);
1631     ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(EnableImeDataParser::ENABLE_KEYBOARD,
1632         [this]() { DatashareCallback(EnableImeDataParser::ENABLE_KEYBOARD); });
1633     IMSA_HILOGI("register enable keyboard observer, ret: %{public}d.", ret);
1634 }
1635 
RegisterSecurityModeObserver()1636 void InputMethodSystemAbility::RegisterSecurityModeObserver()
1637 {
1638     int32_t ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(SecurityModeParser::SECURITY_MODE,
1639         [this]() { DatashareCallback(SecurityModeParser::SECURITY_MODE); });
1640     IMSA_HILOGI("register security mode observer, ret: %{public}d", ret);
1641 }
1642 
DatashareCallback(const std::string & key)1643 void InputMethodSystemAbility::DatashareCallback(const std::string &key)
1644 {
1645     IMSA_HILOGI("start.");
1646     if (key == EnableImeDataParser::ENABLE_KEYBOARD || key == EnableImeDataParser::ENABLE_IME) {
1647         EnableImeDataParser::GetInstance()->OnConfigChanged(userId_, key);
1648         std::lock_guard<std::mutex> autoLock(checkMutex_);
1649         SwitchInfo switchInfo;
1650         if (EnableImeDataParser::GetInstance()->CheckNeedSwitch(key, switchInfo, userId_)) {
1651             auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1652             if (session == nullptr) {
1653                 IMSA_HILOGE("%{public}d session is nullptr", userId_);
1654                 return;
1655             }
1656             switchInfo.timestamp = std::chrono::system_clock::now();
1657             session->GetSwitchQueue().Push(switchInfo);
1658             OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
1659         }
1660     }
1661     if (key == SecurityModeParser::SECURITY_MODE) {
1662         DealSecurityChange();
1663     }
1664 }
1665 
OnSecurityModeChange()1666 void InputMethodSystemAbility::OnSecurityModeChange()
1667 {
1668     {
1669         std::lock_guard<std::mutex> lock(modeChangeMutex_);
1670         hasPendingChanges_ = false;
1671     }
1672     auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
1673     auto oldMode = SecurityModeParser::GetInstance()->GetSecurityMode(currentIme->bundleName, userId_);
1674     SecurityModeParser::GetInstance()->UpdateFullModeList(userId_);
1675     auto newMode = SecurityModeParser::GetInstance()->GetSecurityMode(currentIme->bundleName, userId_);
1676     if (oldMode == newMode) {
1677         IMSA_HILOGD("current ime mode not changed.");
1678         return;
1679     }
1680     IMSA_HILOGI("ime: %{public}s securityMode change to: %{public}d.", currentIme->bundleName.c_str(),
1681         static_cast<int32_t>(newMode));
1682     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1683     if (session == nullptr) {
1684         IMSA_HILOGE("%{public}d session is nullptr", userId_);
1685         return;
1686     }
1687     session->OnSecurityChange(static_cast<int32_t>(newMode));
1688     session->AddRestartIme();
1689 }
1690 
GetSecurityMode(int32_t & security)1691 int32_t InputMethodSystemAbility::GetSecurityMode(int32_t &security)
1692 {
1693     IMSA_HILOGD("InputMethodSystemAbility start.");
1694     if (!enableSecurityMode_.load()) {
1695         security = static_cast<int32_t>(SecurityMode::FULL);
1696         return ErrorCode::NO_ERROR;
1697     }
1698     auto userId = GetCallingUserId();
1699     auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID());
1700     if (bundleName.empty()) {
1701         bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID());
1702         IMSA_HILOGW("%{public}s tokenId not find.", bundleName.c_str());
1703     }
1704     SecurityMode mode = SecurityModeParser::GetInstance()->GetSecurityMode(bundleName, userId);
1705     security = static_cast<int32_t>(mode);
1706     return ErrorCode::NO_ERROR;
1707 }
1708 
UnRegisteredProxyIme(UnRegisteredType type,const sptr<IInputMethodCore> & core)1709 int32_t InputMethodSystemAbility::UnRegisteredProxyIme(UnRegisteredType type, const sptr<IInputMethodCore> &core)
1710 {
1711     if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
1712         IMSA_HILOGE("not native sa!");
1713         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1714     }
1715     auto userId = GetCallingUserId();
1716     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1717     if (session == nullptr) {
1718         IMSA_HILOGE("%{public}d session is nullptr", userId);
1719         return ErrorCode::ERROR_NULL_POINTER;
1720     }
1721     if (type == UnRegisteredType::SWITCH_PROXY_IME_TO_IME) {
1722         int32_t ret = ErrorCode::NO_ERROR;
1723         if (session->CheckSecurityMode()) {
1724             ret = StartInputType(userId, InputType::SECURITY_INPUT);
1725         } else {
1726             ret = session->RestoreCurrentIme();
1727         }
1728         if (ret != ErrorCode::NO_ERROR) {
1729             return ret;
1730         }
1731     }
1732     return session->OnUnRegisteredProxyIme(type, core);
1733 }
1734 
CheckEnableAndSwitchPermission()1735 int32_t InputMethodSystemAbility::CheckEnableAndSwitchPermission()
1736 {
1737     if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingFullTokenID())) {
1738         IMSA_HILOGE("not native sa!");
1739         return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
1740     }
1741     if (!identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
1742         IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!");
1743         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1744     }
1745     return ErrorCode::NO_ERROR;
1746 }
1747 
CheckSwitchPermission(int32_t userId,const SwitchInfo & switchInfo,SwitchTrigger trigger)1748 int32_t InputMethodSystemAbility::CheckSwitchPermission(int32_t userId, const SwitchInfo &switchInfo,
1749     SwitchTrigger trigger)
1750 {
1751     IMSA_HILOGD("trigger: %{public}d.", static_cast<int32_t>(trigger));
1752     if (trigger == SwitchTrigger::IMSA) {
1753         return ErrorCode::NO_ERROR;
1754     }
1755     if (trigger == SwitchTrigger::NATIVE_SA) {
1756         return CheckEnableAndSwitchPermission();
1757     }
1758     if (trigger == SwitchTrigger::SYSTEM_APP) {
1759         if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
1760             IMSA_HILOGE("not system app!");
1761             return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
1762         }
1763         if (!identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
1764             IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY");
1765             return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1766         }
1767         return ErrorCode::NO_ERROR;
1768     }
1769     if (trigger == SwitchTrigger::CURRENT_IME) {
1770         // PERMISSION_CONNECT_IME_ABILITY check temporarily reserved for application adaptation, will be deleted soon
1771         if (identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
1772             return ErrorCode::NO_ERROR;
1773         }
1774         IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY");
1775         // switchInfo.subName.empty() check temporarily reserved for application adaptation, will be deleted soon
1776         auto currentBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
1777         if (identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentBundleName) &&
1778             !switchInfo.subName.empty()) {
1779             return ErrorCode::NO_ERROR;
1780         }
1781         IMSA_HILOGE("not current ime!");
1782         /* return ErrorCode::ERROR_STATUS_PERMISSION_DENIED temporarily reserved for application adaptation,
1783         will be replaced by ERROR_NOT_CURRENT_IME soon */
1784         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1785     }
1786     return ErrorCode::ERROR_BAD_PARAMETERS;
1787 }
1788 
IsStartInputTypePermitted(int32_t userId)1789 bool InputMethodSystemAbility::IsStartInputTypePermitted(int32_t userId)
1790 {
1791     auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeInfo(userId);
1792     if (defaultIme == nullptr) {
1793         IMSA_HILOGE("failed to get default ime!");
1794         return false;
1795     }
1796     auto tokenId = IPCSkeleton::GetCallingTokenID();
1797     if (identityChecker_->IsBundleNameValid(tokenId, defaultIme->prop.name)) {
1798         return true;
1799     }
1800     if (identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
1801         return true;
1802     }
1803     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1804     if (session == nullptr) {
1805         IMSA_HILOGE("%{public}d session is nullptr", userId);
1806         return false;
1807     }
1808     return identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId) && session->IsBoundToClient();
1809 }
1810 
ConnectSystemCmd(const sptr<IRemoteObject> & channel,sptr<IRemoteObject> & agent)1811 int32_t InputMethodSystemAbility::ConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)
1812 {
1813     auto tokenId = IPCSkeleton::GetCallingTokenID();
1814     if (!identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
1815         IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY");
1816         return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
1817     }
1818     auto userId = GetCallingUserId();
1819     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1820     if (session == nullptr) {
1821         IMSA_HILOGE("%{public}d session is nullptr", userId);
1822         return ErrorCode::ERROR_NULL_POINTER;
1823     }
1824     return session->OnConnectSystemCmd(channel, agent);
1825 }
1826 
HandleWmsConnected(int32_t userId,int32_t screenId)1827 void InputMethodSystemAbility::HandleWmsConnected(int32_t userId, int32_t screenId)
1828 {
1829     if (userId == userId_) {
1830         // device boot or scb in foreground reboot
1831         HandleScbStarted(userId, screenId);
1832         return;
1833     }
1834     // user switched
1835     HandleUserSwitched(userId);
1836 }
1837 
HandleScbStarted(int32_t userId,int32_t screenId)1838 void InputMethodSystemAbility::HandleScbStarted(int32_t userId, int32_t screenId)
1839 {
1840     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1841     if (session == nullptr) {
1842         UserSessionManager::GetInstance().AddUserSession(userId);
1843     }
1844     session = UserSessionManager::GetInstance().GetUserSession(userId);
1845     if (session == nullptr) {
1846         IMSA_HILOGE("%{public}d session is nullptr", userId);
1847         return;
1848     }
1849     session->AddRestartIme();
1850 }
1851 
HandleUserSwitched(int32_t userId)1852 void InputMethodSystemAbility::HandleUserSwitched(int32_t userId)
1853 {
1854     UpdateUserInfo(userId);
1855     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1856     if (session == nullptr) {
1857         UserSessionManager::GetInstance().AddUserSession(userId);
1858     }
1859     session = UserSessionManager::GetInstance().GetUserSession(userId);
1860     if (session == nullptr) {
1861         IMSA_HILOGE("%{public}d session is nullptr", userId);
1862         return;
1863     }
1864     auto imeData = session->GetReadyImeData(ImeType::IME);
1865     if (imeData == nullptr && session->IsWmsReady()) {
1866         session->StartCurrentIme();
1867     }
1868 }
1869 
HandleWmsDisconnected(int32_t userId,int32_t screenId)1870 void InputMethodSystemAbility::HandleWmsDisconnected(int32_t userId, int32_t screenId)
1871 {
1872     // clear client
1873     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1874     if (session != nullptr) {
1875         session->RemoveCurrentClient();
1876     }
1877 
1878     if (userId == userId_) {
1879         // user switched or scb in foreground died, not deal
1880         return;
1881     }
1882     // scb in background died, stop ime
1883     if (session == nullptr) {
1884         return;
1885     }
1886     session->StopCurrentIme();
1887 }
1888 
HandleWmsStarted()1889 void InputMethodSystemAbility::HandleWmsStarted()
1890 {
1891     // singleton, device boot, wms reboot
1892     IMSA_HILOGI("Wms start.");
1893     InitFocusChangedMonitor();
1894     if (isScbEnable_.load()) {
1895         IMSA_HILOGI("scb enable, register WMS connection listener.");
1896         InitWmsConnectionMonitor();
1897         return;
1898     }
1899     // clear client
1900     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1901     if (session != nullptr) {
1902         session->RemoveCurrentClient();
1903     }
1904     if (session == nullptr) {
1905         UserSessionManager::GetInstance().AddUserSession(userId_);
1906     }
1907     session = UserSessionManager::GetInstance().GetUserSession(userId_);
1908     if (session == nullptr) {
1909         IMSA_HILOGE("%{public}d session is nullptr", userId_);
1910         return;
1911     }
1912     session->AddRestartIme();
1913     StopImeInBackground();
1914 }
1915 
HandleFocusChanged(bool isFocused,int32_t pid,int32_t uid)1916 void InputMethodSystemAbility::HandleFocusChanged(bool isFocused, int32_t pid, int32_t uid)
1917 {
1918     int32_t userId = GetUserId(uid);
1919     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1920     if (session == nullptr) {
1921         IMSA_HILOGE("[%{public}d, %{public}d] session is nullptr", uid, userId);
1922         return;
1923     }
1924     isFocused ? session->OnFocused(pid, uid) : session->OnUnfocused(pid, uid);
1925 }
1926 
HandleMemStarted()1927 void InputMethodSystemAbility::HandleMemStarted()
1928 {
1929     // singleton
1930     IMSA_HILOGI("MemMgr start.");
1931     Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 1, INPUT_METHOD_SYSTEM_ABILITY_ID);
1932     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1933     if (session == nullptr) {
1934         UserSessionManager::GetInstance().AddUserSession(userId_);
1935     }
1936     session = UserSessionManager::GetInstance().GetUserSession(userId_);
1937     if (session == nullptr) {
1938         IMSA_HILOGE("%{public}d session is nullptr", userId_);
1939         return;
1940     }
1941     session->AddRestartIme();
1942     StopImeInBackground();
1943 }
1944 
HandleOsAccountStarted()1945 void InputMethodSystemAbility::HandleOsAccountStarted()
1946 {
1947     IMSA_HILOGI("account start");
1948     auto userId = OsAccountAdapter::GetForegroundOsAccountLocalId();
1949     if (userId_ != userId) {
1950         UpdateUserInfo(userId);
1951     } else {
1952         UpdateUserLockState();
1953     }
1954     Message *msg = new (std::nothrow) Message(MessageID::MSG_ID_OS_ACCOUNT_STARTED, nullptr);
1955     if (msg == nullptr) {
1956         return;
1957     }
1958     MessageHandler::Instance()->SendMessage(msg);
1959 }
1960 
StopImeInBackground()1961 void InputMethodSystemAbility::StopImeInBackground()
1962 {
1963     auto task = [this]() {
1964         auto sessions = UserSessionManager::GetInstance().GetUserSessions();
1965         for (const auto &tempSession : sessions) {
1966             if (tempSession.first != userId_) {
1967                 tempSession.second->StopCurrentIme();
1968             }
1969         }
1970     };
1971     serviceHandler_->PostTask(task, "StopImeInBackground", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1972 }
1973 
GetUserId(int32_t uid)1974 int32_t InputMethodSystemAbility::GetUserId(int32_t uid)
1975 {
1976     IMSA_HILOGD("uid:%{public}d", uid);
1977     auto userId = OsAccountAdapter::GetOsAccountLocalIdFromUid(uid);
1978     // 0 represents user 0 in the system
1979     if (userId == 0) {
1980         IMSA_HILOGI("user 0");
1981         return userId_;
1982     }
1983     return userId;
1984 }
1985 
GetCallingUserId()1986 int32_t InputMethodSystemAbility::GetCallingUserId()
1987 {
1988     auto uid = IPCSkeleton::GetCallingUid();
1989     return GetUserId(uid);
1990 }
1991 
IsCurrentIme(int32_t userId)1992 bool InputMethodSystemAbility::IsCurrentIme(int32_t userId)
1993 {
1994     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1995     if (session == nullptr) {
1996         IMSA_HILOGE("%{public}d session is nullptr", userId);
1997         return false;
1998     }
1999     auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID());
2000     if (bundleName.empty()) {
2001         IMSA_HILOGW("user:%{public}d tokenId:%{public}d not find.", userId, IPCSkeleton::GetCallingTokenID());
2002         bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID());
2003     }
2004     auto imeData = session->GetImeData(ImeType::IME);
2005     return imeData != nullptr && bundleName == imeData->ime.first;
2006 }
2007 
StartInputType(int32_t userId,InputType type)2008 int32_t InputMethodSystemAbility::StartInputType(int32_t userId, InputType type)
2009 {
2010     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2011     if (session == nullptr) {
2012         IMSA_HILOGE("%{public}d session is nullptr", userId);
2013         return ErrorCode::ERROR_NULL_POINTER;
2014     }
2015     ImeIdentification ime;
2016     int32_t ret = InputTypeManager::GetInstance().GetImeByInputType(type, ime);
2017     if (ret != ErrorCode::NO_ERROR) {
2018         IMSA_HILOGW("not find input type: %{public}d.", type);
2019         // add for not adapter for SECURITY_INPUT
2020         if (type == InputType::SECURITY_INPUT) {
2021             return session->RestoreCurrentIme();
2022         }
2023         return ret;
2024     }
2025     SwitchInfo switchInfo = { std::chrono::system_clock::now(), ime.bundleName, ime.subName };
2026     session->GetSwitchQueue().Push(switchInfo);
2027     IMSA_HILOGI("start input type: %{public}d.", type);
2028     return type == InputType::SECURITY_INPUT ? OnStartInputType(userId, switchInfo, false)
2029                                              : OnStartInputType(userId, switchInfo, true);
2030 }
2031 
NeedHideWhenSwitchInputType(int32_t userId,bool & needHide)2032 void InputMethodSystemAbility::NeedHideWhenSwitchInputType(int32_t userId, bool &needHide)
2033 {
2034     ImeIdentification ime;
2035     InputTypeManager::GetInstance().GetImeByInputType(InputType::SECURITY_INPUT, ime);
2036     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
2037     if (currentImeCfg == nullptr) {
2038         IMSA_HILOGI("currentImeCfg is nullptr");
2039         return;
2040     }
2041     needHide = currentImeCfg->bundleName == ime.bundleName;
2042 }
2043 
GetInputMethodState(EnabledStatus & status)2044 int32_t InputMethodSystemAbility::GetInputMethodState(EnabledStatus &status)
2045 {
2046     auto userId = GetCallingUserId();
2047     auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID());
2048     if (bundleName.empty()) {
2049         bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID());
2050         if (!ImeInfoInquirer::GetInstance().IsInputMethod(userId, bundleName)) {
2051             IMSA_HILOGE("[%{public}d, %{public}s] not an ime.", userId, bundleName.c_str());
2052             return ErrorCode::ERROR_NOT_IME;
2053         }
2054     }
2055 
2056     auto ret = GetInputMethodState(userId, bundleName, status);
2057     if (ret != ErrorCode::NO_ERROR) {
2058         return ret;
2059     }
2060     return ErrorCode::NO_ERROR;
2061 }
2062 
GetInputMethodState(int32_t userId,const std::string & bundleName,EnabledStatus & status)2063 int32_t InputMethodSystemAbility::GetInputMethodState(
2064     int32_t userId, const std::string &bundleName, EnabledStatus &status)
2065 {
2066     auto isDefaultBasicMode = !ImeInfoInquirer::GetInstance().IsEnableInputMethod();
2067     auto isDefaultFullExperience = !ImeInfoInquirer::GetInstance().IsEnableSecurityMode();
2068     IMSA_HILOGI("sys cfg:[%{public}d, %{public}d].", isDefaultBasicMode, isDefaultFullExperience);
2069     auto isSecurityMode = SecurityModeParser::GetInstance()->IsSecurityMode(userId, bundleName);
2070     if (isDefaultBasicMode) {
2071         if (isDefaultFullExperience) {
2072             status = EnabledStatus::FULL_EXPERIENCE_MODE;
2073             return ErrorCode::NO_ERROR;
2074         }
2075         status = isSecurityMode ? EnabledStatus::FULL_EXPERIENCE_MODE : EnabledStatus::BASIC_MODE;
2076         return ErrorCode::NO_ERROR;
2077     }
2078 
2079     if (isDefaultFullExperience) {
2080         auto ret = EnableImeDataParser::GetInstance()->GetImeEnablePattern(userId, bundleName, status);
2081         if (ret != ErrorCode::NO_ERROR) {
2082             return ret;
2083         }
2084         if (status == EnabledStatus::BASIC_MODE) {
2085             status = EnabledStatus::FULL_EXPERIENCE_MODE;
2086         }
2087         return ErrorCode::NO_ERROR;
2088     }
2089 
2090     if (isSecurityMode) {
2091         status = EnabledStatus::FULL_EXPERIENCE_MODE;
2092         return ErrorCode::NO_ERROR;
2093     }
2094 
2095     auto ret = EnableImeDataParser::GetInstance()->GetImeEnablePattern(userId, bundleName, status);
2096     return ret;
2097 }
2098 
2099 } // namespace MiscServices
2100 } // namespace OHOS