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