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