• 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 "securec.h"
17 #include "unordered_map"
18 #include "variant"
19 #include "input_method_system_ability.h"
20 
21 #include <cinttypes>
22 
23 #include "ability_connect_callback_proxy.h"
24 #include "ability_manager_errors.h"
25 #include "ability_manager_interface.h"
26 #include "application_info.h"
27 #include "combination_key.h"
28 #include "full_ime_info_manager.h"
29 #include "ime_enabled_info_manager.h"
30 #include "im_common_event_manager.h"
31 #include "imsa_hisysevent_reporter.h"
32 #include "input_manager.h"
33 #include "ipc_skeleton.h"
34 #include "iservice_registry.h"
35 #include "itypes_util.h"
36 #include "mem_mgr_client.h"
37 #include "numkey_apps_manager.h"
38 #include "inputmethod_message_handler.h"
39 #include "os_account_adapter.h"
40 #include "scene_board_judgement.h"
41 #include "system_ability_definition.h"
42 #ifdef IMF_SCREENLOCK_MGR_ENABLE
43 #include "screenlock_manager.h"
44 #endif
45 #include "system_param_adapter.h"
46 #include "wms_connection_observer.h"
47 #include "xcollie/xcollie.h"
48 #ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE
49 #include "on_demand_start_stop_sa.h"
50 #endif
51 #include "window_adapter.h"
52 #include "input_method_tools.h"
53 #include "ime_state_manager_factory.h"
54 
55 namespace OHOS {
56 namespace MiscServices {
57 using namespace MessageID;
58 using namespace AppExecFwk;
59 using namespace Security::AccessToken;
60 using namespace std::chrono;
61 using namespace HiviewDFX;
62 constexpr uint32_t FATAL_TIMEOUT = 30;    // 30s
63 constexpr int64_t WARNING_TIMEOUT = 5000; // 5s
64 REGISTER_SYSTEM_ABILITY_BY_ID(InputMethodSystemAbility, INPUT_METHOD_SYSTEM_ABILITY_ID, true);
65 constexpr std::int32_t INIT_INTERVAL = 10000L;
66 constexpr const char *UNDEFINED = "undefined";
67 static const char *PERMISSION_CONNECT_IME_ABILITY = "ohos.permission.CONNECT_IME_ABILITY";
68 std::shared_ptr<AppExecFwk::EventHandler> InputMethodSystemAbility::serviceHandler_;
69 constexpr uint32_t START_SA_TIMEOUT = 6; // 6s
70 constexpr const char *SELECT_DIALOG_ACTION = "action.system.inputmethodchoose";
71 constexpr const char *SELECT_DIALOG_HAP = "com.ohos.inputmethodchoosedialog";
72 constexpr const char *SELECT_DIALOG_ABILITY = "InputMethod";
73 constexpr const char *IME_MIRROR_CAP_NAME = "ime_mirror";
74 #ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE
75 constexpr const char *UNLOAD_SA_TASK = "unloadInputMethodSaTask";
76 constexpr int64_t DELAY_UNLOAD_SA_TIME = 20000; // 20s
77 constexpr int32_t REFUSE_UNLOAD_DELAY_TIME = 1000; // 1s
78 #endif
79 const constexpr char *IMMERSIVE_EFFECT_CAP_NAME = "immersive_effect";
InputMethodSystemAbility(int32_t systemAbilityId,bool runOnCreate)80 InputMethodSystemAbility::InputMethodSystemAbility(int32_t systemAbilityId, bool runOnCreate)
81     : SystemAbility(systemAbilityId, runOnCreate), state_(ServiceRunningState::STATE_NOT_START)
82 {
83 }
84 
InputMethodSystemAbility()85 InputMethodSystemAbility::InputMethodSystemAbility() : state_(ServiceRunningState::STATE_NOT_START)
86 {
87 }
88 
~InputMethodSystemAbility()89 InputMethodSystemAbility::~InputMethodSystemAbility()
90 {
91     stop_ = true;
92     Message *msg = new (std::nothrow) Message(MessageID::MSG_ID_QUIT_WORKER_THREAD, nullptr);
93     if (msg == nullptr) {
94         IMSA_HILOGE("new Message failed");
95         return;
96     }
97     auto handler = MessageHandler::Instance();
98     if (handler == nullptr) {
99         IMSA_HILOGE("handler is nullptr");
100         delete msg;
101         return;
102     }
103     handler->SendMessage(msg);
104     if (workThreadHandler.joinable()) {
105         workThreadHandler.join();
106     }
107 }
108 
109 #ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE
GetTickCount()110 int64_t InputMethodSystemAbility::GetTickCount()
111 {
112     auto now = std::chrono::steady_clock::now();
113     auto durationSinceEpoch = now.time_since_epoch();
114     return std::chrono::duration_cast<std::chrono::milliseconds>(durationSinceEpoch).count();
115 }
ResetDelayUnloadTask(uint32_t code)116 void InputMethodSystemAbility::ResetDelayUnloadTask(uint32_t code)
117 {
118     auto task = [this]() {
119         IMSA_HILOGI("start unload task");
120         auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
121         if (session != nullptr) {
122             session->TryUnloadSystemAbility();
123         }
124     };
125 
126     static std::mutex lastPostTimeLock;
127     std::lock_guard<std::mutex> lock(lastPostTimeLock);
128     static int64_t lastPostTime = 0;
129     if (code == static_cast<uint32_t>(IInputMethodSystemAbilityIpcCode::COMMAND_RELEASE_INPUT) ||
130         code == static_cast<uint32_t>(IInputMethodSystemAbilityIpcCode::COMMAND_REQUEST_HIDE_INPUT)) {
131         if (lastPostTime != 0 && (GetTickCount() - lastPostTime) < DELAY_UNLOAD_SA_TIME) {
132             IMSA_HILOGD("no need post unload task repeat");
133             return;
134         }
135     }
136 
137     if (serviceHandler_ == nullptr) {
138         IMSA_HILOGE("serviceHandler_ is nullptr code:%{public}u", code);
139         return;
140     }
141 
142     serviceHandler_->RemoveTask(std::string(UNLOAD_SA_TASK));
143     IMSA_HILOGD("post unload task");
144     lastPostTime = GetTickCount();
145     bool ret = serviceHandler_->PostTask(task, std::string(UNLOAD_SA_TASK), DELAY_UNLOAD_SA_TIME);
146     if (!ret) {
147         IMSA_HILOGE("post unload task fail code:%{public}u", code);
148     }
149 }
IsImeInUse()150 bool InputMethodSystemAbility::IsImeInUse()
151 {
152     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
153     if (session == nullptr) {
154         IMSA_HILOGE("session is nullptr userId: %{public}d", userId_);
155         return false;
156     }
157 
158     auto data = session->GetReadyImeData(ImeType::IME);
159     if (data == nullptr || data->imeStateManager == nullptr) {
160         IMSA_HILOGE("data or imeStateManager is nullptr");
161         return false;
162     }
163     return data->imeStateManager->IsImeInUse();
164 }
165 #endif
166 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)167 int32_t InputMethodSystemAbility::OnRemoteRequest(
168     uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
169 {
170 #ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE
171     OnDemandStartStopSa::IncreaseProcessingIpcCnt();
172 #endif
173     if (code != static_cast<uint32_t>(IInputMethodSystemAbilityIpcCode::COMMAND_RELEASE_INPUT)) {
174         IMSA_HILOGI("IMSA, code = %{public}u, callingPid/Uid/timestamp: %{public}d/%{public}d/%{public}lld", code,
175             IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(),
176             std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
177                 .count());
178     }
179     auto id = XCollie::GetInstance().SetTimer("IMSA_API[" + std::to_string(code) + "]", FATAL_TIMEOUT, nullptr,
180     nullptr, XCOLLIE_FLAG_DEFAULT);
181     int64_t startPoint = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
182     auto ret = InputMethodSystemAbilityStub::OnRemoteRequest(code, data, reply, option);
183     int64_t costTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count() - startPoint;
184     // log warning when timeout 5s
185     if (costTime > WARNING_TIMEOUT) {
186     IMSA_HILOGW("code: %{public}d, pid: %{public}d, uid: %{public}d, cost: %{public}" PRId64 "", code,
187         IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid(), costTime);
188     }
189     XCollie::GetInstance().CancelTimer(id);
190 #ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE
191     OnDemandStartStopSa::DecreaseProcessingIpcCnt();
192     ResetDelayUnloadTask(code);
193 #endif
194     return ret;
195 }
196 // LCOV_EXCL_START
OnStart()197 void InputMethodSystemAbility::OnStart()
198 {
199     IMSA_HILOGI("InputMethodSystemAbility::OnStart start.");
200     if (!InputMethodSysEvent::GetInstance().StartTimerForReport()) {
201         IMSA_HILOGE("start sysevent timer failed!");
202     }
203     if (state_ == ServiceRunningState::STATE_RUNNING) {
204         IMSA_HILOGI("imsa service is already running.");
205         return;
206     }
207     auto id = HiviewDFX::XCollie::GetInstance().SetTimer(
208         "IMSA OnStart timeout", START_SA_TIMEOUT, nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_DEFAULT);
209     InitServiceHandler();
210     Initialize();
211     int32_t ret = Init();
212     if (ret != ErrorCode::NO_ERROR) {
213         InputMethodSysEvent::GetInstance().ServiceFaultReporter("imf", ret);
214         auto callback = [=]() { Init(); };
215         if (serviceHandler_ == nullptr) {
216             IMSA_HILOGE("serviceHandler_ is nullptr!");
217         } else {
218             serviceHandler_->PostTask(callback, INIT_INTERVAL);
219         }
220         IMSA_HILOGE("init failed. try again 10s later!");
221     }
222     HiviewDFX::XCollie::GetInstance().CancelTimer(id);
223     InitHiTrace();
224     InputMethodSyncTrace tracer("InputMethodController Attach trace.");
225     InputmethodDump::GetInstance().AddDumpAllMethod([this](int fd) { this->DumpAllMethod(fd); });
226     IMSA_HILOGI("start imsa service success.");
227     return;
228 }
229 // LCOV_EXCL_STOP
IsValidBundleName(const std::string & bundleName)230 bool InputMethodSystemAbility::IsValidBundleName(const std::string &bundleName)
231 {
232     if (bundleName.empty()) {
233         IMSA_HILOGE("bundleName is empty.");
234         return false;
235     }
236     std::vector<Property> props;
237     auto ret = ListInputMethod(InputMethodStatus::ALL, props);
238     if (ret != ErrorCode::NO_ERROR) {
239         IMSA_HILOGE("ListInputMethod failed, ret=%{public}d", ret);
240         return false;
241     }
242 
243     return std::any_of(props.begin(), props.end(), [&bundleName](const auto &prop) {
244         return prop.name == bundleName;
245     });
246 }
247 // LCOV_EXCL_START
GetRestoreBundleName(MessageParcel & data)248 std::string InputMethodSystemAbility::GetRestoreBundleName(MessageParcel &data)
249 {
250     std::string jsonString = data.ReadString();
251     if (jsonString.empty()) {
252         IMSA_HILOGE("jsonString is empty.");
253         return "";
254     }
255     IMSA_HILOGI("restore jsonString=%{public}s", jsonString.c_str());
256 
257     cJSON *root = cJSON_Parse(jsonString.c_str());
258     if (root == NULL) {
259         IMSA_HILOGE("cJSON_Parse fail");
260         return "";
261     }
262     std::string bundleName = "";
263     cJSON *item = NULL;
264     cJSON_ArrayForEach(item, root)
265     {
266         cJSON *type = cJSON_GetObjectItem(item, "type");
267         cJSON *detail = cJSON_GetObjectItem(item, "detail");
268         if (type == NULL || detail == NULL || type->valuestring == NULL || detail->valuestring == NULL) {
269             IMSA_HILOGE("type or detail is null");
270             continue;
271         }
272 
273         if (strcmp(type->valuestring, "default_input_method") == 0) {
274             bundleName = std::string(detail->valuestring);
275             break;
276         }
277     }
278     cJSON_Delete(root);
279     return bundleName;
280 }
281 
RestoreInputmethod(std::string & bundleName)282 int32_t InputMethodSystemAbility::RestoreInputmethod(std::string &bundleName)
283 {
284     Property propertyData;
285     GetCurrentInputMethod(propertyData);
286     auto prop = std::make_shared<Property>(propertyData);
287     std::string currentInputMethod = prop->name;
288     if (currentInputMethod == bundleName) {
289         IMSA_HILOGW("currentInputMethod=%{public}s, has been set", currentInputMethod.c_str());
290         return ErrorCode::NO_ERROR;
291     }
292 
293     int32_t userId = GetCallingUserId();
294     auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultIme();
295     if (defaultIme.bundleName != bundleName) {
296         auto result = EnableIme(userId, bundleName);
297         if (result != ErrorCode::NO_ERROR) {
298             IMSA_HILOGE("EnableIme failed");
299             return ErrorCode::ERROR_ENABLE_IME;
300         }
301     }
302 
303     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
304     if (session == nullptr) {
305         IMSA_HILOGE("session[ userId=%{public}d ] is nullptr", userId);
306         return ErrorCode::ERROR_NULL_POINTER;
307     }
308     SwitchInfo switchInfo = { std::chrono::system_clock::now(), bundleName, "" };
309     switchInfo.timestamp = std::chrono::system_clock::now();
310     session->GetSwitchQueue().Push(switchInfo);
311     auto ret = OnSwitchInputMethod(userId, switchInfo, SwitchTrigger::IMSA);
312     if (ret != ErrorCode::NO_ERROR) {
313         IMSA_HILOGE("SwitchInputMethod failed, ret=%{public}d.", ret);
314         return ret;
315     }
316     IMSA_HILOGI("restore success");
317     return ErrorCode::NO_ERROR;
318 }
319 
OnExtension(const std::string & extension,MessageParcel & data,MessageParcel & reply)320 int32_t InputMethodSystemAbility::OnExtension(const std::string &extension, MessageParcel &data, MessageParcel &reply)
321 {
322     IMSA_HILOGI("extension=%{public}s", extension.c_str());
323     if (extension == "restore") {
324         int32_t fd = data.ReadFileDescriptor();
325         if (fd >= 0) {
326             close(fd);
327         }
328         std::string bundleName = GetRestoreBundleName(data);
329         if (!IsValidBundleName(bundleName)) {
330             IMSA_HILOGE("bundleName=%{public}s is invalid", bundleName.c_str());
331             return ErrorCode::ERROR_BAD_PARAMETERS;
332         }
333 
334         return RestoreInputmethod(bundleName);
335     }
336     return 0;
337 }
338 // LCOV_EXCL_STOP
Dump(int fd,const std::vector<std::u16string> & args)339 int InputMethodSystemAbility::Dump(int fd, const std::vector<std::u16string> &args)
340 {
341     IMSA_HILOGD("InputMethodSystemAbility::Dump start.");
342     std::vector<std::string> argsStr;
343     for (auto item : args) {
344         argsStr.emplace_back(Str16ToStr8(item));
345     }
346     InputmethodDump::GetInstance().Dump(fd, argsStr);
347     return ERR_OK;
348 }
349 
DumpAllMethod(int fd)350 void InputMethodSystemAbility::DumpAllMethod(int fd)
351 {
352     IMSA_HILOGD("InputMethodSystemAbility::DumpAllMethod start.");
353     auto ids = OsAccountAdapter::QueryActiveOsAccountIds();
354     if (ids.empty()) {
355         dprintf(fd, "\n - InputMethodSystemAbility::DumpAllMethod get Active Id failed.\n");
356         return;
357     }
358     dprintf(fd, "\n - DumpAllMethod get Active Id succeed,count=%zu,", ids.size());
359     for (auto id : ids) {
360         const auto &params = ImeInfoInquirer::GetInstance().GetDumpInfo(id);
361         if (params.empty()) {
362             IMSA_HILOGD("userId: %{public}d the IME properties is empty.", id);
363             dprintf(fd, "\n - The IME properties about the Active Id %d is empty.\n", id);
364             continue;
365         }
366         dprintf(fd, "\n - The Active Id:%d get input method:\n%s\n", id, params.c_str());
367     }
368     IMSA_HILOGD("InputMethodSystemAbility::DumpAllMethod end.");
369 }
370 // LCOV_EXCL_START
Init()371 int32_t InputMethodSystemAbility::Init()
372 {
373     IMSA_HILOGI("publish start");
374 #ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE
375     ImeCfgManager::GetInstance().Init();
376     ImeInfoInquirer::GetInstance().InitSystemConfig();
377     bool isSuccess = Publish(this);
378     if (!isSuccess) {
379         IMSA_HILOGE("publish failed");
380         return -1;
381     }
382     state_ = ServiceRunningState::STATE_RUNNING;
383     IMSA_HILOGI("publish success");
384 #else
385     bool isSuccess = Publish(this);
386     if (!isSuccess) {
387         IMSA_HILOGE("publish failed");
388         return -1;
389     }
390     IMSA_HILOGI("publish success");
391     state_ = ServiceRunningState::STATE_RUNNING;
392     ImeInfoInquirer::GetInstance().InitSystemConfig();
393     ImeStateManagerFactory::GetInstance().SetDynamicStartIme(ImeInfoInquirer::GetInstance().IsDynamicStartIme());
394 #endif
395     InitMonitors();
396     return ErrorCode::NO_ERROR;
397 }
398 // LCOV_EXCL_STOP
UpdateUserInfo(int32_t userId)399 void InputMethodSystemAbility::UpdateUserInfo(int32_t userId)
400 {
401     IMSA_HILOGI("%{public}d switch to %{public}d.", userId_, userId);
402     userId_ = userId;
403     UserSessionManager::GetInstance().AddUserSession(userId_);
404     InputMethodSysEvent::GetInstance().SetUserId(userId_);
405     NumkeyAppsManager::GetInstance().OnUserSwitched(userId_);
406 }
407 // LCOV_EXCL_START
OnIdle(const SystemAbilityOnDemandReason & idleReason)408 int32_t InputMethodSystemAbility::OnIdle(const SystemAbilityOnDemandReason &idleReason)
409 {
410     IMSA_HILOGI("OnIdle start.");
411     (void)idleReason;
412 #ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE
413     if (OnDemandStartStopSa::IsSaBusy() || IsImeInUse()) {
414         IMSA_HILOGW("sa is busy, refuse stop imsa.");
415         return REFUSE_UNLOAD_DELAY_TIME;
416     }
417 #endif
418     return 0;
419 }
420 
OnStop()421 void InputMethodSystemAbility::OnStop()
422 {
423     IMSA_HILOGI("OnStop start.");
424     ImeStateManager::SetEventHandler(nullptr);
425     ImeCfgManager::GetInstance().SetEventHandler(nullptr);
426     UserSessionManager::GetInstance().SetEventHandler(nullptr);
427     ImeEnabledInfoManager::GetInstance().SetEventHandler(nullptr);
428     serviceHandler_ = nullptr;
429     state_ = ServiceRunningState::STATE_NOT_START;
430     Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 0, INPUT_METHOD_SYSTEM_ABILITY_ID);
431     SettingsDataUtils::GetInstance().Release();
432 }
433 // LCOV_EXCL_STOP
InitServiceHandler()434 void InputMethodSystemAbility::InitServiceHandler()
435 {
436     IMSA_HILOGI("InitServiceHandler start.");
437     if (serviceHandler_ != nullptr) {
438         IMSA_HILOGE("InputMethodSystemAbility already init!");
439         return;
440     }
441     std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("OS_InputMethodSystemAbility");
442     serviceHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
443     ImeStateManager::SetEventHandler(serviceHandler_);
444     ImeEnabledInfoManager::GetInstance().SetEventHandler(serviceHandler_);
445     IMSA_HILOGI("InitServiceHandler succeeded.");
446 }
447 
448 /**
449  * Initialization of Input method management service
450  * \n It's called after the service starts, before any transaction.
451  */
Initialize()452 void InputMethodSystemAbility::Initialize()
453 {
454     IMSA_HILOGI("InputMethodSystemAbility::Initialize.");
455     // init work thread to handle the messages
456     workThreadHandler = std::thread([this] { this->WorkThread(); });
457     identityChecker_ = std::make_shared<IdentityCheckerImpl>();
458     userId_ = OsAccountAdapter::MAIN_USER_ID;
459     UserSessionManager::GetInstance().SetEventHandler(serviceHandler_);
460     ImeCfgManager::GetInstance().SetEventHandler(serviceHandler_);
461     UserSessionManager::GetInstance().AddUserSession(userId_);
462     InputMethodSysEvent::GetInstance().SetUserId(userId_);
463     IMSA_HILOGI("start get scene board enable status");
464     ImeEnabledInfoManager::GetInstance().SetCurrentImeStatusChangedHandler(
465         [this](int32_t userId, const std::string &bundleName, EnabledStatus newStatus) {
466             OnCurrentImeStatusChanged(userId, bundleName, newStatus);
467         });
468     isScbEnable_.store(Rosen::SceneBoardJudgement::IsSceneBoardEnabled());
469     IMSA_HILOGI("Initialize end");
470 }
471 
RestartSessionIme(std::shared_ptr<PerUserSession> & session)472 void InputMethodSystemAbility::RestartSessionIme(std::shared_ptr<PerUserSession> &session)
473 {
474     if (session == nullptr) {
475         UserSessionManager::GetInstance().AddUserSession(userId_);
476     }
477     session = UserSessionManager::GetInstance().GetUserSession(userId_);
478     if (session == nullptr) {
479         IMSA_HILOGE("%{public}d session is nullptr!", userId_);
480         return;
481     }
482 #ifndef IMF_ON_DEMAND_START_STOP_SA_ENABLE
483     if (!ImeStateManagerFactory::GetInstance().GetDynamicStartIme()) {
484         session->AddRestartIme();
485     }
486 #endif
487     StopImeInBackground();
488 }
489 // LCOV_EXCL_START
GetSessionFromMsg(const Message * msg)490 std::shared_ptr<PerUserSession> InputMethodSystemAbility::GetSessionFromMsg(const Message *msg)
491 {
492     if (msg == nullptr || msg->msgContent_ == nullptr) {
493         IMSA_HILOGE("Aborted! Message is nullptr!");
494         return nullptr;
495     }
496     auto userId = msg->msgContent_->ReadInt32();
497     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
498     if (session == nullptr) {
499         IMSA_HILOGE("%{public}d session is nullptr!", userId);
500         return nullptr;
501     }
502     return session;
503 }
504 // LCOV_EXCL_STOP
PrepareForOperateKeyboard(std::shared_ptr<PerUserSession> & session)505 int32_t InputMethodSystemAbility::PrepareForOperateKeyboard(std::shared_ptr<PerUserSession> &session)
506 {
507     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
508     auto userId = GetCallingUserId();
509     session = UserSessionManager::GetInstance().GetUserSession(userId);
510     if (session == nullptr) {
511         IMSA_HILOGE("%{public}d session is nullptr!", userId);
512         return ErrorCode::ERROR_NULL_POINTER;
513     }
514     if (!identityChecker_->IsBroker(tokenId)) {
515         if (!identityChecker_->IsFocused(
516             IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid(GetCallingDisplayId()))) {
517             return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
518         }
519     }
520     return ErrorCode::NO_ERROR;
521 }
522 // LCOV_EXCL_START
SwitchByCondition(const Condition & condition,const std::shared_ptr<ImeInfo> & info)523 int32_t InputMethodSystemAbility::SwitchByCondition(const Condition &condition,
524     const std::shared_ptr<ImeInfo> &info)
525 {
526     if (info == nullptr) {
527         IMSA_HILOGE("info is nullptr!");
528         return ErrorCode::ERROR_NULL_POINTER;
529     }
530     auto target = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(info->subProps, condition);
531     if (target == nullptr) {
532         IMSA_HILOGE("target is empty!");
533         return ErrorCode::ERROR_BAD_PARAMETERS;
534     }
535     SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
536     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
537     if (session == nullptr) {
538         IMSA_HILOGE("%{public}d session is nullptr!", userId_);
539         return ErrorCode::ERROR_NULL_POINTER;
540     }
541     session->GetSwitchQueue().Push(switchInfo);
542     return OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
543 }
544 // LCOV_EXCL_STOP
SubscribeCommonEvent()545 void InputMethodSystemAbility::SubscribeCommonEvent()
546 {
547     sptr<ImCommonEventManager> imCommonEventManager = ImCommonEventManager::GetInstance();
548     bool isSuccess = imCommonEventManager->SubscribeEvent();
549     if (isSuccess) {
550         IMSA_HILOGI("initialize subscribe service event success.");
551         return;
552     }
553 
554     IMSA_HILOGE("failed, try again 10s later!");
555     auto callback = [this]() { SubscribeCommonEvent(); };
556     serviceHandler_->PostTask(callback, INIT_INTERVAL);
557 }
558 // LCOV_EXCL_START
PrepareInput(int32_t userId,InputClientInfo & clientInfo)559 int32_t InputMethodSystemAbility::PrepareInput(int32_t userId, InputClientInfo &clientInfo)
560 {
561     InputMethodSyncTrace tracer("InputMethodSystemAbility PrepareInput");
562     auto ret = GenerateClientInfo(userId, clientInfo);
563     if (ret != ErrorCode::NO_ERROR) {
564         return ret;
565     }
566     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
567     if (session == nullptr) {
568         IMSA_HILOGE("%{public}d session is nullptr!", userId);
569         return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND;
570     }
571     return session->OnPrepareInput(clientInfo);
572 }
573 
GenerateClientInfo(int32_t userId,InputClientInfo & clientInfo)574 int32_t InputMethodSystemAbility::GenerateClientInfo(int32_t userId, InputClientInfo &clientInfo)
575 {
576     if (clientInfo.client == nullptr || clientInfo.channel == nullptr) {
577         IMSA_HILOGE("client or channel is nullptr!");
578         return ErrorCode::ERROR_IMSA_NULLPTR;
579     }
580     auto deathRecipient = new (std::nothrow) InputDeathRecipient();
581     if (deathRecipient == nullptr) {
582         IMSA_HILOGE("failed to new deathRecipient!");
583         return ErrorCode::ERROR_IMSA_MALLOC_FAILED;
584     }
585     clientInfo.pid = IPCSkeleton::GetCallingPid();
586     clientInfo.uid = IPCSkeleton::GetCallingUid();
587     clientInfo.displayId = GetCallingDisplayId(clientInfo.config.abilityToken);
588     clientInfo.userID = userId;
589     clientInfo.deathRecipient = deathRecipient;
590     auto tokenId = IPCSkeleton::GetCallingTokenID();
591     if (identityChecker_->IsFocusedUIExtension(tokenId)) {
592         clientInfo.uiExtensionTokenId = tokenId;
593     }
594     auto callingDisplayId = identityChecker_->GetDisplayIdByWindowId(clientInfo.config.windowId);
595     clientInfo.config.privateCommand.insert_or_assign("displayId",
596         PrivateDataValue(static_cast<int32_t>(callingDisplayId)));
597     clientInfo.name = ImfHiSysEventUtil::GetAppName(tokenId);
598     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
599     if (session != nullptr) {
600         auto callingWindowInfo = session->GetCallingWindowInfo(clientInfo);
601         clientInfo.config.inputAttribute.windowId = callingWindowInfo.windowId;
602         clientInfo.config.inputAttribute.callingDisplayId = callingWindowInfo.displayId;
603         clientInfo.config.inputAttribute.needAutoInputNumkey =
604             session->IsNumkeyAutoInputApp(clientInfo.config.inputAttribute.bundleName);
605         IMSA_HILOGD("result:%{public}s,wid:%{public}d", clientInfo.config.inputAttribute.ToString().c_str(),
606             clientInfo.config.windowId);
607     }
608     return ErrorCode::NO_ERROR;
609 }
610 // LCOV_EXCL_STOP
ReleaseInput(const sptr<IInputClient> & client,uint32_t sessionId)611 ErrCode InputMethodSystemAbility::ReleaseInput(const sptr<IInputClient>& client, uint32_t sessionId)
612 {
613     if (client == nullptr) {
614         IMSA_HILOGE("client is nullptr!");
615         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
616     }
617     auto userId = GetCallingUserId();
618     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
619     if (session == nullptr) {
620         IMSA_HILOGE("%{public}d session is nullptr!", userId);
621         return ErrorCode::ERROR_NULL_POINTER;
622     }
623     return session->OnReleaseInput(client, sessionId);
624 }
625 
IncreaseAttachCount()626 void InputMethodSystemAbility::IncreaseAttachCount()
627 {
628     auto userId = GetCallingUserId();
629     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
630     if (session == nullptr) {
631         IMSA_HILOGE("get session failed:%{public}d", userId);
632         return;
633     }
634 
635     session->IncreaseAttachCount();
636 }
637 
DecreaseAttachCount()638 void InputMethodSystemAbility::DecreaseAttachCount()
639 {
640     auto userId = GetCallingUserId();
641     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
642     if (session == nullptr) {
643         IMSA_HILOGE("get session failed:%{public}d", userId);
644         return;
645     }
646 
647     session->DecreaseAttachCount();
648 }
649 
StartInput(const InputClientInfoInner & inputClientInfoInner,std::vector<sptr<IRemoteObject>> & agents,std::vector<BindImeInfo> & imeInfos)650 ErrCode InputMethodSystemAbility::StartInput(const InputClientInfoInner &inputClientInfoInner,
651     std::vector<sptr<IRemoteObject>> &agents, std::vector<BindImeInfo> &imeInfos)
652 {
653     AttachStateGuard guard(*this);
654     InputClientInfo inputClientInfo = InputMethodTools::GetInstance().InnerToInputClientInfo(inputClientInfoInner);
655     auto ret = StartInputInner(inputClientInfo, agents, imeInfos);
656     std::string bundleName = "";
657     if (!imeInfos.empty()) {
658         bundleName = imeInfos[0].bundleName;
659     } else {
660         bundleName = GetCurrentImeInfoForHiSysEvent(GetCallingUserId()).second;
661     }
662     IMSA_HILOGD("HiSysEvent report start!");
663     auto evenInfo = HiSysOriginalInfo::Builder()
664                         .SetPeerName(ImfHiSysEventUtil::GetAppName(IPCSkeleton::GetCallingTokenID()))
665                         .SetPeerPid(IPCSkeleton::GetCallingPid())
666                         .SetPeerUserId(GetCallingUserId())
667                         .SetClientType(inputClientInfo.type)
668                         .SetInputPattern(inputClientInfo.attribute.inputPattern)
669                         .SetIsShowKeyboard(inputClientInfo.isShowKeyboard)
670                         .SetImeName(bundleName)
671                         .SetErrCode(ret)
672                         .Build();
673     ImsaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_ATTACH, *evenInfo);
674     IMSA_HILOGD("HiSysEvent report end!");
675     return ret;
676 }
677 
StartInputInner(InputClientInfo & inputClientInfo,std::vector<sptr<IRemoteObject>> & agents,std::vector<BindImeInfo> & imeInfos)678 int32_t InputMethodSystemAbility::StartInputInner(
679     InputClientInfo &inputClientInfo, std::vector<sptr<IRemoteObject>> &agents, std::vector<BindImeInfo> &imeInfos)
680 {
681     auto userId = GetCallingUserId();
682     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
683     if (!identityChecker_->IsBroker(tokenId) && !identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId,
684         IdentityChecker::INVALID_PID, true, inputClientInfo.config.abilityToken)) {
685         return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
686     }
687     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
688     if (session == nullptr) {
689         IMSA_HILOGE("%{public}d session is nullptr!", userId);
690         return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND;
691     }
692     auto displayId = GetCallingDisplayId();
693     if (session->GetCurrentClientPid(displayId) != IPCSkeleton::GetCallingPid()
694         && session->GetInactiveClientPid(displayId) != IPCSkeleton::GetCallingPid()) {
695         // notify inputStart when caller pid different from both current client and inactive client
696         inputClientInfo.isNotifyInputStart = true;
697     }
698     if (session->CheckPwdInputPatternConv(inputClientInfo, displayId)) {
699         inputClientInfo.needHide = true;
700         inputClientInfo.isNotifyInputStart = true;
701     }
702     if (session->IsDefaultDisplayGroup(displayId) && !session->IsProxyImeEnable()) {
703         auto ret = CheckInputTypeOption(userId, inputClientInfo);
704         if (ret != ErrorCode::NO_ERROR) {
705             IMSA_HILOGE("%{public}d failed to CheckInputTypeOption!", userId);
706             return ret;
707         }
708     }
709     inputClientInfo.config.inputAttribute.bundleName = identityChecker_->GetBundleNameByToken(tokenId);
710     int32_t ret = PrepareInput(userId, inputClientInfo);
711     if (ret != ErrorCode::NO_ERROR) {
712         IMSA_HILOGE("failed to PrepareInput!");
713         return ret;
714     }
715     session->SetInputType();
716     return session->OnStartInput(inputClientInfo, agents, imeInfos);
717 }
718 
CheckInputTypeOption(int32_t userId,InputClientInfo & inputClientInfo)719 int32_t InputMethodSystemAbility::CheckInputTypeOption(int32_t userId, InputClientInfo &inputClientInfo)
720 {
721     IMSA_HILOGI("SecurityImeFlag: %{public}d, IsSameTextInput: %{public}d, IsStarted: %{public}d.",
722         inputClientInfo.config.inputAttribute.IsSecurityImeFlag(),
723         !inputClientInfo.isNotifyInputStart,
724         InputTypeManager::GetInstance().IsStarted());
725     if (inputClientInfo.config.inputAttribute.IsSecurityImeFlag()) {
726         return StartSecurityIme(userId, inputClientInfo);
727     }
728     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
729     if (session == nullptr) {
730         IMSA_HILOGE("%{public}d session is nullptr!", userId);
731         return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND;
732     }
733     if (!inputClientInfo.isNotifyInputStart && InputTypeManager::GetInstance().IsStarted()) {
734         IMSA_HILOGD("NormalFlag, same textField, input type started, not deal.");
735         return ErrorCode::NO_ERROR;
736     }
737     if (inputClientInfo.isNotifyInputStart && InputTypeManager::GetInstance().IsStarted()) {
738         IMSA_HILOGD("NormalFlag, diff textField, input type started, restore.");
739         session->RestoreCurrentImeSubType(DEFAULT_DISPLAY_ID);
740     }
741 #ifdef IMF_SCREENLOCK_MGR_ENABLE
742     auto screenLockMgr = ScreenLock::ScreenLockManager::GetInstance();
743     if (screenLockMgr != nullptr && screenLockMgr->IsScreenLocked()) {
744         std::string ime;
745         if (GetScreenLockIme(userId, ime) != ErrorCode::NO_ERROR) {
746             IMSA_HILOGE("not ime screenlocked");
747             return ErrorCode::ERROR_IMSA_IME_TO_START_NULLPTR;
748         }
749         ImeCfgManager::GetInstance().ModifyTempScreenLockImeCfg(userId, ime);
750         return session->StartUserSpecifiedIme(DEFAULT_DISPLAY_ID);
751     }
752 #endif
753     if (session->IsPreconfiguredDefaultImeSpecified(inputClientInfo)) {
754         auto [ret, status] = session->StartPreconfiguredDefaultIme(DEFAULT_DISPLAY_ID);
755         return ret;
756     }
757     return session->StartUserSpecifiedIme(DEFAULT_DISPLAY_ID);
758 }
759 
IsRestrictedDefaultImeByDisplay(uint64_t displayId,bool & resultValue)760 ErrCode InputMethodSystemAbility::IsRestrictedDefaultImeByDisplay(uint64_t displayId, bool &resultValue)
761 {
762     resultValue = ImeInfoInquirer::GetInstance().IsRestrictedDefaultImeByDisplay(displayId);
763     return ErrorCode::NO_ERROR;
764 }
765 
ShowInputInner(sptr<IInputClient> client,int32_t requestKeyboardReason)766 int32_t InputMethodSystemAbility::ShowInputInner(sptr<IInputClient> client, int32_t requestKeyboardReason)
767 {
768     std::shared_ptr<PerUserSession> session = nullptr;
769     auto result = PrepareForOperateKeyboard(session);
770     if (result != ErrorCode::NO_ERROR) {
771         return result;
772     }
773     if (client == nullptr) {
774         IMSA_HILOGE("client is nullptr!");
775         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
776     }
777     return session->OnShowInput(client, requestKeyboardReason);
778 }
779 
HideInput(const sptr<IInputClient> & client)780 ErrCode InputMethodSystemAbility::HideInput(const sptr<IInputClient>& client)
781 {
782     std::shared_ptr<PerUserSession> session = nullptr;
783     auto result = PrepareForOperateKeyboard(session);
784     if (result != ErrorCode::NO_ERROR) {
785         return result;
786     }
787     if (client == nullptr) {
788         IMSA_HILOGE("client is nullptr!");
789         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
790     }
791     return session->OnHideInput(client);
792 }
793 
StopInputSession()794 ErrCode InputMethodSystemAbility::StopInputSession()
795 {
796     std::shared_ptr<PerUserSession> session = nullptr;
797     auto result = PrepareForOperateKeyboard(session);
798     if (result != ErrorCode::NO_ERROR) {
799         return result;
800     }
801     return session->OnHideCurrentInput(GetCallingDisplayId());
802 }
803 
RequestShowInput()804 ErrCode InputMethodSystemAbility::RequestShowInput()
805 {
806     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
807     if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId) &&
808         !identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) {
809         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
810     }
811     auto userId = GetCallingUserId();
812     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
813     if (session == nullptr) {
814         IMSA_HILOGE("%{public}d session is nullptr!", userId);
815         return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND;
816     }
817     return session->OnRequestShowInput(GetCallingDisplayId());
818 }
819 
RequestHideInput(bool isFocusTriggered)820 ErrCode InputMethodSystemAbility::RequestHideInput(bool isFocusTriggered)
821 {
822     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
823     auto pid = IPCSkeleton::GetCallingPid();
824     if (isFocusTriggered) {
825         if (!identityChecker_->IsFocused(pid, tokenId)) {
826             return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
827         }
828     } else {
829         if (!identityChecker_->IsFocused(pid, tokenId) &&
830             !identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) {
831             return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
832         }
833     }
834     auto userId = GetCallingUserId();
835     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
836     if (session == nullptr) {
837         IMSA_HILOGE("%{public}d session is nullptr!", userId);
838         return ErrorCode::ERROR_NULL_POINTER;
839     }
840     return session->OnRequestHideInput(pid, GetCallingDisplayId());
841 }
842 
SetCoreAndAgent(const sptr<IInputMethodCore> & core,const sptr<IRemoteObject> & agent)843 ErrCode InputMethodSystemAbility::SetCoreAndAgent(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
844 {
845     IMSA_HILOGD("InputMethodSystemAbility start.");
846     auto pid = IPCSkeleton::GetCallingPid();
847     auto userId = GetCallingUserId();
848     auto tokenId = GetCallingTokenID();
849     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
850     if (session == nullptr) {
851         IMSA_HILOGE("%{public}d session is nullptr!", userId);
852         return ErrorCode::ERROR_NULL_POINTER;
853     }
854     if (identityChecker_->IsValidVirtualIme(IPCSkeleton::GetCallingUid())) {
855         return session->OnRegisterProxyIme(core, agent, pid);
856     }
857     if (!IsCurrentIme(userId, tokenId)) {
858         IMSA_HILOGE("not current ime, userId:%{public}d", userId);
859         return ErrorCode::ERROR_NOT_CURRENT_IME;
860     }
861     return session->OnSetCoreAndAgent(core, agent);
862 }
863 
RegisterProxyIme(uint64_t displayId,const sptr<IInputMethodCore> & core,const sptr<IRemoteObject> & agent)864 ErrCode InputMethodSystemAbility::RegisterProxyIme(
865     uint64_t displayId, const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
866 {
867     if (!ImeInfoInquirer::GetInstance().IsEnableAppAgent()) {
868         IMSA_HILOGE("current device does not support app agent");
869         return ErrorCode::ERROR_DEVICE_UNSUPPORTED;
870     }
871     if (!identityChecker_->IsValidVirtualIme(IPCSkeleton::GetCallingUid())) {
872         IMSA_HILOGE("not agent sa");
873         return ErrorCode::ERROR_NOT_AI_APP_IME;
874     }
875     auto userId = GetCallingUserId();
876     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
877     if (session == nullptr) {
878         IMSA_HILOGE("%{public}d session is nullptr!", userId);
879         return ErrorCode::ERROR_NULL_POINTER;
880     }
881     return session->OnRegisterProxyIme(displayId, core, agent);
882 }
883 
UnregisterProxyIme(uint64_t displayId)884 ErrCode InputMethodSystemAbility::UnregisterProxyIme(uint64_t displayId)
885 {
886     if (!ImeInfoInquirer::GetInstance().IsEnableAppAgent()) {
887         IMSA_HILOGE("current device does not support app agent");
888         return ErrorCode::ERROR_DEVICE_UNSUPPORTED;
889     }
890     if (!identityChecker_->IsValidVirtualIme(IPCSkeleton::GetCallingUid())) {
891         IMSA_HILOGE("not agent sa");
892         return ErrorCode::ERROR_NOT_AI_APP_IME;
893     }
894     auto userId = GetCallingUserId();
895     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
896     if (session == nullptr) {
897         IMSA_HILOGE("%{public}d session is nullptr!", userId);
898         return ErrorCode::ERROR_NULL_POINTER;
899     }
900     return session->OnUnregisterProxyIme(displayId);
901 }
902 
BindImeMirror(const sptr<IInputMethodCore> & core,const sptr<IRemoteObject> & agent)903 ErrCode InputMethodSystemAbility::BindImeMirror(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
904 {
905     if (identityChecker_ == nullptr) {
906         IMSA_HILOGE("identityChecker_ is nullptr!");
907         return ErrorCode::ERROR_NULL_POINTER;
908     }
909 
910     if (!ImeInfoInquirer::GetInstance().IsCapacitySupport(IME_MIRROR_CAP_NAME)) {
911         IMSA_HILOGE("ime_mirror is not supported");
912         return ErrorCode::ERROR_DEVICE_UNSUPPORTED;
913     }
914 
915     if (!identityChecker_->IsValidVirtualIme(IPCSkeleton::GetCallingUid())) {
916         IMSA_HILOGE("not agent sa");
917         return ErrorCode::ERROR_NOT_AI_APP_IME;
918     }
919     auto userId = GetCallingUserId();
920     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
921     if (session == nullptr) {
922         IMSA_HILOGE("%{public}d session is nullptr!", userId);
923         return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND;
924     }
925     return session->OnBindImeMirror(core, agent);
926 }
927 
UnbindImeMirror()928 ErrCode InputMethodSystemAbility::UnbindImeMirror()
929 {
930     if (identityChecker_ == nullptr) {
931         IMSA_HILOGE("identityChecker_ is nullptr!");
932         return ErrorCode::ERROR_NULL_POINTER;
933     }
934     if (!ImeInfoInquirer::GetInstance().IsCapacitySupport(IME_MIRROR_CAP_NAME)) {
935         IMSA_HILOGE("ime_mirror is not supported");
936         return ErrorCode::ERROR_DEVICE_UNSUPPORTED;
937     }
938     if (!identityChecker_->IsValidVirtualIme(IPCSkeleton::GetCallingUid())) {
939         IMSA_HILOGE("not agent sa");
940         return ErrorCode::ERROR_NOT_AI_APP_IME;
941     }
942     auto userId = GetCallingUserId();
943     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
944     if (session == nullptr) {
945         IMSA_HILOGE("%{public}d session is nullptr!", userId);
946         return ErrorCode::ERROR_NULL_POINTER;
947     }
948     return session->OnUnbindImeMirror();
949 }
950 
InitConnect()951 ErrCode InputMethodSystemAbility::InitConnect()
952 {
953     IMSA_HILOGD("InputMethodSystemAbility init connect.");
954     auto userId = GetCallingUserId();
955     auto tokenId = GetCallingTokenID();
956     auto pid = IPCSkeleton::GetCallingPid();
957     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
958     if (session == nullptr) {
959         IMSA_HILOGE("%{public}d session is nullptr!", userId);
960         return ErrorCode::ERROR_NULL_POINTER;
961     }
962     if (!IsCurrentIme(userId, tokenId)) {
963         return ErrorCode::ERROR_NOT_CURRENT_IME;
964     }
965     return session->InitConnect(pid);
966 }
967 
HideCurrentInput()968 ErrCode InputMethodSystemAbility::HideCurrentInput()
969 {
970     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
971     auto userId = GetCallingUserId();
972     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
973     if (session == nullptr) {
974         IMSA_HILOGE("%{public}d session is nullptr!", userId);
975         return ErrorCode::ERROR_NULL_POINTER;
976     }
977     if (identityChecker_->IsBroker(tokenId)) {
978         return session->OnHideCurrentInput(GetCallingDisplayId());
979     }
980     if (!identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) {
981         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
982     }
983     return session->OnHideCurrentInput(GetCallingDisplayId());
984 }
985 
ShowCurrentInputInner()986 ErrCode InputMethodSystemAbility::ShowCurrentInputInner()
987 {
988     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
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_IMSA_USER_SESSION_NOT_FOUND;
994     }
995     if (identityChecker_->IsBroker(tokenId)) {
996         return session->OnShowCurrentInput(GetCallingDisplayId());
997     }
998     if (!identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) {
999         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1000     }
1001     return session->OnShowCurrentInput(GetCallingDisplayId());
1002 }
1003 
PanelStatusChange(uint32_t status,const ImeWindowInfo & info)1004 ErrCode InputMethodSystemAbility::PanelStatusChange(uint32_t status, const ImeWindowInfo &info)
1005 {
1006     auto userId = GetCallingUserId();
1007     auto tokenId = GetCallingTokenID();
1008     if (!IsCurrentIme(userId, tokenId)) {
1009         IMSA_HILOGE("not current ime!");
1010         return ErrorCode::ERROR_NOT_CURRENT_IME;
1011     }
1012     auto commonEventManager = ImCommonEventManager::GetInstance();
1013     if (commonEventManager != nullptr) {
1014         auto ret = commonEventManager->PublishPanelStatusChangeEvent(
1015             userId, static_cast<InputWindowStatus>(status), info);
1016         IMSA_HILOGD("public panel status change event: %{public}d", ret);
1017     }
1018     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1019     if (session == nullptr) {
1020         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1021         return ErrorCode::ERROR_NULL_POINTER;
1022     }
1023     return session->OnPanelStatusChange(static_cast<InputWindowStatus>(status), info, GetCallingDisplayId());
1024 }
1025 
UpdateListenEventFlag(const InputClientInfoInner & clientInfoInner,uint32_t eventFlag)1026 ErrCode InputMethodSystemAbility::UpdateListenEventFlag(const InputClientInfoInner &clientInfoInner, uint32_t eventFlag)
1027 {
1028     InputClientInfo clientInfo = InputMethodTools::GetInstance().InnerToInputClientInfo(clientInfoInner);
1029     IMSA_HILOGD("finalEventFlag: %{public}u, eventFlag: %{public}u.", clientInfo.eventFlag, eventFlag);
1030     if (EventStatusManager::IsImeHideOn(eventFlag) || EventStatusManager::IsImeShowOn(eventFlag) ||
1031         EventStatusManager::IsInputStatusChangedOn(eventFlag)) {
1032         if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) &&
1033             !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
1034             IMSA_HILOGE("not system application!");
1035             return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
1036         }
1037     }
1038     auto userId = GetCallingUserId();
1039     auto ret = GenerateClientInfo(userId, const_cast<InputClientInfo &>(clientInfo));
1040     if (ret != ErrorCode::NO_ERROR) {
1041         return ret;
1042     }
1043     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1044     if (session == nullptr) {
1045         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1046         return ErrorCode::ERROR_NULL_POINTER;
1047     }
1048     return session->OnUpdateListenEventFlag(clientInfo);
1049 }
1050 // LCOV_EXCL_START
SetCallingWindow(uint32_t windowId,const sptr<IInputClient> & client)1051 ErrCode InputMethodSystemAbility::SetCallingWindow(uint32_t windowId, const sptr<IInputClient>& client)
1052 {
1053     IMSA_HILOGD("IMF SA setCallingWindow enter");
1054     if (identityChecker_ == nullptr) {
1055         return ErrorCode::ERROR_NULL_POINTER;
1056     }
1057     AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
1058     if (!identityChecker_->IsBroker(tokenId) &&
1059         !identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)) {
1060         return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
1061     }
1062     auto callingUserId = GetCallingUserId();
1063     auto session = UserSessionManager::GetInstance().GetUserSession(callingUserId);
1064     if (session == nullptr) {
1065         IMSA_HILOGE("%{public}d session is nullptr!", callingUserId);
1066         return ErrorCode::ERROR_NULL_POINTER;
1067     }
1068     auto callingDisplayId = identityChecker_->GetDisplayIdByWindowId(windowId);
1069     return session->OnSetCallingWindow(windowId, callingDisplayId, client);
1070 }
1071 // LCOV_EXCL_STOP
GetInputStartInfo(bool & isInputStart,uint32_t & callingWndId,int32_t & requestKeyboardReason)1072 ErrCode InputMethodSystemAbility::GetInputStartInfo(bool& isInputStart,
1073     uint32_t& callingWndId, int32_t &requestKeyboardReason)
1074 {
1075     if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
1076         IMSA_HILOGE("not native sa!");
1077         return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
1078     }
1079     auto callingUserId = GetCallingUserId();
1080     auto session = UserSessionManager::GetInstance().GetUserSession(callingUserId);
1081     if (session == nullptr) {
1082         IMSA_HILOGE("%{public}d session is nullptr!", callingUserId);
1083         return false;
1084     }
1085     return session->GetInputStartInfo(GetCallingDisplayId(), isInputStart, callingWndId, requestKeyboardReason);
1086 }
1087 
IsCurrentIme(bool & resultValue)1088 ErrCode InputMethodSystemAbility::IsCurrentIme(bool& resultValue)
1089 {
1090     auto userId = GetCallingUserId();
1091     auto tokenId = GetCallingTokenID();
1092     resultValue = IsCurrentIme(userId, tokenId);
1093     return ERR_OK;
1094 }
1095 
IsInputTypeSupported(int32_t type,bool & resultValue)1096 ErrCode InputMethodSystemAbility::IsInputTypeSupported(int32_t type, bool &resultValue)
1097 {
1098     resultValue = InputTypeManager::GetInstance().IsSupported(static_cast<InputType>(type));
1099     return ERR_OK;
1100 }
1101 
StartInputType(int32_t type)1102 ErrCode InputMethodSystemAbility::StartInputType(int32_t type)
1103 {
1104     return StartInputType(GetCallingUserId(), static_cast<InputType>(type));
1105 }
1106 
StartInputTypeAsync(int32_t type)1107 ErrCode InputMethodSystemAbility::StartInputTypeAsync(int32_t type)
1108 {
1109     return StartInputType(GetCallingUserId(), static_cast<InputType>(type));
1110 }
1111 
ExitCurrentInputType()1112 ErrCode InputMethodSystemAbility::ExitCurrentInputType()
1113 {
1114     auto userId = GetCallingUserId();
1115     auto ret = IsDefaultImeFromTokenId(userId, IPCSkeleton::GetCallingTokenID());
1116     if (ret != ErrorCode::NO_ERROR) {
1117         IMSA_HILOGE("not default ime!");
1118         return ErrorCode::ERROR_NOT_DEFAULT_IME;
1119     }
1120     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1121     if (session == nullptr) {
1122         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1123         return ErrorCode::ERROR_NULL_POINTER;
1124     }
1125     InputTypeManager::GetInstance().Set(false);
1126     return session->StartCurrentIme();
1127 }
1128 
IsDefaultIme()1129 ErrCode InputMethodSystemAbility::IsDefaultIme()
1130 {
1131     return IsDefaultImeFromTokenId(GetCallingUserId(), IPCSkeleton::GetCallingTokenID());
1132 }
1133 
IsSystemApp(bool & resultValue)1134 ErrCode InputMethodSystemAbility::IsSystemApp(bool& resultValue)
1135 {
1136     resultValue = identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID());
1137     return ERR_OK;
1138 }
1139 // LCOV_EXCL_START
IsCapacitySupport(int32_t capacity,bool & isSupport)1140 ErrCode InputMethodSystemAbility::IsCapacitySupport(int32_t capacity, bool &isSupport)
1141 {
1142     IMSA_HILOGI("capacity:%{public}d", capacity);
1143     if (capacity != static_cast<int32_t>(CapacityType::IMMERSIVE_EFFECT)) {
1144         IMSA_HILOGE("capacity is invalid!");
1145         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
1146     }
1147 
1148     isSupport = ImeInfoInquirer::GetInstance().IsCapacitySupport(IMMERSIVE_EFFECT_CAP_NAME);
1149     return ERR_OK;
1150 }
1151 // LCOV_EXCL_STOP
IsDefaultImeFromTokenId(int32_t userId,uint32_t tokenId)1152 int32_t InputMethodSystemAbility::IsDefaultImeFromTokenId(int32_t userId, uint32_t tokenId)
1153 {
1154     auto prop = std::make_shared<Property>();
1155     auto ret = ImeInfoInquirer::GetInstance().GetDefaultInputMethod(userId, prop, true);
1156     if (ret != ErrorCode::NO_ERROR || prop == nullptr) {
1157         IMSA_HILOGE("failed to get default ime!");
1158         return ErrorCode::ERROR_PERSIST_CONFIG;
1159     }
1160     if (!identityChecker_->IsBundleNameValid(tokenId, prop->name)) {
1161         return ErrorCode::ERROR_NOT_DEFAULT_IME;
1162     }
1163     return ErrorCode::NO_ERROR;
1164 }
1165 
IsCurrentImeByPid(int32_t pid,bool & resultValue)1166 ErrCode InputMethodSystemAbility::IsCurrentImeByPid(int32_t pid, bool& resultValue)
1167 {
1168     if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) &&
1169         !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
1170         IMSA_HILOGE("not system application or system ability!");
1171         resultValue = false;
1172         return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
1173     }
1174     auto userId = GetCallingUserId();
1175     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1176     if (session == nullptr) {
1177         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1178         resultValue = false;
1179         return ErrorCode::ERROR_NULL_POINTER;
1180     }
1181     resultValue = session->IsCurrentImeByPid(pid);
1182     return ERR_OK;
1183 }
1184 
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)1185 int32_t InputMethodSystemAbility::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
1186 {
1187     if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
1188         IMSA_HILOGE("not system application!");
1189         return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
1190     }
1191     auto userId = GetCallingUserId();
1192     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1193     if (session == nullptr) {
1194         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1195         return ErrorCode::ERROR_NULL_POINTER;
1196     }
1197     return session->IsPanelShown(panelInfo, isShown);
1198 }
1199 
DisplayOptionalInputMethod()1200 int32_t InputMethodSystemAbility::DisplayOptionalInputMethod()
1201 {
1202     IMSA_HILOGD("InputMethodSystemAbility start.");
1203     return OnDisplayOptionalInputMethod();
1204 }
1205 
SwitchInputMethod(const std::string & bundleName,const std::string & subName,uint32_t trigger)1206 ErrCode InputMethodSystemAbility::SwitchInputMethod(const std::string &bundleName,
1207     const std::string &subName, uint32_t trigger)
1208 {
1209     // IMSA not check permission, add this verify for prevent counterfeit
1210     if (static_cast<SwitchTrigger>(trigger) == SwitchTrigger::IMSA) {
1211         IMSA_HILOGW("caller counterfeit!");
1212         return ErrorCode::ERROR_BAD_PARAMETERS;
1213     }
1214     int32_t userId = GetCallingUserId();
1215     auto tokenId = GetCallingTokenID();
1216     SwitchInfo switchInfo = { std::chrono::system_clock::now(), bundleName, subName };
1217     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1218     if (session == nullptr) {
1219         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1220         return ErrorCode::ERROR_NULL_POINTER;
1221     }
1222     EnabledStatus status = EnabledStatus::DISABLED;
1223     auto ret = ImeEnabledInfoManager::GetInstance().GetEnabledState(userId, bundleName, status);
1224     if (ret != ErrorCode::NO_ERROR || status == EnabledStatus::DISABLED) {
1225         IMSA_HILOGW("ime %{public}s not enable, stopped!", bundleName.c_str());
1226         return ErrorCode::ERROR_ENABLE_IME;
1227     }
1228     if (identityChecker_->IsFormShell(IPCSkeleton::GetCallingFullTokenID()) && session->IsImeSwitchForbidden()) {
1229         IMSA_HILOGE("ime switch is forbidden, can not switch input method");
1230         return ErrorCode::ERROR_SWITCH_IME;
1231     }
1232     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
1233     if (switchInfo.subName.empty() && switchInfo.bundleName == currentImeCfg->bundleName) {
1234         switchInfo.subName = currentImeCfg->subName;
1235     }
1236     switchInfo.timestamp = std::chrono::system_clock::now();
1237     switchInfo.isTmpImeSwitchSubtype = IsTmpImeSwitchSubtype(userId, tokenId, switchInfo);
1238     session->GetSwitchQueue().Push(switchInfo);
1239     return InputTypeManager::GetInstance().IsInputType({ bundleName, subName })
1240                ? OnStartInputType(userId, switchInfo, true)
1241                : OnSwitchInputMethod(userId, switchInfo, static_cast<SwitchTrigger>(trigger));
1242 }
1243 
EnableIme(const std::string & bundleName,const std::string & extensionName,int32_t status)1244 ErrCode InputMethodSystemAbility::EnableIme(
1245     const std::string &bundleName, const std::string &extensionName, int32_t status)
1246 {
1247     auto ret = CheckEnableAndSwitchPermission();
1248     if (ret != ErrorCode::NO_ERROR) {
1249         IMSA_HILOGE("permission check failed!");
1250         return ret;
1251     }
1252     return EnableIme(GetCallingUserId(), bundleName, extensionName, static_cast<EnabledStatus>(status));
1253 }
1254 
EnableIme(int32_t userId,const std::string & bundleName,const std::string & extensionName,EnabledStatus status)1255 int32_t InputMethodSystemAbility::EnableIme(
1256     int32_t userId, const std::string &bundleName, const std::string &extensionName, EnabledStatus status)
1257 {
1258     return ImeEnabledInfoManager::GetInstance().Update(
1259         userId, bundleName, extensionName, static_cast<EnabledStatus>(status));
1260 }
1261 
StartSwitch(int32_t userId,const SwitchInfo & switchInfo,const std::shared_ptr<PerUserSession> & session)1262 int32_t InputMethodSystemAbility::StartSwitch(int32_t userId, const SwitchInfo &switchInfo,
1263     const std::shared_ptr<PerUserSession> &session)
1264 {
1265     if (session == nullptr) {
1266         IMSA_HILOGE("session nullptr");
1267         return ErrorCode::ERROR_NULL_POINTER;
1268     }
1269     IMSA_HILOGI("start switch %{public}s|%{public}s.", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
1270     auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId, switchInfo.bundleName, switchInfo.subName);
1271     if (info == nullptr) {
1272         return ErrorCode::ERROR_IMSA_GET_IME_INFO_FAILED;
1273     }
1274     InputTypeManager::GetInstance().Set(false);
1275     int32_t ret = 0;
1276     {
1277         InputMethodSyncTrace tracer("InputMethodSystemAbility_OnSwitchInputMethod");
1278         std::string targetImeName = info->prop.name + "/" + info->prop.id;
1279         if (!switchInfo.isTmpImeSwitchSubtype) {
1280             ImeCfgManager::GetInstance().ModifyImeCfg({ userId, targetImeName, switchInfo.subName, true });
1281         }
1282         auto targetIme = std::make_shared<ImeNativeCfg>(
1283             ImeNativeCfg{ targetImeName, info->prop.name, switchInfo.subName, info->prop.id });
1284         ret = session->StartIme(targetIme);
1285         if (ret != ErrorCode::NO_ERROR) {
1286             InputMethodSysEvent::GetInstance().InputmethodFaultReporter(
1287                 ret, switchInfo.bundleName, "switch input method failed!");
1288             return ret;
1289         }
1290         GetValidSubtype(switchInfo.subName, info);
1291         if (!switchInfo.isTmpImeSwitchSubtype) {
1292             session->NotifyImeChangeToClients(info->prop, info->subProp);
1293         }
1294         ret = session->SwitchSubtype(info->subProp);
1295     }
1296     ret = info->isSpecificSubName ? ret : ErrorCode::NO_ERROR;
1297     if (ret != ErrorCode::NO_ERROR) {
1298         InputMethodSysEvent::GetInstance().InputmethodFaultReporter(
1299             ret, switchInfo.bundleName, "switch input method subtype failed!");
1300     }
1301     return ret;
1302 }
1303 
IsTmpIme(int32_t userId,uint32_t tokenId)1304 bool InputMethodSystemAbility::IsTmpIme(int32_t userId, uint32_t tokenId)
1305 {
1306     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1307     if (session == nullptr) {
1308         IMSA_HILOGE("user:%{public}d session is nullptr!", userId);
1309         return false;
1310     }
1311     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
1312     if (currentImeCfg == nullptr) {
1313         IMSA_HILOGE("user:%{public}d has no default ime.", userId);
1314         return false;
1315     }
1316     auto imeData = session->GetImeData(ImeType::IME);
1317     if (imeData == nullptr) {
1318         IMSA_HILOGE("user:%{public}d has no running ime.", userId);
1319         return false;
1320     }
1321     auto bundleName = FullImeInfoManager::GetInstance().Get(userId, tokenId);
1322     if (bundleName.empty()) {
1323         bundleName = identityChecker_->GetBundleNameByToken(tokenId);
1324         IMSA_HILOGW("%{public}d/%{public}d/%{public}s not find in cache.", userId, tokenId, bundleName.c_str());
1325     }
1326     return !currentImeCfg->bundleName.empty() && !bundleName.empty() &&
1327            imeData->ime.first != currentImeCfg->bundleName && imeData->ime.first == bundleName;
1328 }
1329 
IsTmpImeSwitchSubtype(int32_t userId,uint32_t tokenId,const SwitchInfo & switchInfo)1330 bool InputMethodSystemAbility::IsTmpImeSwitchSubtype(int32_t userId, uint32_t tokenId, const SwitchInfo &switchInfo)
1331 {
1332     if (!IsTmpIme(userId, tokenId)) {
1333         IMSA_HILOGD("user:%{public}d tokenId:%{public}d not tmp ime.", userId, tokenId);
1334         return false;
1335     }
1336     auto bundleName = FullImeInfoManager::GetInstance().Get(userId, tokenId);
1337     if (bundleName.empty()) {
1338         bundleName = identityChecker_->GetBundleNameByToken(tokenId);
1339         IMSA_HILOGW("%{public}d/%{public}d/%{public}s not find in cache.", userId, tokenId, bundleName.c_str());
1340     }
1341     bool ret = !bundleName.empty() && bundleName == switchInfo.bundleName;
1342     IMSA_HILOGD("%{public}s/%{public}d switch.", switchInfo.bundleName.c_str(), ret);
1343     return ret;
1344 }
1345 
OnSwitchInputMethod(int32_t userId,const SwitchInfo & switchInfo,SwitchTrigger trigger)1346 int32_t InputMethodSystemAbility::OnSwitchInputMethod(int32_t userId, const SwitchInfo &switchInfo,
1347     SwitchTrigger trigger)
1348 {
1349     InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::CHANGE_IME);
1350     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1351     if (session == nullptr) {
1352         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1353         return ErrorCode::ERROR_NULL_POINTER;
1354     }
1355     if (!session->GetSwitchQueue().IsReady(switchInfo)) {
1356         IMSA_HILOGD("start wait.");
1357         session->GetSwitchQueue().Wait(switchInfo);
1358     }
1359     int32_t ret = CheckSwitchPermission(userId, switchInfo, trigger);
1360     if (ret != ErrorCode::NO_ERROR) {
1361         InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ErrorCode::ERROR_STATUS_PERMISSION_DENIED,
1362             switchInfo.bundleName, "switch input method failed!");
1363         session->GetSwitchQueue().Pop();
1364         return ret;
1365     }
1366     ret = StartSwitch(userId, switchInfo, session);
1367     session->GetSwitchQueue().Pop();
1368     return ret;
1369 }
1370 
GetValidSubtype(const std::string & subName,const std::shared_ptr<ImeInfo> & info)1371 void InputMethodSystemAbility::GetValidSubtype(const std::string &subName, const std::shared_ptr<ImeInfo> &info)
1372 {
1373     if (info == nullptr) {
1374         IMSA_HILOGE("info is nullptr!");
1375         return;
1376     }
1377     if (subName.empty()) {
1378         IMSA_HILOGW("undefined subtype");
1379         info->subProp.id = UNDEFINED;
1380         info->subProp.name = UNDEFINED;
1381     }
1382 }
1383 
OnStartInputType(int32_t userId,const SwitchInfo & switchInfo,bool isCheckPermission)1384 int32_t InputMethodSystemAbility::OnStartInputType(int32_t userId, const SwitchInfo &switchInfo,
1385     bool isCheckPermission)
1386 {
1387     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1388     if (session == nullptr) {
1389         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1390         return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND;
1391     }
1392     if (!session->GetSwitchQueue().IsReady(switchInfo)) {
1393         IMSA_HILOGD("start wait.");
1394         session->GetSwitchQueue().Wait(switchInfo);
1395     }
1396     IMSA_HILOGD("start switch %{public}s|%{public}s.", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
1397     if (isCheckPermission && !IsStartInputTypePermitted(userId)) {
1398         IMSA_HILOGE("not permitted to start input type!");
1399         session->GetSwitchQueue().Pop();
1400         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1401     }
1402     if (!IsNeedSwitch(userId, switchInfo.bundleName, switchInfo.subName)) {
1403         IMSA_HILOGI("no need to switch.");
1404         session->GetSwitchQueue().Pop();
1405         return ErrorCode::NO_ERROR;
1406     }
1407     int32_t ret = SwitchInputType(userId, switchInfo);
1408     session->GetSwitchQueue().Pop();
1409     return ret;
1410 }
1411 
IsNeedSwitch(int32_t userId,const std::string & bundleName,const std::string & subName)1412 bool InputMethodSystemAbility::IsNeedSwitch(int32_t userId, const std::string &bundleName,
1413     const std::string &subName)
1414 {
1415     if (InputTypeManager::GetInstance().IsStarted()) {
1416         ImeIdentification target = { bundleName, subName };
1417         return !(target == InputTypeManager::GetInstance().GetCurrentIme());
1418     }
1419     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
1420     IMSA_HILOGI("currentIme: %{public}s/%{public}s, targetIme: %{public}s/%{public}s.",
1421         currentImeCfg->bundleName.c_str(), currentImeCfg->subName.c_str(), bundleName.c_str(), subName.c_str());
1422     if ((subName.empty() && bundleName == currentImeCfg->bundleName) ||
1423         (!subName.empty() && subName == currentImeCfg->subName && currentImeCfg->bundleName == bundleName)) {
1424         IMSA_HILOGI("no need to switch");
1425         return false;
1426     }
1427     return true;
1428 }
1429 
Switch(int32_t userId,const std::string & bundleName,const std::shared_ptr<ImeInfo> & info)1430 int32_t InputMethodSystemAbility::Switch(int32_t userId, const std::string &bundleName,
1431     const std::shared_ptr<ImeInfo> &info)
1432 {
1433     auto currentImeBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
1434     if (bundleName != currentImeBundleName) {
1435         IMSA_HILOGI("switch input method to: %{public}s", bundleName.c_str());
1436         return SwitchExtension(userId, info);
1437     }
1438     auto currentInputType = InputTypeManager::GetInstance().GetCurrentIme();
1439     auto isInputTypeStarted = InputTypeManager::GetInstance().IsStarted();
1440     if (isInputTypeStarted && bundleName != currentInputType.bundleName) {
1441         IMSA_HILOGI("right click on state, switch input method to: %{public}s", bundleName.c_str());
1442         return SwitchExtension(userId, info);
1443     }
1444     return SwitchSubType(userId, info);
1445 }
1446 
1447 // Switch the current InputMethodExtension to the new InputMethodExtension
SwitchExtension(int32_t userId,const std::shared_ptr<ImeInfo> & info)1448 int32_t InputMethodSystemAbility::SwitchExtension(int32_t userId, const std::shared_ptr<ImeInfo> &info)
1449 {
1450     if (info == nullptr) {
1451         IMSA_HILOGE("info is nullptr!");
1452         return ErrorCode::ERROR_NULL_POINTER;
1453     }
1454     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1455     if (session == nullptr) {
1456         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1457         return ErrorCode::ERROR_NULL_POINTER;
1458     }
1459     std::string targetImeName = info->prop.name + "/" + info->prop.id;
1460     ImeCfgManager::GetInstance().ModifyImeCfg({ userId, targetImeName, info->subProp.id, false });
1461     ImeNativeCfg targetIme = { targetImeName, info->prop.name, info->subProp.id, info->prop.id };
1462     auto ret = session->StartIme(std::make_shared<ImeNativeCfg>(targetIme));
1463     if (ret != ErrorCode::NO_ERROR) {
1464         IMSA_HILOGE("start input method failed!");
1465         return ret;
1466     }
1467     session->NotifyImeChangeToClients(info->prop, info->subProp);
1468     GetValidSubtype("", info);
1469     session->SwitchSubtype(info->subProp);
1470     return ErrorCode::NO_ERROR;
1471 }
1472 
1473 // Inform current InputMethodExtension to switch subtype
SwitchSubType(int32_t userId,const std::shared_ptr<ImeInfo> & info)1474 int32_t InputMethodSystemAbility::SwitchSubType(int32_t userId, const std::shared_ptr<ImeInfo> &info)
1475 {
1476     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1477     if (session == nullptr) {
1478         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1479         return ErrorCode::ERROR_NULL_POINTER;
1480     }
1481     auto ret = session->SwitchSubtype(info->subProp);
1482     if (ret != ErrorCode::NO_ERROR) {
1483         IMSA_HILOGE("failed to inform ime to switch subtype, ret: %{public}d!", ret);
1484         return ret;
1485     }
1486     auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->imeId;
1487     ImeCfgManager::GetInstance().ModifyImeCfg({ userId, currentIme, info->subProp.id, false });
1488     session->NotifyImeChangeToClients(info->prop, info->subProp);
1489     return ErrorCode::NO_ERROR;
1490 }
1491 
SwitchInputType(int32_t userId,const SwitchInfo & switchInfo)1492 int32_t InputMethodSystemAbility::SwitchInputType(int32_t userId, const SwitchInfo &switchInfo)
1493 {
1494     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1495     if (session == nullptr) {
1496         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1497         return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND;
1498     }
1499     auto targetIme = session->GetImeNativeCfg(userId, switchInfo.bundleName, switchInfo.subName);
1500     if (targetIme == nullptr) {
1501         IMSA_HILOGE("targetIme is nullptr!");
1502         return ErrorCode::ERROR_IMSA_GET_IME_INFO_FAILED;
1503     }
1504     auto ret = session->StartIme(targetIme);
1505     if (ret != ErrorCode::NO_ERROR) {
1506         IMSA_HILOGE("start input method failed!");
1507         return ret;
1508     }
1509     SubProperty prop;
1510     prop.name = switchInfo.bundleName;
1511     prop.id = switchInfo.subName;
1512     ret = session->SwitchSubtype(prop);
1513     if (ret != ErrorCode::NO_ERROR) {
1514         IMSA_HILOGE("switch subtype failed!");
1515         return ret;
1516     }
1517     InputTypeManager::GetInstance().Set(true, { switchInfo.bundleName, switchInfo.subName });
1518     session->SetInputType();
1519     return ErrorCode::NO_ERROR;
1520 }
1521 
1522 // Deprecated because of no permission check, kept for compatibility
HideCurrentInputDeprecated()1523 int32_t InputMethodSystemAbility::HideCurrentInputDeprecated()
1524 {
1525     std::shared_ptr<PerUserSession> session = nullptr;
1526     auto result = PrepareForOperateKeyboard(session);
1527     if (result != ErrorCode::NO_ERROR) {
1528         return result;
1529     }
1530     return session->OnHideCurrentInput(GetCallingDisplayId());
1531 }
1532 
ShowCurrentInputDeprecated()1533 int32_t InputMethodSystemAbility::ShowCurrentInputDeprecated()
1534 {
1535     std::shared_ptr<PerUserSession> session = nullptr;
1536     auto result = PrepareForOperateKeyboard(session);
1537     if (result != ErrorCode::NO_ERROR) {
1538         return result;
1539     }
1540     return session->OnShowCurrentInput(GetCallingDisplayId());
1541 }
1542 
GetCurrentInputMethod(Property & resultValue)1543 ErrCode InputMethodSystemAbility::GetCurrentInputMethod(Property& resultValue)
1544 {
1545     auto prop = ImeInfoInquirer::GetInstance().GetCurrentInputMethod(GetCallingUserId());
1546     if (prop == nullptr) {
1547         IMSA_HILOGE("prop is nullptr!");
1548         return ErrorCode::ERROR_NULL_POINTER;
1549     }
1550     resultValue = *prop;
1551     return ERR_OK;
1552 }
1553 
IsDefaultImeSet(bool & resultValue)1554 ErrCode InputMethodSystemAbility::IsDefaultImeSet(bool& resultValue)
1555 {
1556     resultValue = ImeInfoInquirer::GetInstance().IsDefaultImeSet(GetCallingUserId());
1557     return ERR_OK;
1558 }
1559 
GetCurrentInputMethodSubtype(SubProperty & resultValue)1560 ErrCode InputMethodSystemAbility::GetCurrentInputMethodSubtype(SubProperty& resultValue)
1561 {
1562     auto prop = ImeInfoInquirer::GetInstance().GetCurrentSubtype(GetCallingUserId());
1563     if (prop == nullptr) {
1564         IMSA_HILOGE("prop is nullptr!");
1565         return ErrorCode::ERROR_NULL_POINTER;
1566     }
1567     resultValue = *prop;
1568     return ERR_OK;
1569 }
1570 
GetDefaultInputMethod(Property & prop,bool isBrief)1571 ErrCode InputMethodSystemAbility::GetDefaultInputMethod(Property &prop, bool isBrief)
1572 {
1573     std::shared_ptr<Property> property = std::make_shared<Property>(prop);
1574     auto ret = ImeInfoInquirer::GetInstance().GetDefaultInputMethod(GetCallingUserId(), property, isBrief);
1575     if (property != nullptr && ret == ErrorCode::NO_ERROR) {
1576         prop = *property;
1577     }
1578     return ret;
1579 }
1580 
GetInputMethodConfig(ElementName & inputMethodConfig)1581 ErrCode InputMethodSystemAbility::GetInputMethodConfig(ElementName &inputMethodConfig)
1582 {
1583     return ImeInfoInquirer::GetInstance().GetInputMethodConfig(GetCallingUserId(), inputMethodConfig);
1584 }
1585 
ListInputMethod(uint32_t status,std::vector<Property> & props)1586 ErrCode InputMethodSystemAbility::ListInputMethod(uint32_t status, std::vector<Property> &props)
1587 {
1588     return ImeInfoInquirer::GetInstance().ListInputMethod(GetCallingUserId(),
1589         static_cast<InputMethodStatus>(status), props);
1590 }
1591 
ListCurrentInputMethodSubtype(std::vector<SubProperty> & subProps)1592 ErrCode InputMethodSystemAbility::ListCurrentInputMethodSubtype(std::vector<SubProperty> &subProps)
1593 {
1594     return ImeInfoInquirer::GetInstance().ListCurrentInputMethodSubtype(GetCallingUserId(), subProps);
1595 }
1596 
ListInputMethodSubtype(const std::string & bundleName,std::vector<SubProperty> & subProps)1597 int32_t InputMethodSystemAbility::ListInputMethodSubtype(const std::string &bundleName,
1598     std::vector<SubProperty> &subProps)
1599 {
1600     return ImeInfoInquirer::GetInstance().ListInputMethodSubtype(GetCallingUserId(), bundleName, subProps);
1601 }
1602 
1603 /**
1604  * Work Thread of input method management service
1605  * \n Remote commands which may change the state or data in the service will be handled sequentially in this thread.
1606  */
WorkThread()1607 void InputMethodSystemAbility::WorkThread()
1608 {
1609     pthread_setname_np(pthread_self(), "OS_IMSAWorkThread");
1610     while (!stop_) {
1611         Message *msg = MessageHandler::Instance()->GetMessage();
1612         if (msg == nullptr) {
1613             IMSA_HILOGE("msg is nullptr!");
1614             break;
1615         }
1616         switch (msg->msgId_) {
1617             case MSG_ID_USER_START: {
1618                 OnUserStarted(msg);
1619                 break;
1620             }
1621             case MSG_ID_USER_REMOVED: {
1622                 OnUserRemoved(msg);
1623                 break;
1624             }
1625             case MSG_ID_USER_STOP: {
1626                 OnUserStop(msg);
1627                 break;
1628             }
1629             case MSG_ID_HIDE_KEYBOARD_SELF: {
1630                 OnHideKeyboardSelf(msg);
1631                 break;
1632             }
1633             case MSG_ID_BUNDLE_SCAN_FINISHED: {
1634                 HandleBundleScanFinished();
1635                 break;
1636             }
1637             case MSG_ID_DATA_SHARE_READY: {
1638                 HandleDataShareReady();
1639                 break;
1640             }
1641             case MSG_ID_PACKAGE_ADDED:
1642             case MSG_ID_PACKAGE_CHANGED:
1643             case MSG_ID_PACKAGE_REMOVED: {
1644                 HandlePackageEvent(msg);
1645                 break;
1646             }
1647             case MSG_ID_SYS_LANGUAGE_CHANGED: {
1648                 FullImeInfoManager::GetInstance().Update();
1649                 break;
1650             }
1651             case MSG_ID_BOOT_COMPLETED:
1652             case MSG_ID_OS_ACCOUNT_STARTED: {
1653                 FullImeInfoManager::GetInstance().Init();
1654                 break;
1655             }
1656             case MSG_ID_SCREEN_UNLOCK: {
1657                 OnScreenUnlock(msg);
1658                 break;
1659             }
1660             case MSG_ID_SCREEN_LOCK: {
1661                 OnScreenLock(msg);
1662                 break;
1663             }
1664             case MSG_ID_REGULAR_UPDATE_IME_INFO: {
1665                 FullImeInfoManager::GetInstance().RegularInit();
1666                 break;
1667             }
1668             case MSG_ID_UPDATE_LARGE_MEMORY_STATE: {
1669                 int32_t ret = HandleUpdateLargeMemoryState(msg);
1670                 if (ret != ErrorCode::NO_ERROR) {
1671                     IMSA_HILOGE("update large memory state failed %{public}d", ret);
1672                 }
1673                 break;
1674             }
1675             case MSG_ID_SYS_MEMORY_CHANGED: {
1676                 OnSysMemChanged();
1677                 break;
1678             }
1679             default: {
1680                 IMSA_HILOGD("the message is %{public}d.", msg->msgId_);
1681                 break;
1682             }
1683         }
1684         delete msg;
1685     }
1686 }
1687 
1688 /**
1689  * Called when a user is started. (EVENT_USER_STARTED is received)
1690  * \n Run in work thread of input method management service
1691  * \param msg the parameters are saved in msg->msgContent_
1692  * \return ErrorCode
1693  */
OnUserStarted(const Message * msg)1694 int32_t InputMethodSystemAbility::OnUserStarted(const Message *msg)
1695 {
1696     if (msg == nullptr) {
1697         IMSA_HILOGE("msg is nullptr!");
1698         return ErrorCode::ERROR_NULL_POINTER;
1699     }
1700     if (msg->msgContent_ == nullptr) {
1701         IMSA_HILOGE("msgContent_ is nullptr!");
1702         return ErrorCode::ERROR_NULL_POINTER;
1703     }
1704     auto newUserId = msg->msgContent_->ReadInt32();
1705     FullImeInfoManager::GetInstance().Switch(newUserId);
1706     // if scb enable, deal when receive wmsConnected.
1707     if (isScbEnable_.load()) {
1708         return ErrorCode::NO_ERROR;
1709     }
1710     if (newUserId == userId_) {
1711         return ErrorCode::NO_ERROR;
1712     }
1713     HandleUserSwitched(newUserId);
1714     return ErrorCode::NO_ERROR;
1715 }
1716 
OnUserRemoved(const Message * msg)1717 int32_t InputMethodSystemAbility::OnUserRemoved(const Message *msg)
1718 {
1719     if (msg == nullptr || msg->msgContent_ == nullptr) {
1720         IMSA_HILOGE("Aborted! Message is nullptr!");
1721         return ErrorCode::ERROR_NULL_POINTER;
1722     }
1723     auto userId = msg->msgContent_->ReadInt32();
1724     IMSA_HILOGI("start: %{public}d", userId);
1725     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1726     if (session != nullptr) {
1727         session->StopCurrentIme();
1728         UserSessionManager::GetInstance().RemoveUserSession(userId);
1729     }
1730     FullImeInfoManager::GetInstance().Delete(userId);
1731     NumkeyAppsManager::GetInstance().OnUserRemoved(userId);
1732     return ErrorCode::NO_ERROR;
1733 }
1734 // LCOV_EXCL_START
OnUserStop(const Message * msg)1735 int32_t InputMethodSystemAbility::OnUserStop(const Message *msg)
1736 {
1737     auto session = GetSessionFromMsg(msg);
1738     if (session == nullptr) {
1739         return ErrorCode::ERROR_NULL_POINTER;
1740     }
1741     session->StopCurrentIme();
1742     return ErrorCode::NO_ERROR;
1743 }
1744 
OnHideKeyboardSelf(const Message * msg)1745 int32_t InputMethodSystemAbility::OnHideKeyboardSelf(const Message *msg)
1746 {
1747     auto session = GetSessionFromMsg(msg);
1748     if (session == nullptr) {
1749         return ErrorCode::ERROR_NULL_POINTER;
1750     }
1751     session->OnHideSoftKeyBoardSelf();
1752     return ErrorCode::NO_ERROR;
1753 }
1754 
HandleUpdateLargeMemoryState(const Message * msg)1755 int32_t InputMethodSystemAbility::HandleUpdateLargeMemoryState(const Message *msg)
1756 {
1757     IMSA_HILOGD("called");
1758     if (msg == nullptr || msg->msgContent_ == nullptr) {
1759         IMSA_HILOGE("Aborted! Message is nullptr!");
1760         return ErrorCode::ERROR_NULL_POINTER;
1761     }
1762     MessageParcel *data = msg->msgContent_;
1763     int32_t uid = 0;
1764     int32_t memoryState = 0;
1765     if (!ITypesUtil::Unmarshal(*data, uid, memoryState) ||
1766         (memoryState != LargeMemoryState::LARGE_MEMORY_NEED &&
1767         memoryState != LargeMemoryState::LARGE_MEMORY_NOT_NEED)) {
1768         IMSA_HILOGE("Failed to read message parcel or invaild param %{public}d!", memoryState);
1769         return ErrorCode::ERROR_BAD_PARAMETERS;
1770     }
1771     IMSA_HILOGI("memory state %{public}d.", memoryState);
1772     auto userId = GetUserId(uid);
1773     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1774     if (session == nullptr) {
1775         IMSA_HILOGE("%{public}d session is nullptr", userId);
1776         return ErrorCode::ERROR_NULL_POINTER;
1777     }
1778     return session->UpdateLargeMemorySceneState(memoryState);
1779 }
1780 
1781 // LCOV_EXCL_STOP
HandlePackageEvent(const Message * msg)1782 int32_t InputMethodSystemAbility::HandlePackageEvent(const Message *msg)
1783 {
1784     MessageParcel *data = msg->msgContent_;
1785     if (data == nullptr) {
1786         IMSA_HILOGD("data is nullptr.");
1787         return ErrorCode::ERROR_NULL_POINTER;
1788     }
1789     int32_t userId = 0;
1790     std::string packageName;
1791     if (!ITypesUtil::Unmarshal(*data, userId, packageName)) {
1792         IMSA_HILOGE("Failed to read message parcel!");
1793         return ErrorCode::ERROR_EX_PARCELABLE;
1794     }
1795     if (msg->msgId_ == MSG_ID_PACKAGE_CHANGED) {
1796         return FullImeInfoManager::GetInstance().Update(userId, packageName);
1797     }
1798     if (msg->msgId_ == MSG_ID_PACKAGE_ADDED) {
1799         return FullImeInfoManager::GetInstance().Add(userId, packageName);
1800     }
1801     if (msg->msgId_ == MSG_ID_PACKAGE_REMOVED) {
1802         return OnPackageRemoved(userId, packageName);
1803     }
1804     return ErrorCode::NO_ERROR;
1805 }
1806 
1807 /**
1808  *  Called when a package is removed.
1809  *  \n Run in work thread of input method management service
1810  *  \param msg the parameters are saved in msg->msgContent_
1811  *  \return ErrorCode::NO_ERROR
1812  *  \return ErrorCode::ERROR_USER_NOT_UNLOCKED user not unlocked
1813  *  \return ErrorCode::ERROR_BAD_PARAMETERS bad parameter
1814  */
OnPackageRemoved(int32_t userId,const std::string & packageName)1815 int32_t InputMethodSystemAbility::OnPackageRemoved(int32_t userId, const std::string &packageName)
1816 {
1817     FullImeInfoManager::GetInstance().Delete(userId, packageName);
1818     return ErrorCode::NO_ERROR;
1819 }
1820 
OnScreenUnlock(const Message * msg)1821 void InputMethodSystemAbility::OnScreenUnlock(const Message *msg)
1822 {
1823     if (msg == nullptr || msg->msgContent_ == nullptr) {
1824         IMSA_HILOGE("message is nullptr");
1825         return;
1826     }
1827     int32_t userId = 0;
1828     if (!ITypesUtil::Unmarshal(*msg->msgContent_, userId)) {
1829         IMSA_HILOGE("failed to read message");
1830         return;
1831     }
1832     IMSA_HILOGI("userId: %{public}d", userId);
1833     if (userId != userId_) {
1834         return;
1835     }
1836     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1837     if (session == nullptr) {
1838         UserSessionManager::GetInstance().AddUserSession(userId_);
1839     }
1840     session = UserSessionManager::GetInstance().GetUserSession(userId_);
1841     if (session == nullptr) {
1842         IMSA_HILOGE("%{public}d session is nullptr!", userId_);
1843         return;
1844     }
1845     session->OnScreenUnlock();
1846 }
1847 
OnScreenLock(const Message * msg)1848 void InputMethodSystemAbility::OnScreenLock(const Message *msg)
1849 {
1850     if (msg == nullptr || msg->msgContent_ == nullptr) {
1851         IMSA_HILOGE("message is nullptr");
1852         return;
1853     }
1854     int32_t userId = 0;
1855     if (!ITypesUtil::Unmarshal(*msg->msgContent_, userId)) {
1856         IMSA_HILOGE("failed to read message");
1857         return;
1858     }
1859     IMSA_HILOGD("userId: %{public}d", userId);
1860     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1861     if (session == nullptr) {
1862         UserSessionManager::GetInstance().AddUserSession(userId);
1863     }
1864     session = UserSessionManager::GetInstance().GetUserSession(userId);
1865     if (session == nullptr) {
1866         IMSA_HILOGE("%{public}d session is nullptr!", userId);
1867         return;
1868     }
1869     session->OnScreenLock();
1870 }
1871 
OnDisplayOptionalInputMethod()1872 int32_t InputMethodSystemAbility::OnDisplayOptionalInputMethod()
1873 {
1874     IMSA_HILOGD("InputMethodSystemAbility::OnDisplayOptionalInputMethod start.");
1875     auto abilityManager = GetAbilityManagerService();
1876     if (abilityManager == nullptr) {
1877         IMSA_HILOGE("InputMethodSystemAbility::get ability manager failed");
1878         return ErrorCode::ERROR_EX_SERVICE_SPECIFIC;
1879     }
1880     AAFwk::Want want;
1881     want.SetAction(SELECT_DIALOG_ACTION);
1882     want.SetElementName(SELECT_DIALOG_HAP, SELECT_DIALOG_ABILITY);
1883     int32_t ret = abilityManager->StartAbility(want);
1884     if (ret != ErrorCode::NO_ERROR && ret != START_SERVICE_ABILITY_ACTIVATING) {
1885         IMSA_HILOGE("start InputMethod ability failed, err: %{public}d", ret);
1886         return ErrorCode::ERROR_EX_SERVICE_SPECIFIC;
1887     }
1888     IMSA_HILOGI("start InputMethod ability success.");
1889     return ErrorCode::NO_ERROR;
1890 }
1891 
GetAbilityManagerService()1892 sptr<AAFwk::IAbilityManager> InputMethodSystemAbility::GetAbilityManagerService()
1893 {
1894     IMSA_HILOGD("InputMethodSystemAbility::GetAbilityManagerService start");
1895     auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1896     if (systemAbilityManager == nullptr) {
1897         IMSA_HILOGE("SystemAbilityManager is nullptr.");
1898         return nullptr;
1899     }
1900 
1901     auto abilityMsObj = systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID);
1902     if (abilityMsObj == nullptr) {
1903         IMSA_HILOGE("Failed to get ability manager service.");
1904         return nullptr;
1905     }
1906 
1907     return iface_cast<AAFwk::IAbilityManager>(abilityMsObj);
1908 }
1909 
SwitchByCombinationKey(uint32_t state)1910 int32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state)
1911 {
1912     IMSA_HILOGD("InputMethodSystemAbility::SwitchByCombinationKey start.");
1913     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1914     if (session == nullptr) {
1915         IMSA_HILOGE("%{public}d session is nullptr!", userId_);
1916         return ErrorCode::ERROR_NULL_POINTER;
1917     }
1918     if (session->IsProxyImeEnable()) {
1919         IMSA_HILOGI("proxy enable, not switch.");
1920         return ErrorCode::NO_ERROR;
1921     }
1922     if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_MODE, state)) {
1923         IMSA_HILOGI("switch mode.");
1924         return SwitchMode();
1925     }
1926     if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_LANGUAGE, state)) {
1927         IMSA_HILOGI("switch language.");
1928         return SwitchLanguage();
1929     }
1930     if (session->IsImeSwitchForbidden()) {
1931         return ErrorCode::NO_ERROR;
1932     }
1933     if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_IME, state)) {
1934         IMSA_HILOGI("switch ime.");
1935         DealSwitchRequest();
1936         return ErrorCode::NO_ERROR;
1937     }
1938     IMSA_HILOGE("keycode is undefined!");
1939     return ErrorCode::ERROR_EX_UNSUPPORTED_OPERATION;
1940 }
1941 // LCOV_EXCL_START
DealSwitchRequest()1942 void InputMethodSystemAbility::DealSwitchRequest()
1943 {
1944     {
1945         std::lock_guard<std::mutex> lock(switchImeMutex_);
1946         // 0 means current swich ime task count.
1947         if (switchTaskExecuting_.load()) {
1948             IMSA_HILOGI("already has switch ime task.");
1949             ++targetSwitchCount_;
1950             return;
1951         } else {
1952             switchTaskExecuting_.store(true);
1953             ++targetSwitchCount_;
1954         }
1955     }
1956     auto switchTask = [this]() {
1957         auto checkSwitchCount = [this]() {
1958             std::lock_guard<std::mutex> lock(switchImeMutex_);
1959             if (targetSwitchCount_ > 0) {
1960                 return true;
1961             }
1962             switchTaskExecuting_.store(false);
1963             return false;
1964         };
1965         do {
1966             SwitchType();
1967         } while (checkSwitchCount());
1968     };
1969     if (serviceHandler_ == nullptr) {
1970         IMSA_HILOGE("serviceHandler_ is nullptr");
1971         return;
1972     }
1973     // 0 means delay time is 0.
1974     serviceHandler_->PostTask(switchTask, "SwitchImeTask", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1975 }
1976 // LCOV_EXCL_STOP
SwitchMode()1977 int32_t InputMethodSystemAbility::SwitchMode()
1978 {
1979     auto bundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
1980     auto subName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->subName;
1981     auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, bundleName, subName);
1982     if (info == nullptr) {
1983         IMSA_HILOGE("current ime is abnormal!");
1984         return ErrorCode::ERROR_BAD_PARAMETERS;
1985     }
1986     if (info->isNewIme) {
1987         IMSA_HILOGD("the switching operation is handed over to ime.");
1988         return ErrorCode::NO_ERROR;
1989     }
1990     auto condition = info->subProp.mode == "upper" ? Condition::LOWER : Condition::UPPER;
1991     return SwitchByCondition(condition, info);
1992 }
1993 
SwitchLanguage()1994 int32_t InputMethodSystemAbility::SwitchLanguage()
1995 {
1996     auto bundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
1997     auto subName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->subName;
1998     auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, bundleName, subName);
1999     if (info == nullptr) {
2000         IMSA_HILOGE("current ime is abnormal!");
2001         return ErrorCode::ERROR_BAD_PARAMETERS;
2002     }
2003     if (info->isNewIme) {
2004         IMSA_HILOGD("the switching operation is handed over to ime.");
2005         return ErrorCode::NO_ERROR;
2006     }
2007     if (info->subProp.language != "chinese" && info->subProp.language != "english") {
2008         return ErrorCode::NO_ERROR;
2009     }
2010     auto condition = info->subProp.language == "chinese" ? Condition::ENGLISH : Condition::CHINESE;
2011     return SwitchByCondition(condition, info);
2012 }
2013 // LCOV_EXCL_START
SwitchType()2014 int32_t InputMethodSystemAbility::SwitchType()
2015 {
2016     SwitchInfo nextSwitchInfo = { std::chrono::system_clock::now(), "", "" };
2017     uint32_t cacheCount = 0;
2018     {
2019         std::lock_guard<std::mutex> lock(switchImeMutex_);
2020         cacheCount = targetSwitchCount_.exchange(0);
2021     }
2022     int32_t ret =
2023         ImeInfoInquirer::GetInstance().GetSwitchInfoBySwitchCount(nextSwitchInfo, userId_, cacheCount);
2024     if (ret != ErrorCode::NO_ERROR) {
2025         IMSA_HILOGE("get next SwitchInfo failed, stop switching ime.");
2026         return ret;
2027     }
2028     if (nextSwitchInfo.bundleName.empty()) {
2029         IMSA_HILOGD("Stay current ime, no need to switch.");
2030         return ErrorCode::NO_ERROR;
2031     }
2032     IMSA_HILOGD("switch to: %{public}s.", nextSwitchInfo.bundleName.c_str());
2033     nextSwitchInfo.timestamp = std::chrono::system_clock::now();
2034     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
2035     if (session == nullptr) {
2036         IMSA_HILOGE("%{public}d session is nullptr!", userId_);
2037         return ErrorCode::ERROR_NULL_POINTER;
2038     }
2039     session->GetSwitchQueue().Push(nextSwitchInfo);
2040     return OnSwitchInputMethod(userId_, nextSwitchInfo, SwitchTrigger::IMSA);
2041 }
2042 
InitMonitors()2043 void InputMethodSystemAbility::InitMonitors()
2044 {
2045     int32_t ret = InitAccountMonitor();
2046     IMSA_HILOGI("init account monitor, ret: %{public}d.", ret);
2047     SubscribeCommonEvent();
2048     ret = InitMemMgrMonitor();
2049     IMSA_HILOGI("init MemMgr monitor, ret: %{public}d.", ret);
2050     ret = InitKeyEventMonitor();
2051     IMSA_HILOGI("init KeyEvent monitor, ret: %{public}d.", ret);
2052     ret = InitWmsMonitor();
2053     IMSA_HILOGI("init wms monitor, ret: %{public}d.", ret);
2054     ret = InitPasteboardMonitor();
2055     IMSA_HILOGI("init Pasteboard monitor, ret: %{public}d.", ret);
2056     InitSystemLanguageMonitor();
2057 }
2058 // LCOV_EXCL_STOP
HandleDataShareReady()2059 void InputMethodSystemAbility::HandleDataShareReady()
2060 {
2061     IMSA_HILOGI("run in.");
2062     if (ImeInfoInquirer::GetInstance().GetSystemConfig().enableFullExperienceFeature) {
2063         IMSA_HILOGW("Enter security mode.");
2064         RegisterSecurityModeObserver();
2065     }
2066     if (SettingsDataUtils::GetInstance().IsDataShareReady()) {
2067         return;
2068     }
2069     SettingsDataUtils::GetInstance().NotifyDataShareReady();
2070     FullImeInfoManager::GetInstance().Init();
2071     NumkeyAppsManager::GetInstance().Init(userId_);
2072 }
2073 
InitAccountMonitor()2074 int32_t InputMethodSystemAbility::InitAccountMonitor()
2075 {
2076     IMSA_HILOGI("InputMethodSystemAbility::InitAccountMonitor start.");
2077     auto imCommonEventManager = ImCommonEventManager::GetInstance();
2078     if (imCommonEventManager == nullptr) {
2079         IMSA_HILOGE("imCommonEventManager is nullptr!");
2080         return ErrorCode::ERROR_NULL_POINTER;
2081     }
2082     return imCommonEventManager->SubscribeAccountManagerService([this]() { HandleOsAccountStarted(); });
2083 }
2084 
InitKeyEventMonitor()2085 int32_t InputMethodSystemAbility::InitKeyEventMonitor()
2086 {
2087     IMSA_HILOGI("InputMethodSystemAbility::InitKeyEventMonitor start.");
2088     auto handler = [this]() {
2089         auto switchTrigger = [this](uint32_t keyCode) { return SwitchByCombinationKey(keyCode);};
2090         int32_t ret = KeyboardEvent::GetInstance().AddKeyEventMonitor(switchTrigger);
2091         IMSA_HILOGI("SubscribeKeyboardEvent add monitor: %{public}s.",
2092             ret == ErrorCode::NO_ERROR ? "success" : "failed");
2093         // Check device capslock status and ime cfg corrent, when device power-up.
2094         HandleImeCfgCapsState();
2095     };
2096     auto imCommonEventManager = ImCommonEventManager::GetInstance();
2097     if (imCommonEventManager == nullptr) {
2098         IMSA_HILOGE("imCommonEventManager is nullptr!");
2099         return ErrorCode::ERROR_NULL_POINTER;
2100     }
2101     bool ret = imCommonEventManager->SubscribeKeyboardEvent(handler);
2102     return ret ? ErrorCode::NO_ERROR : ErrorCode::ERROR_SERVICE_START_FAILED;
2103 }
2104 
InitWmsMonitor()2105 bool InputMethodSystemAbility::InitWmsMonitor()
2106 {
2107     auto imCommonEventManager = ImCommonEventManager::GetInstance();
2108     if (imCommonEventManager == nullptr) {
2109         IMSA_HILOGE("imCommonEventManager is nullptr!");
2110         return false;
2111     }
2112     return imCommonEventManager->SubscribeWindowManagerService([this]() { HandleWmsStarted(); });
2113 }
2114 
InitMemMgrMonitor()2115 bool InputMethodSystemAbility::InitMemMgrMonitor()
2116 {
2117     auto imCommonEventManager = ImCommonEventManager::GetInstance();
2118     if (imCommonEventManager == nullptr) {
2119         IMSA_HILOGE("imCommonEventManager is nullptr!");
2120         return false;
2121     }
2122     return imCommonEventManager->SubscribeMemMgrService([this]() { HandleMemStarted(); });
2123 }
2124 
InitWmsConnectionMonitor()2125 void InputMethodSystemAbility::InitWmsConnectionMonitor()
2126 {
2127     WmsConnectionMonitorManager::GetInstance().RegisterWMSConnectionChangedListener(
2128         [this](bool isConnected, int32_t userId, int32_t screenId) {
2129             isConnected ? HandleWmsConnected(userId, screenId) : HandleWmsDisconnected(userId, screenId);
2130         });
2131 }
2132 // LCOV_EXCL_START
HandlePasteboardStarted()2133 void InputMethodSystemAbility::HandlePasteboardStarted()
2134 {
2135     IMSA_HILOGI("pasteboard started");
2136     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
2137     if (session == nullptr) {
2138         IMSA_HILOGE("%{public}d session is nullptr!", userId_);
2139         return;
2140     }
2141 
2142     auto data = session->GetReadyImeData(ImeType::IME);
2143     if (data == nullptr) {
2144         IMSA_HILOGE("readyImeData is nullptr.");
2145         return;
2146     }
2147 
2148     if (data->imeStateManager == nullptr) {
2149         IMSA_HILOGE("imeStateManager is nullptr.");
2150         return;
2151     }
2152 
2153     data->imeStateManager->TemporaryActiveIme();
2154 }
2155 
InitPasteboardMonitor()2156 bool InputMethodSystemAbility::InitPasteboardMonitor()
2157 {
2158     auto commonEventMgr = ImCommonEventManager::GetInstance();
2159     if (commonEventMgr == nullptr) {
2160         IMSA_HILOGE("commonEventMgr is nullptr.");
2161         return false;
2162     }
2163 
2164     return commonEventMgr->SubscribePasteboardService([this]() {
2165         HandlePasteboardStarted();
2166     });
2167 }
2168 // LCOV_EXCL_STOP
InitSystemLanguageMonitor()2169 void InputMethodSystemAbility::InitSystemLanguageMonitor()
2170 {
2171     SystemParamAdapter::GetInstance().WatchParam(SystemParamAdapter::SYSTEM_LANGUAGE_KEY);
2172 }
2173 
InitFocusChangedMonitor()2174 void InputMethodSystemAbility::InitFocusChangedMonitor()
2175 {
2176     FocusMonitorManager::GetInstance().RegisterFocusChangedListener(
2177         [this](bool isOnFocused, uint64_t displayId, int32_t pid, int32_t uid) {
2178             HandleFocusChanged(isOnFocused, displayId, pid, uid);
2179         });
2180 }
2181 // LCOV_EXCL_START
InitWindowDisplayChangedMonitor()2182 void InputMethodSystemAbility::InitWindowDisplayChangedMonitor()
2183 {
2184     IMSA_HILOGD("enter.");
2185     auto callBack = [this](OHOS::Rosen::CallingWindowInfo callingWindowInfo) {
2186         IMSA_HILOGD("WindowDisplayChanged callbak.");
2187         int32_t userId = callingWindowInfo.userId_;
2188         auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2189         if (session == nullptr) {
2190             IMSA_HILOGE("[%{public}d] session is nullptr!", userId);
2191             return;
2192         };
2193         session->OnCallingDisplayIdChanged(
2194             callingWindowInfo.windowId_, callingWindowInfo.callingPid_, callingWindowInfo.displayId_);
2195     };
2196     WindowAdapter::GetInstance().RegisterCallingWindowInfoChangedListener(callBack);
2197 }
2198 
RegisterSecurityModeObserver()2199 void InputMethodSystemAbility::RegisterSecurityModeObserver()
2200 {
2201     int32_t ret = SettingsDataUtils::GetInstance().CreateAndRegisterObserver(SETTING_URI_PROXY,
2202         SettingsDataUtils::SECURITY_MODE, [this]() { DataShareCallback(SettingsDataUtils::SECURITY_MODE); });
2203     IMSA_HILOGI("register security mode observer, ret: %{public}d", ret);
2204 }
2205 
DataShareCallback(const std::string & key)2206 void InputMethodSystemAbility::DataShareCallback(const std::string &key)
2207 {
2208     if (key != SettingsDataUtils::SECURITY_MODE) {
2209         return;
2210     }
2211     IMSA_HILOGI("%{public}d full experience change.", userId_);
2212     if (serviceHandler_ == nullptr) {
2213         return;
2214     }
2215     auto task = [userId = userId_]() { ImeEnabledInfoManager::GetInstance().OnFullExperienceTableChanged(userId); };
2216     serviceHandler_->PostTask(task, "OnFullExperienceTableChanged", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
2217 }
2218 
OnCurrentImeStatusChanged(int32_t userId,const std::string & bundleName,EnabledStatus newStatus)2219 void InputMethodSystemAbility::OnCurrentImeStatusChanged(
2220     int32_t userId, const std::string &bundleName, EnabledStatus newStatus)
2221 {
2222     IMSA_HILOGI("start.");
2223     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2224     if (session == nullptr) {
2225         IMSA_HILOGE("%{public}d session is nullptr!", userId);
2226         return;
2227     }
2228     auto imeData = session->GetImeData(ImeType::IME);
2229     if (imeData != nullptr && bundleName != imeData->ime.first) {
2230         IMSA_HILOGD("%{public}d,%{public}s not current ime %{public}s!", userId, bundleName.c_str(),
2231             imeData->ime.first.c_str());
2232         return;
2233     }
2234     if (newStatus == EnabledStatus::BASIC_MODE) {
2235         session->OnSecurityChange(static_cast<int32_t>(SecurityMode::BASIC));
2236     }
2237     if (newStatus == EnabledStatus::FULL_EXPERIENCE_MODE) {
2238         session->OnSecurityChange(static_cast<int32_t>(SecurityMode::FULL));
2239     }
2240     session->AddRestartIme();
2241 }
2242 // LCOV_EXCL_STOP
GetSecurityMode(int32_t & security)2243 int32_t InputMethodSystemAbility::GetSecurityMode(int32_t &security)
2244 {
2245     IMSA_HILOGD("InputMethodSystemAbility start.");
2246     auto userId = GetCallingUserId();
2247     auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID());
2248     if (bundleName.empty()) {
2249         bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID());
2250         if (!ImeInfoInquirer::GetInstance().IsInputMethod(userId, bundleName)) {
2251             IMSA_HILOGE("[%{public}d, %{public}s] not an ime.", userId, bundleName.c_str());
2252             return ErrorCode::ERROR_NOT_IME;
2253         }
2254     }
2255     security = static_cast<int32_t>(SecurityMode::BASIC);
2256     EnabledStatus status = EnabledStatus::BASIC_MODE;
2257     auto ret = ImeEnabledInfoManager::GetInstance().GetEnabledState(userId, bundleName, status);
2258     if (ret != ErrorCode::NO_ERROR) {
2259         IMSA_HILOGW("[%{public}d, %{public}s] get enabled status failed:%{public}d,!", userId, bundleName.c_str(), ret);
2260     }
2261     if (status == EnabledStatus::FULL_EXPERIENCE_MODE) {
2262         security = static_cast<int32_t>(SecurityMode::FULL);
2263     }
2264     return ErrorCode::NO_ERROR;
2265 }
2266 
UnRegisteredProxyIme(int32_t type,const sptr<IInputMethodCore> & core)2267 ErrCode InputMethodSystemAbility::UnRegisteredProxyIme(int32_t type, const sptr<IInputMethodCore> &core)
2268 {
2269     pid_t pid = IPCSkeleton::GetCallingPid();
2270     if (!identityChecker_->IsValidVirtualIme(IPCSkeleton::GetCallingUid())) {
2271         IMSA_HILOGE("not native sa!");
2272         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
2273     }
2274     auto userId = GetCallingUserId();
2275     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2276     if (session == nullptr) {
2277         IMSA_HILOGE("%{public}d session is nullptr!", userId);
2278         return ErrorCode::ERROR_NULL_POINTER;
2279     }
2280     return session->OnUnRegisteredProxyIme(static_cast<UnRegisteredType>(type), core, pid);
2281 }
2282 
CheckEnableAndSwitchPermission()2283 int32_t InputMethodSystemAbility::CheckEnableAndSwitchPermission()
2284 {
2285     if (identityChecker_->IsFormShell(IPCSkeleton::GetCallingFullTokenID())) {
2286         IMSA_HILOGD("is form shell!");
2287         return ErrorCode::NO_ERROR;
2288     }
2289     if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingFullTokenID()) &&
2290         !identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
2291         IMSA_HILOGE("not native sa or system app!");
2292         return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
2293     }
2294     if (!identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(),
2295         std::string(PERMISSION_CONNECT_IME_ABILITY))) {
2296         IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!");
2297         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
2298     }
2299     return ErrorCode::NO_ERROR;
2300 }
2301 
CheckSwitchPermission(int32_t userId,const SwitchInfo & switchInfo,SwitchTrigger trigger)2302 int32_t InputMethodSystemAbility::CheckSwitchPermission(int32_t userId, const SwitchInfo &switchInfo,
2303     SwitchTrigger trigger)
2304 {
2305     IMSA_HILOGD("trigger: %{public}d.", static_cast<int32_t>(trigger));
2306     auto tokenId = IPCSkeleton::GetCallingTokenID();
2307     if (trigger == SwitchTrigger::IMSA) {
2308         return ErrorCode::NO_ERROR;
2309     }
2310     if (trigger == SwitchTrigger::NATIVE_SA) {
2311         return CheckEnableAndSwitchPermission();
2312     }
2313     if (trigger == SwitchTrigger::SYSTEM_APP) {
2314         if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
2315             IMSA_HILOGE("not system app!");
2316             return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
2317         }
2318         if (!identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) {
2319             IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!");
2320             return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
2321         }
2322         return ErrorCode::NO_ERROR;
2323     }
2324     if (trigger == SwitchTrigger::CURRENT_IME) {
2325         // PERMISSION_CONNECT_IME_ABILITY check temporarily reserved for application adaptation, will be deleted soon
2326         if (identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) {
2327             return ErrorCode::NO_ERROR;
2328         }
2329         IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!");
2330         if (IsCurrentIme(userId, tokenId)) {
2331             return ErrorCode::NO_ERROR;
2332         }
2333         IMSA_HILOGE("not current ime!");
2334         /* return ErrorCode::ERROR_STATUS_PERMISSION_DENIED temporarily reserved for application adaptation,
2335         will be replaced by ERROR_NOT_CURRENT_IME soon */
2336         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
2337     }
2338     return ErrorCode::ERROR_BAD_PARAMETERS;
2339 }
2340 
IsStartInputTypePermitted(int32_t userId)2341 bool InputMethodSystemAbility::IsStartInputTypePermitted(int32_t userId)
2342 {
2343     auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeInfo(userId);
2344     if (defaultIme == nullptr) {
2345         IMSA_HILOGE("failed to get default ime!");
2346         return false;
2347     }
2348     auto tokenId = IPCSkeleton::GetCallingTokenID();
2349     if (identityChecker_->IsBundleNameValid(tokenId, defaultIme->prop.name)) {
2350         return true;
2351     }
2352     if (identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) {
2353         return true;
2354     }
2355     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2356     if (session == nullptr) {
2357         IMSA_HILOGE("%{public}d session is nullptr!", userId);
2358         return false;
2359     }
2360     return identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)
2361            && session->IsBoundToClient(GetCallingDisplayId());
2362 }
2363 // LCOV_EXCL_START
ConnectSystemCmd(const sptr<IRemoteObject> & channel,sptr<IRemoteObject> & agent)2364 int32_t InputMethodSystemAbility::ConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)
2365 {
2366     auto tokenId = IPCSkeleton::GetCallingTokenID();
2367     if (!identityChecker_->HasPermission(tokenId, std::string(PERMISSION_CONNECT_IME_ABILITY))) {
2368         IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!");
2369         return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
2370     }
2371     auto userId = GetCallingUserId();
2372     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2373     if (session == nullptr) {
2374         IMSA_HILOGE("%{public}d session is nullptr!", userId);
2375         return ErrorCode::ERROR_NULL_POINTER;
2376     }
2377     return session->OnConnectSystemCmd(channel, agent);
2378 }
2379 // LCOV_EXCL_STOP
HandleWmsConnected(int32_t userId,int32_t screenId)2380 void InputMethodSystemAbility::HandleWmsConnected(int32_t userId, int32_t screenId)
2381 {
2382     if (userId == userId_) {
2383         // device boot or scb in foreground reboot
2384         HandleScbStarted(userId, screenId);
2385         return;
2386     }
2387     // user switched
2388     HandleUserSwitched(userId);
2389 }
2390 
HandleScbStarted(int32_t userId,int32_t screenId)2391 void InputMethodSystemAbility::HandleScbStarted(int32_t userId, int32_t screenId)
2392 {
2393     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2394     if (session == nullptr) {
2395         UserSessionManager::GetInstance().AddUserSession(userId);
2396     }
2397     session = UserSessionManager::GetInstance().GetUserSession(userId);
2398     if (session == nullptr) {
2399         IMSA_HILOGE("%{public}d session is nullptr!", userId);
2400         return;
2401     }
2402 #ifndef IMF_ON_DEMAND_START_STOP_SA_ENABLE
2403     if (!ImeStateManagerFactory::GetInstance().GetDynamicStartIme()) {
2404         session->IncreaseScbStartCount();
2405         session->AddRestartIme();
2406     }
2407 #endif
2408 }
2409 
HandleUserSwitched(int32_t userId)2410 void InputMethodSystemAbility::HandleUserSwitched(int32_t userId)
2411 {
2412     UpdateUserInfo(userId);
2413     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2414     if (session == nullptr) {
2415         UserSessionManager::GetInstance().AddUserSession(userId);
2416     }
2417     session = UserSessionManager::GetInstance().GetUserSession(userId);
2418     if (session == nullptr) {
2419         IMSA_HILOGE("%{public}d session is nullptr!", userId);
2420         return;
2421     }
2422     auto imeData = session->GetReadyImeData(ImeType::IME);
2423     if (imeData == nullptr && session->IsWmsReady()) {
2424         session->StartCurrentIme();
2425     }
2426 }
2427 
HandleWmsDisconnected(int32_t userId,int32_t screenId)2428 void InputMethodSystemAbility::HandleWmsDisconnected(int32_t userId, int32_t screenId)
2429 {
2430     // clear client
2431     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2432     if (session != nullptr) {
2433         session->RemoveAllCurrentClient();
2434     }
2435 
2436 #ifndef IMF_ON_DEMAND_START_STOP_SA_ENABLE
2437     if (userId == userId_ && !ImeStateManagerFactory::GetInstance().GetDynamicStartIme()) {
2438         // user switched or scb in foreground died, not deal
2439         return;
2440     }
2441 #endif
2442     // scb in background died, stop ime
2443     if (session == nullptr) {
2444         return;
2445     }
2446     session->StopCurrentIme();
2447 }
2448 
HandleWmsStarted()2449 void InputMethodSystemAbility::HandleWmsStarted()
2450 {
2451     // singleton, device boot, wms reboot
2452     IMSA_HILOGI("Wms start.");
2453     InitFocusChangedMonitor();
2454     if (isScbEnable_.load()) {
2455         IMSA_HILOGI("scb enable, register WMS connection listener.");
2456         InitWmsConnectionMonitor();
2457         InitWindowDisplayChangedMonitor();
2458         return;
2459     }
2460     // clear client
2461     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
2462     if (session != nullptr) {
2463         session->RemoveAllCurrentClient();
2464     }
2465     RestartSessionIme(session);
2466 }
2467 
HandleFocusChanged(bool isFocused,uint64_t displayId,int32_t pid,int32_t uid)2468 void InputMethodSystemAbility::HandleFocusChanged(bool isFocused, uint64_t displayId, int32_t pid, int32_t uid)
2469 {
2470     int32_t userId = GetUserId(uid);
2471     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2472     if (session == nullptr) {
2473         IMSA_HILOGE("[%{public}d, %{public}d] session is nullptr!", uid, userId);
2474         return;
2475     }
2476     isFocused ? session->OnFocused(displayId, pid, uid) : session->OnUnfocused(displayId, pid, uid);
2477 }
2478 
HandleMemStarted()2479 void InputMethodSystemAbility::HandleMemStarted()
2480 {
2481     // singleton
2482     IMSA_HILOGI("MemMgr start.");
2483     Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 1, INPUT_METHOD_SYSTEM_ABILITY_ID);
2484     Memory::MemMgrClient::GetInstance().SetCritical(getpid(), true, INPUT_METHOD_SYSTEM_ABILITY_ID);
2485     SystemParamAdapter::GetInstance().WatchParam(SystemParamAdapter::MEMORY_WATERMARK_KEY);
2486     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
2487     RestartSessionIme(session);
2488 }
2489 
HandleOsAccountStarted()2490 void InputMethodSystemAbility::HandleOsAccountStarted()
2491 {
2492     IMSA_HILOGI("account start");
2493     auto userId = OsAccountAdapter::GetForegroundOsAccountLocalId();
2494     if (userId_ != userId) {
2495         UpdateUserInfo(userId);
2496     }
2497     Message *msg = new (std::nothrow) Message(MessageID::MSG_ID_OS_ACCOUNT_STARTED, nullptr);
2498     if (msg == nullptr) {
2499         return;
2500     }
2501     auto handler = MessageHandler::Instance();
2502     if (handler == nullptr) {
2503         IMSA_HILOGE("handler is nullptr");
2504         return;
2505     }
2506     handler->SendMessage(msg);
2507 }
2508 
StopImeInBackground()2509 void InputMethodSystemAbility::StopImeInBackground()
2510 {
2511     auto task = [this]() {
2512         auto sessions = UserSessionManager::GetInstance().GetUserSessions();
2513         for (const auto &tempSession : sessions) {
2514             if (tempSession.first != userId_) {
2515                 tempSession.second->StopCurrentIme();
2516             }
2517         }
2518     };
2519     if (serviceHandler_ == nullptr) {
2520         return;
2521     }
2522     serviceHandler_->PostTask(task, "StopImeInBackground", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
2523 }
2524 
GetUserId(int32_t uid)2525 int32_t InputMethodSystemAbility::GetUserId(int32_t uid)
2526 {
2527     IMSA_HILOGD("uid:%{public}d", uid);
2528     auto userId = OsAccountAdapter::GetOsAccountLocalIdFromUid(uid);
2529     // 0 represents user 0 in the system
2530     if (userId == 0) {
2531         IMSA_HILOGI("user 0");
2532         return userId_;
2533     }
2534     return userId;
2535 }
2536 
GetCallingUserId()2537 int32_t InputMethodSystemAbility::GetCallingUserId()
2538 {
2539     auto uid = IPCSkeleton::GetCallingUid();
2540     return GetUserId(uid);
2541 }
2542 
GetCallingDisplayId(sptr<IRemoteObject> abilityToken)2543 uint64_t InputMethodSystemAbility::GetCallingDisplayId(sptr<IRemoteObject> abilityToken)
2544 {
2545     return identityChecker_->GetDisplayIdByPid(IPCSkeleton::GetCallingPid(), abilityToken);
2546 }
2547 
IsCurrentIme(int32_t userId,uint32_t tokenId)2548 bool InputMethodSystemAbility::IsCurrentIme(int32_t userId, uint32_t tokenId)
2549 {
2550     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2551     if (session == nullptr) {
2552         IMSA_HILOGE("%{public}d session is nullptr!", userId);
2553         return false;
2554     }
2555     auto bundleName = FullImeInfoManager::GetInstance().Get(userId, tokenId);
2556     if (bundleName.empty()) {
2557         IMSA_HILOGW("user:%{public}d tokenId:%{public}d not find.", userId, tokenId);
2558         bundleName = identityChecker_->GetBundleNameByToken(tokenId);
2559     }
2560     auto imeData = session->GetImeData(ImeType::IME);
2561     return imeData != nullptr && bundleName == imeData->ime.first;
2562 }
2563 
StartInputType(int32_t userId,InputType type)2564 int32_t InputMethodSystemAbility::StartInputType(int32_t userId, InputType type)
2565 {
2566     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2567     if (session == nullptr) {
2568         IMSA_HILOGE("%{public}d session is nullptr!", userId);
2569         return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND;
2570     }
2571     if (!session->IsDefaultDisplayGroup(GetCallingDisplayId())) {
2572         IMSA_HILOGI("only need input type in default display");
2573         return ErrorCode::NO_ERROR;
2574     }
2575     ImeIdentification ime;
2576     int32_t ret = InputTypeManager::GetInstance().GetImeByInputType(type, ime);
2577     if (ret != ErrorCode::NO_ERROR) {
2578         IMSA_HILOGW("not find input type: %{public}d.", type);
2579         // add for not adapter for SECURITY_INPUT
2580         if (type == InputType::SECURITY_INPUT) {
2581             return session->StartUserSpecifiedIme(DEFAULT_DISPLAY_ID);
2582         }
2583         return ret;
2584     }
2585     SwitchInfo switchInfo = { std::chrono::system_clock::now(), ime.bundleName, ime.subName };
2586     session->GetSwitchQueue().Push(switchInfo);
2587     IMSA_HILOGI("start input type: %{public}d.", type);
2588     return (type == InputType::SECURITY_INPUT) ?
2589         OnStartInputType(userId, switchInfo, false) : OnStartInputType(userId, switchInfo, true);
2590 }
2591 
NeedHideWhenSwitchInputType(int32_t userId,InputType type,bool & needHide)2592 void InputMethodSystemAbility::NeedHideWhenSwitchInputType(int32_t userId, InputType type, bool &needHide)
2593 {
2594     if (!needHide) {
2595         return;
2596     }
2597     ImeIdentification ime;
2598     InputTypeManager::GetInstance().GetImeByInputType(type, ime);
2599     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2600     if (session == nullptr) {
2601         IMSA_HILOGE("UserId: %{public}d session is nullptr!", userId_);
2602         needHide = false;
2603         return;
2604     }
2605     auto imeData = session->GetReadyImeData(ImeType::IME);
2606     if (imeData == nullptr) {
2607         IMSA_HILOGI("Readyime is nullptr");
2608         needHide = false;
2609         return;
2610     }
2611     needHide = imeData->ime.first == ime.bundleName;
2612 }
2613 // LCOV_EXCL_START
HandleBundleScanFinished()2614 void InputMethodSystemAbility::HandleBundleScanFinished()
2615 {
2616     isBundleScanFinished_.store(true);
2617     HandleImeCfgCapsState();
2618 }
2619 
ModifyImeCfgWithWrongCaps()2620 bool InputMethodSystemAbility::ModifyImeCfgWithWrongCaps()
2621 {
2622     bool isCapsEnable = false;
2623     if (!GetDeviceFunctionKeyState(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY, isCapsEnable)) {
2624         IMSA_HILOGE("Get capslock function key state failed!");
2625         return false;
2626     }
2627     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
2628     if (currentImeCfg == nullptr) {
2629         IMSA_HILOGE("currentImeCfg is nullptr!");
2630         return false;
2631     }
2632     auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, currentImeCfg->bundleName, currentImeCfg->subName);
2633     if (info == nullptr) {
2634         IMSA_HILOGE("ime info is nullptr!");
2635         return false;
2636     }
2637     bool imeCfgCapsEnable = info->subProp.mode == "upper";
2638     if (imeCfgCapsEnable == isCapsEnable) {
2639         IMSA_HILOGE("current caps state is correct.");
2640         return true;
2641     }
2642     auto condition = isCapsEnable ? Condition::UPPER : Condition::LOWER;
2643     auto correctIme = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(info->subProps, condition);
2644     if (correctIme == nullptr) {
2645         IMSA_HILOGE("correctIme is empty!");
2646         return false;
2647     }
2648     std::string correctImeName = info->prop.name + "/" + info->prop.id;
2649     ImeCfgManager::GetInstance().ModifyImeCfg({ userId_, correctImeName, correctIme->id, false });
2650     IMSA_HILOGD("Adjust imeCfg caps success! current imeName: %{public}s, subName: %{public}s",
2651         correctImeName.c_str(), correctIme->id.c_str());
2652     return true;
2653 }
2654 
GetDeviceFunctionKeyState(int32_t functionKey,bool & isEnable)2655 bool InputMethodSystemAbility::GetDeviceFunctionKeyState(int32_t functionKey, bool &isEnable)
2656 {
2657     auto multiInputMgr = MMI::InputManager::GetInstance();
2658     if (multiInputMgr == nullptr) {
2659         IMSA_HILOGE("multiInputMgr is nullptr");
2660         return false;
2661     }
2662     int32_t ret = multiInputMgr->GetFunctionKeyState(functionKey, isEnable);
2663     IMSA_HILOGD("The function key: %{public}d, isEnable: %{public}d", functionKey, isEnable);
2664     if (ret != ErrorCode::NO_ERROR) {
2665         IMSA_HILOGE("multiInputMgr get function key state error: %{public}d", ret);
2666         return false;
2667     }
2668     return true;
2669 }
2670 // LCOV_EXCL_STOP
HandleImeCfgCapsState()2671 void InputMethodSystemAbility::HandleImeCfgCapsState()
2672 {
2673     if (!isBundleScanFinished_.load()) {
2674         IMSA_HILOGE("Bundle scan is not ready.");
2675         return;
2676     }
2677     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
2678     if (session == nullptr) {
2679         IMSA_HILOGE("UserId: %{public}d session is nullptr!", userId_);
2680         return;
2681     }
2682     if (!session->IsSaReady(MULTIMODAL_INPUT_SERVICE_ID)) {
2683         IMSA_HILOGE("MMI service is not ready.");
2684         return;
2685     }
2686     if (!ModifyImeCfgWithWrongCaps()) {
2687         IMSA_HILOGE("Check ImeCfg capslock state correct failed!");
2688     }
2689 }
2690 
GetInputMethodState(int32_t & status)2691 ErrCode InputMethodSystemAbility::GetInputMethodState(int32_t& status)
2692 {
2693     auto userId = GetCallingUserId();
2694     auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID());
2695     if (bundleName.empty()) {
2696         bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID());
2697         if (!ImeInfoInquirer::GetInstance().IsInputMethod(userId, bundleName)) {
2698             IMSA_HILOGE("[%{public}d, %{public}s] not an ime.", userId, bundleName.c_str());
2699             return ErrorCode::ERROR_NOT_IME;
2700         }
2701     }
2702     EnabledStatus tmpStatus = EnabledStatus::DISABLED;
2703     auto ret = ImeEnabledInfoManager::GetInstance().GetEnabledState(userId, bundleName, tmpStatus);
2704     if (ret != ErrorCode::NO_ERROR) {
2705         return ret;
2706     }
2707     status = static_cast<int32_t>(tmpStatus);
2708     return ErrorCode::NO_ERROR;
2709 }
2710 
ShowCurrentInput(uint32_t type)2711 ErrCode InputMethodSystemAbility::ShowCurrentInput(uint32_t type)
2712 {
2713     auto name = ImfHiSysEventUtil::GetAppName(IPCSkeleton::GetCallingTokenID());
2714     auto pid = IPCSkeleton::GetCallingPid();
2715     auto userId = GetCallingUserId();
2716     auto imeInfo = GetCurrentImeInfoForHiSysEvent(userId);
2717     auto ret = ShowCurrentInputInner();
2718     auto evenInfo = HiSysOriginalInfo::Builder()
2719                         .SetPeerName(name)
2720                         .SetPeerPid(pid)
2721                         .SetPeerUserId(userId)
2722                         .SetClientType(static_cast<ClientType>(type))
2723                         .SetImeName(imeInfo.second)
2724                         .SetEventCode(
2725         static_cast<int32_t>(IInputMethodSystemAbilityIpcCode::COMMAND_SHOW_CURRENT_INPUT))
2726                         .SetErrCode(ret)
2727                         .Build();
2728     ImsaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_SHOW, *evenInfo);
2729     return ret;
2730 }
2731 
ShowInput(const sptr<IInputClient> & client,uint32_t type,int32_t requestKeyboardReason)2732 ErrCode InputMethodSystemAbility::ShowInput(const sptr<IInputClient>& client,
2733     uint32_t type, int32_t requestKeyboardReason)
2734 {
2735     auto name = ImfHiSysEventUtil::GetAppName(IPCSkeleton::GetCallingTokenID());
2736     auto pid = IPCSkeleton::GetCallingPid();
2737     auto userId = GetCallingUserId();
2738     auto imeInfo = GetCurrentImeInfoForHiSysEvent(userId);
2739     auto ret = ShowInputInner(client, requestKeyboardReason);
2740     auto evenInfo = HiSysOriginalInfo::Builder()
2741                         .SetPeerName(name)
2742                         .SetPeerPid(pid)
2743                         .SetPeerUserId(userId)
2744                         .SetClientType(static_cast<ClientType>(type))
2745                         .SetImeName(imeInfo.second)
2746                         .SetEventCode(static_cast<int32_t>(IInputMethodSystemAbilityIpcCode::COMMAND_SHOW_INPUT))
2747                         .SetErrCode(ret)
2748                         .Build();
2749     ImsaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_SHOW, *evenInfo);
2750     return ret;
2751 }
2752 
GetCurrentImeInfoForHiSysEvent(int32_t userId)2753 std::pair<int64_t, std::string> InputMethodSystemAbility::GetCurrentImeInfoForHiSysEvent(int32_t userId)
2754 {
2755     std::pair<int64_t, std::string> imeInfo{ 0, "" };
2756     auto session = UserSessionManager::GetInstance().GetUserSession(userId);
2757     if (session == nullptr) {
2758         auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
2759         imeInfo.second = currentImeCfg != nullptr ? currentImeCfg->bundleName : "";
2760         return imeInfo;
2761     }
2762     auto imeType = session->IsProxyImeEnable() ? ImeType::PROXY_IME : ImeType::IME;
2763     auto imeData = session->GetImeData(imeType);
2764     if (imeData != nullptr) {
2765         imeInfo.first = imeData->pid;
2766         imeInfo.second = imeData->ime.first;
2767     }
2768     return imeInfo;
2769 }
2770 
GetScreenLockIme(int32_t userId,std::string & ime)2771 int32_t InputMethodSystemAbility::GetScreenLockIme(int32_t userId, std::string &ime)
2772 {
2773     auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeCfg();
2774     if (defaultIme != nullptr) {
2775         ime = defaultIme->imeId;
2776         IMSA_HILOGD("GetDefaultIme screenlocked");
2777         return ErrorCode::NO_ERROR;
2778     }
2779     IMSA_HILOGE("GetDefaultIme is failed!");
2780     auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
2781     if (currentIme != nullptr) {
2782         ime = currentIme->imeId;
2783         IMSA_HILOGD("GetCurrentIme screenlocked");
2784         return ErrorCode::NO_ERROR;
2785     }
2786     IMSA_HILOGE("GetCurrentIme is failed!");
2787     if (GetAlternativeIme(userId, ime) != ErrorCode::NO_ERROR) {
2788         return ErrorCode::ERROR_NOT_IME;
2789     }
2790     return ErrorCode::NO_ERROR;
2791 }
2792 
GetAlternativeIme(int32_t userId,std::string & ime)2793 int32_t InputMethodSystemAbility::GetAlternativeIme(int32_t userId, std::string &ime)
2794 {
2795     InputMethodStatus status = InputMethodStatus::ENABLE;
2796     std::vector<Property> props;
2797     int32_t ret = ListInputMethod(status, props);
2798     if (ret == ErrorCode::NO_ERROR && !props.empty()) {
2799         ime = props[0].name + "/" + props[0].id;
2800         return ErrorCode::NO_ERROR;
2801     }
2802     IMSA_HILOGE("GetListEnableInputMethodIme is failed!");
2803     status = InputMethodStatus::DISABLE;
2804     ret = ListInputMethod(status, props);
2805     if (ret != ErrorCode::NO_ERROR || props.empty()) {
2806         IMSA_HILOGE("GetListDisableInputMethodIme is failed!");
2807         return ErrorCode::ERROR_NOT_IME;
2808     }
2809     ret = EnableIme(userId, props[0].name);
2810     if (ret == ErrorCode::NO_ERROR) {
2811         ime = props[0].name + "/" + props[0].id;
2812         return ErrorCode::NO_ERROR;
2813     }
2814     IMSA_HILOGE("GetAlternativeIme is failed!");
2815     return ErrorCode::ERROR_NOT_IME;
2816 }
2817 // LCOV_EXCL_START
SendPrivateData(const Value & value)2818 ErrCode InputMethodSystemAbility::SendPrivateData(const Value &value)
2819 {
2820     std::unordered_map<std::string, PrivateDataValue> privateCommand;
2821     privateCommand = value.valueMap;
2822     if (privateCommand.empty()) {
2823         IMSA_HILOGE("PrivateCommand is empty!");
2824         return ErrorCode::ERROR_PRIVATE_COMMAND_IS_EMPTY;
2825     }
2826     if (!identityChecker_->IsSpecialSaUid()) {
2827         IMSA_HILOGE("Uid failed, not permission!");
2828         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
2829     }
2830     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
2831     if (session == nullptr) {
2832         IMSA_HILOGE("UserId: %{public}d session is nullptr!", userId_);
2833         return ErrorCode::ERROR_IMSA_USER_SESSION_NOT_FOUND;
2834     }
2835     if (!session->SpecialScenarioCheck()) {
2836         IMSA_HILOGE("Special check permission failed!");
2837         return ErrorCode::ERROR_SCENE_UNSUPPORTED;
2838     }
2839     auto ret = session->SpecialSendPrivateData(privateCommand);
2840     if (ret != ErrorCode::NO_ERROR) {
2841         IMSA_HILOGE("Special send private data failed, ret: %{public}d!", ret);
2842     }
2843     return ret;
2844 }
2845 
GetSecurityInputType(const InputClientInfo & inputClientInfo)2846 InputType InputMethodSystemAbility::GetSecurityInputType(const InputClientInfo &inputClientInfo)
2847 {
2848     if (inputClientInfo.config.inputAttribute.GetSecurityFlag()) {
2849         return InputType::SECURITY_INPUT;
2850     } else {
2851         return InputType::NONE;
2852     }
2853 }
2854 
StartSecurityIme(int32_t & userId,InputClientInfo & inputClientInfo)2855 int32_t InputMethodSystemAbility::StartSecurityIme(int32_t &userId, InputClientInfo &inputClientInfo)
2856 {
2857     InputType type = GetSecurityInputType(inputClientInfo);
2858     IMSA_HILOGI("InputType:[%{public}d.", type);
2859     if (!InputTypeManager::GetInstance().IsStarted()) {
2860         IMSA_HILOGD("SecurityImeFlag, input type is not started, start.");
2861         // if need to switch ime, no need to hide panel first.
2862         NeedHideWhenSwitchInputType(userId, type, inputClientInfo.needHide);
2863         return StartInputType(userId, type);
2864     }
2865     if (!inputClientInfo.isNotifyInputStart) {
2866         IMSA_HILOGD("SecurityImeFlag, same textField, input type is started, not deal.");
2867         return ErrorCode::NO_ERROR;
2868     }
2869     if (!InputTypeManager::GetInstance().IsInputTypeImeStarted(type)) {
2870         IMSA_HILOGD("SecurityImeFlag, new textField, input type is started, but it is not target, switch.");
2871         NeedHideWhenSwitchInputType(userId, type, inputClientInfo.needHide);
2872         return StartInputType(userId, type);
2873     }
2874     return ErrorCode::NO_ERROR;
2875 }
2876 
OnSysMemChanged()2877 void InputMethodSystemAbility::OnSysMemChanged()
2878 {
2879     auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
2880     if (session == nullptr) {
2881         return;
2882     }
2883     if (SystemParamAdapter::GetInstance().GetBoolParam(SystemParamAdapter::MEMORY_WATERMARK_KEY)) {
2884         session->TryDisconnectIme();
2885         return;
2886     }
2887     session->TryStartIme();
2888 }
2889 // LCOV_EXCL_STOP
2890 } // namespace MiscServices
2891 } // namespace OHOS