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