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