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 ¶ms = 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