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