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