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