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 "peruser_session.h" 17 18 #include <vector> 19 20 #include "ability_connect_callback_proxy.h" 21 #include "ability_manager_interface.h" 22 #include "element_name.h" 23 #include "ime_cfg_manager.h" 24 #include "input_client_proxy.h" 25 #include "input_control_channel_proxy.h" 26 #include "input_data_channel_proxy.h" 27 #include "input_method_agent_proxy.h" 28 #include "input_method_core_proxy.h" 29 #include "ipc_skeleton.h" 30 #include "message_parcel.h" 31 #include "parcel.h" 32 #include "iservice_registry.h" 33 #include "system_ability_definition.h" 34 #include "unistd.h" 35 #include "utils.h" 36 #include "want.h" 37 38 namespace OHOS { 39 namespace MiscServices { 40 using namespace MessageID; 41 OnRemoteDied(const wptr<IRemoteObject> & remote)42 void RemoteObjectDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote) 43 { 44 IMSA_HILOGE("Start"); 45 if (handler_ != nullptr) { 46 handler_(remote); 47 } 48 } 49 SetDeathRecipient(RemoteDiedHandler handler)50 void RemoteObjectDeathRecipient::SetDeathRecipient(RemoteDiedHandler handler) 51 { 52 handler_ = handler; 53 } 54 PerUserSession(int userId)55 PerUserSession::PerUserSession(int userId) : userId_(userId), imsDeathRecipient(new RemoteObjectDeathRecipient()) 56 { 57 } 58 59 /*! Destructor 60 */ ~PerUserSession()61 PerUserSession::~PerUserSession() 62 { 63 imsDeathRecipient = nullptr; 64 if (workThreadHandler.joinable()) { 65 workThreadHandler.join(); 66 } 67 } 68 69 70 /*! Create work thread for this user 71 \param handle message handle to receive the message 72 */ CreateWorkThread(MessageHandler & handler)73 void PerUserSession::CreateWorkThread(MessageHandler& handler) 74 { 75 msgHandler = &handler; 76 workThreadHandler = std::thread([this] {WorkThread();}); 77 } 78 79 /*! Wait till work thread exits 80 */ JoinWorkThread()81 void PerUserSession::JoinWorkThread() 82 { 83 if (workThreadHandler.joinable()) { 84 workThreadHandler.join(); 85 } 86 } 87 88 /*! Work thread for this user 89 */ WorkThread()90 void PerUserSession::WorkThread() 91 { 92 if (!msgHandler) { 93 return; 94 } 95 while (1) { 96 Message *msg = msgHandler->GetMessage(); 97 std::lock_guard<std::recursive_mutex> lock(mtx); 98 switch (msg->msgId_) { 99 case MSG_ID_HIDE_KEYBOARD_SELF: { 100 int flag = msg->msgContent_->ReadInt32(); 101 OnHideKeyboardSelf(flag); 102 break; 103 } 104 default: { 105 break; 106 } 107 } 108 delete msg; 109 msg = nullptr; 110 } 111 } 112 AddClient(sptr<IRemoteObject> inputClient,const ClientInfo & clientInfo)113 int PerUserSession::AddClient(sptr<IRemoteObject> inputClient, const ClientInfo &clientInfo) 114 { 115 IMSA_HILOGD("PerUserSession::AddClient"); 116 std::lock_guard<std::recursive_mutex> lock(mtx); 117 auto cacheClient = GetClientInfo(inputClient); 118 if (cacheClient != nullptr) { 119 IMSA_HILOGE("PerUserSession::AddClient info is exist, not need add."); 120 return ErrorCode::NO_ERROR; 121 } 122 auto info = std::make_shared<ClientInfo>(clientInfo); 123 if (info == nullptr) { 124 IMSA_HILOGE("info is nullptr"); 125 return ErrorCode::ERROR_NULL_POINTER; 126 } 127 mapClients.insert({ inputClient, info }); 128 info->deathRecipient->SetDeathRecipient( 129 [this, info](const wptr<IRemoteObject> &) { this->OnClientDied(info->client); }); 130 sptr<IRemoteObject> obj = info->client->AsObject(); 131 if (obj == nullptr) { 132 IMSA_HILOGE("PerUserSession::AddClient inputClient AsObject is nullptr"); 133 return ErrorCode::ERROR_REMOTE_CLIENT_DIED; 134 } 135 bool ret = obj->AddDeathRecipient(info->deathRecipient); 136 IMSA_HILOGI("Add death recipient %{public}s", ret ? "success" : "failed"); 137 return ErrorCode::NO_ERROR; 138 } 139 UpdateClient(sptr<IRemoteObject> inputClient,bool isShowKeyboard)140 void PerUserSession::UpdateClient(sptr<IRemoteObject> inputClient, bool isShowKeyboard) 141 { 142 IMSA_HILOGD("PerUserSession::start"); 143 std::lock_guard<std::recursive_mutex> lock(mtx); 144 auto it = mapClients.find(inputClient); 145 if (it == mapClients.end()) { 146 IMSA_HILOGE("PerUserSession::client not found"); 147 return; 148 } 149 it->second->isShowKeyBoard = isShowKeyboard; 150 } 151 152 /*! Remove an input client 153 \param inputClient remote object handler of the input client 154 \return ErrorCode::NO_ERROR no error 155 \return ErrorCode::ERROR_CLIENT_NOT_FOUND client is not found 156 */ RemoveClient(sptr<IRemoteObject> inputClient)157 void PerUserSession::RemoveClient(sptr<IRemoteObject> inputClient) 158 { 159 IMSA_HILOGD("PerUserSession::RemoveClient"); 160 auto client = GetCurrentClient(); 161 if (client != nullptr && client->AsObject() == inputClient) { 162 SetCurrentClient(nullptr); 163 } 164 std::lock_guard<std::recursive_mutex> lock(mtx); 165 auto it = mapClients.find(inputClient); 166 if (it == mapClients.end()) { 167 IMSA_HILOGE("PerUserSession::RemoveClient client not found"); 168 return; 169 } 170 auto info = it->second; 171 info->client->AsObject()->RemoveDeathRecipient(info->deathRecipient); 172 mapClients.erase(it); 173 } 174 175 /*! Show keyboard 176 \param inputClient the remote object handler of the input client. 177 \return ErrorCode::NO_ERROR no error 178 \return ErrorCode::ERROR_IME_NOT_STARTED ime not started 179 \return ErrorCode::ERROR_KBD_IS_OCCUPIED keyboard is showing by other client 180 \return ErrorCode::ERROR_CLIENT_NOT_FOUND the input client is not found 181 \return ErrorCode::ERROR_IME_START_FAILED failed to start input method service 182 \return ErrorCode::ERROR_KBD_SHOW_FAILED failed to show keyboard 183 \return other errors returned by binder driver 184 */ ShowKeyboard(const sptr<IInputClient> & inputClient,bool isShowKeyboard)185 int PerUserSession::ShowKeyboard(const sptr<IInputClient>& inputClient, bool isShowKeyboard) 186 { 187 IMSA_HILOGD("PerUserSession::ShowKeyboard"); 188 auto clientInfo = GetClientInfo(inputClient->AsObject()); 189 int index = GetImeIndex(inputClient); 190 if (index == -1 || clientInfo == nullptr) { 191 IMSA_HILOGE("PerUserSession::ShowKeyboard Aborted! index = -1 or clientInfo is nullptr"); 192 return ErrorCode::ERROR_CLIENT_NOT_FOUND; 193 } 194 sptr<IInputMethodCore> core = GetImsCore(CURRENT_IME); 195 if (core == nullptr) { 196 IMSA_HILOGE("PerUserSession::ShowKeyboard Aborted! imsCore[%{public}d] is nullptr", index); 197 return ErrorCode::ERROR_NULL_POINTER; 198 } 199 200 auto subProperty = GetCurrentSubProperty(); 201 int32_t ret = core->showKeyboard(clientInfo->channel, isShowKeyboard, subProperty); 202 if (ret != ErrorCode::NO_ERROR) { 203 IMSA_HILOGE("PerUserSession::showKeyboard failed ret: %{public}d", ret); 204 return ErrorCode::ERROR_KBD_SHOW_FAILED; 205 } 206 UpdateClient(inputClient->AsObject(), isShowKeyboard); 207 SetCurrentClient(inputClient); 208 return ErrorCode::NO_ERROR; 209 } 210 211 /*! hide keyboard 212 \param inputClient the remote object handler of the input client. 213 \return ErrorCode::NO_ERROR no error 214 \return ErrorCode::ERROR_IME_NOT_STARTED ime not started 215 \return ErrorCode::ERROR_KBD_IS_NOT_SHOWING keyboard has not been showing 216 \return ErrorCode::ERROR_CLIENT_NOT_FOUND the input client is not found 217 \return ErrorCode::ERROR_KBD_HIDE_FAILED failed to hide keyboard 218 \return other errors returned by binder driver 219 */ HideKeyboard(const sptr<IInputClient> & inputClient)220 int PerUserSession::HideKeyboard(const sptr<IInputClient>& inputClient) 221 { 222 IMSA_HILOGD("PerUserSession::HideKeyboard"); 223 sptr<IInputMethodCore> core = GetImsCore(CURRENT_IME); 224 if (core == nullptr) { 225 IMSA_HILOGE("PerUserSession::HideKeyboard imsCore is nullptr"); 226 return ErrorCode::ERROR_IME_NOT_STARTED; 227 } 228 UpdateClient(inputClient->AsObject(), false); 229 bool ret = core->hideKeyboard(1); 230 if (!ret) { 231 IMSA_HILOGE("PerUserSession::HideKeyboard [imsCore->hideKeyboard] failed"); 232 return ErrorCode::ERROR_KBD_HIDE_FAILED; 233 } 234 return ErrorCode::NO_ERROR; 235 } 236 237 /*! Handle the situation a remote input client died\n 238 It's called when a remote input client died 239 \param the remote object handler of the input client died. 240 */ OnClientDied(sptr<IInputClient> remote)241 void PerUserSession::OnClientDied(sptr<IInputClient> remote) 242 { 243 IMSA_HILOGI("PerUserSession::OnClientDied Start...[%{public}d]\n", userId_); 244 sptr<IInputClient> client = GetCurrentClient(); 245 if (client == nullptr) { 246 IMSA_HILOGE("current client is nullptr"); 247 RemoveClient(remote->AsObject()); 248 return; 249 } 250 if (client->AsObject() == remote->AsObject()) { 251 int ret = HideKeyboard(client); 252 IMSA_HILOGI("hide keyboard ret: %{public}s", ErrorCode::ToString(ret)); 253 } 254 RemoveClient(remote->AsObject()); 255 } 256 257 /*! Handle the situation a input method service died\n 258 It's called when an input method service died 259 \param the remote object handler of input method service who died. 260 */ OnImsDied(sptr<IInputMethodCore> remote)261 void PerUserSession::OnImsDied(sptr<IInputMethodCore> remote) 262 { 263 (void)remote; 264 IMSA_HILOGI("Start...[%{public}d]\n", userId_); 265 int index = 0; 266 for (int i = 0; i < MAX_IME; i++) { 267 sptr<IInputMethodCore> core = GetImsCore(i); 268 if (core == remote) { 269 index = i; 270 break; 271 } 272 } 273 ClearImeData(index); 274 if (!IsRestartIme(index)) { 275 IMSA_HILOGI("Restart ime over max num"); 276 return; 277 } 278 IMSA_HILOGI("IME died. Restart input method...[%{public}d]\n", userId_); 279 auto cfg = ImeCfgManager::GetInstance().GetImeCfg(userId_); 280 auto ¤tIme = cfg.currentIme; 281 if (currentIme.empty()) { 282 IMSA_HILOGE("currentIme is empty"); 283 return; 284 } 285 auto *parcel = new (std::nothrow) MessageParcel(); 286 if (parcel == nullptr) { 287 IMSA_HILOGE("parcel is nullptr"); 288 return; 289 } 290 parcel->WriteString(currentIme); 291 auto *msg = new (std::nothrow) Message(MSG_ID_START_INPUT_SERVICE, parcel); 292 if (msg == nullptr) { 293 IMSA_HILOGE("msg is nullptr"); 294 delete parcel; 295 return; 296 } 297 usleep(MAX_RESET_WAIT_TIME); 298 MessageHandler::Instance()->SendMessage(msg); 299 IMSA_HILOGD("End...[%{public}d]\n", userId_); 300 } 301 UpdateCurrentUserId(int32_t userId)302 void PerUserSession::UpdateCurrentUserId(int32_t userId) 303 { 304 userId_ = userId; 305 } 306 307 /*! Hide current keyboard 308 \param flag the flag to hide keyboard. 309 */ OnHideKeyboardSelf(int flags)310 int PerUserSession::OnHideKeyboardSelf(int flags) 311 { 312 IMSA_HILOGD("PerUserSession::OnHideKeyboardSelf"); 313 (void)flags; 314 sptr<IInputClient> client = GetCurrentClient(); 315 if (client == nullptr) { 316 IMSA_HILOGE("current client is nullptr"); 317 return ErrorCode::ERROR_CLIENT_NOT_FOUND; 318 } 319 return HideKeyboard(client); 320 } 321 OnShowKeyboardSelf()322 int PerUserSession::OnShowKeyboardSelf() 323 { 324 IMSA_HILOGD("PerUserSession::OnShowKeyboardSelf"); 325 sptr<IInputClient> client = GetCurrentClient(); 326 if (client == nullptr) { 327 IMSA_HILOGE("current client is nullptr"); 328 return ErrorCode::ERROR_CLIENT_NOT_FOUND; 329 } 330 return ShowKeyboard(client, true); 331 } 332 333 /*! Get ime index for the input client 334 \param inputClient the remote object handler of an input client. 335 \return 0 - default ime 336 \return 1 - security ime 337 \return -1 - input client is not found 338 */ GetImeIndex(const sptr<IInputClient> & inputClient)339 int PerUserSession::GetImeIndex(const sptr<IInputClient>& inputClient) 340 { 341 if (inputClient == nullptr) { 342 IMSA_HILOGW("PerUserSession::GetImeIndex inputClient is nullptr"); 343 return -1; 344 } 345 346 auto clientInfo = GetClientInfo(inputClient->AsObject()); 347 if (clientInfo == nullptr) { 348 IMSA_HILOGW("PerUserSession::GetImeIndex clientInfo is nullptr"); 349 return -1; 350 } 351 352 if (clientInfo->attribute.GetSecurityFlag()) { 353 return SECURITY_IME; 354 } 355 return CURRENT_IME; 356 } 357 358 /*! Get ClientInfo 359 \param inputClient the IRemoteObject remote handler of given input client 360 \return a pointer of ClientInfo if client is found 361 \n null if client is not found 362 \note the clientInfo pointer should not be freed by caller 363 */ GetClientInfo(sptr<IRemoteObject> inputClient)364 std::shared_ptr<ClientInfo> PerUserSession::GetClientInfo(sptr<IRemoteObject> inputClient) 365 { 366 std::lock_guard<std::recursive_mutex> lock(mtx); 367 if (inputClient == nullptr) { 368 IMSA_HILOGE("PerUserSession::GetClientInfo inputClient is nullptr"); 369 return nullptr; 370 } 371 auto it = mapClients.find(inputClient); 372 if (it == mapClients.end()) { 373 IMSA_HILOGE("PerUserSession::GetClientInfo client not found"); 374 return nullptr; 375 } 376 return it->second; 377 } 378 379 /*! Prepare input. Called by an input client. 380 \n Run in work thread of this user 381 \param the parameters from remote client 382 \return ErrorCode 383 */ OnPrepareInput(const ClientInfo & clientInfo)384 int32_t PerUserSession::OnPrepareInput(const ClientInfo &clientInfo) 385 { 386 IMSA_HILOGD("PerUserSession::OnPrepareInput Start\n"); 387 int ret = AddClient(clientInfo.client->AsObject(), clientInfo); 388 if (ret != ErrorCode::NO_ERROR) { 389 IMSA_HILOGE("PerUserSession::OnPrepareInput %{public}s", ErrorCode::ToString(ret)); 390 return ErrorCode::ERROR_ADD_CLIENT_FAILED; 391 } 392 SendAgentToSingleClient(clientInfo); 393 return ErrorCode::NO_ERROR; 394 } 395 SendAgentToSingleClient(const ClientInfo & clientInfo)396 void PerUserSession::SendAgentToSingleClient(const ClientInfo &clientInfo) 397 { 398 IMSA_HILOGD("PerUserSession::SendAgentToSingleClient"); 399 if (imsAgent == nullptr) { 400 IMSA_HILOGI("PerUserSession::SendAgentToSingleClient imsAgent is nullptr"); 401 CreateComponentFailed(userId_, ErrorCode::ERROR_NULL_POINTER); 402 return; 403 } 404 clientInfo.client->onInputReady(imsAgent); 405 } 406 407 /*! Release input. Called by an input client. 408 \n Run in work thread of this user 409 \param the parameters from remote client 410 \return ErrorCode 411 */ OnReleaseInput(sptr<IInputClient> client)412 int32_t PerUserSession::OnReleaseInput(sptr<IInputClient> client) 413 { 414 IMSA_HILOGI("PerUserSession::OnReleaseInput Start"); 415 RemoveClient(client->AsObject()); 416 auto ret = HideKeyboard(client); 417 if (ret != ErrorCode::NO_ERROR) { 418 IMSA_HILOGE("failed to hide keyboard ret %{public}d", ret); 419 return ret; 420 } 421 IMSA_HILOGD("PerUserSession::OnReleaseInput End...[%{public}d]\n", userId_); 422 return ErrorCode::NO_ERROR; 423 } 424 425 /*! Start input. Called by an input client. 426 \n Run in work thread of this user 427 \param the parameters from remote client 428 \return ErrorCode 429 */ OnStartInput(sptr<IInputClient> client,bool isShowKeyboard)430 int32_t PerUserSession::OnStartInput(sptr<IInputClient> client, bool isShowKeyboard) 431 { 432 IMSA_HILOGI("PerUserSession::OnStartInput"); 433 return ShowKeyboard(client, isShowKeyboard); 434 } 435 OnSetCoreAndAgent(sptr<IInputMethodCore> core,sptr<IInputMethodAgent> agent)436 int32_t PerUserSession::OnSetCoreAndAgent(sptr<IInputMethodCore> core, sptr<IInputMethodAgent> agent) 437 { 438 IMSA_HILOGD("PerUserSession::SetCoreAndAgent Start\n"); 439 if (core == nullptr || agent == nullptr) { 440 IMSA_HILOGE("PerUserSession::SetCoreAndAgent core or agent nullptr"); 441 return ErrorCode::ERROR_EX_NULL_POINTER; 442 } 443 SetImsCore(CURRENT_IME, core); 444 if (imsDeathRecipient != nullptr) { 445 imsDeathRecipient->SetDeathRecipient([this, core](const wptr<IRemoteObject> &) { this->OnImsDied(core); }); 446 bool ret = core->AsObject()->AddDeathRecipient(imsDeathRecipient); 447 IMSA_HILOGI("Add death recipient %{public}s", ret ? "success" : "failed"); 448 } 449 imsAgent = agent; 450 InitInputControlChannel(); 451 SendAgentToAllClients(); 452 auto client = GetCurrentClient(); 453 if (client != nullptr) { 454 auto it = mapClients.find(client->AsObject()); 455 if (it != mapClients.end()) { 456 IMSA_HILOGI("PerUserSession::Bind IMC to IMA"); 457 OnStartInput(it->second->client, it->second->isShowKeyBoard); 458 } 459 } 460 return ErrorCode::NO_ERROR; 461 } 462 SendAgentToAllClients()463 void PerUserSession::SendAgentToAllClients() 464 { 465 IMSA_HILOGD("PerUserSession::SendAgentToAllClients"); 466 std::lock_guard<std::recursive_mutex> lock(mtx); 467 if (imsAgent == nullptr) { 468 IMSA_HILOGE("PerUserSession::SendAgentToAllClients imsAgent is nullptr"); 469 return; 470 } 471 472 for (auto it = mapClients.begin(); it != mapClients.end(); ++it) { 473 auto clientInfo = it->second; 474 if (clientInfo != nullptr) { 475 clientInfo->client->onInputReady(imsAgent); 476 } 477 } 478 } 479 InitInputControlChannel()480 void PerUserSession::InitInputControlChannel() 481 { 482 IMSA_HILOGD("PerUserSession::InitInputControlChannel"); 483 sptr<IInputControlChannel> inputControlChannel = new InputControlChannelStub(userId_); 484 sptr<IInputMethodCore> core = GetImsCore(CURRENT_IME); 485 if (core == nullptr) { 486 IMSA_HILOGE("PerUserSession::InitInputControlChannel core is nullptr"); 487 return; 488 } 489 auto cfg = ImeCfgManager::GetInstance().GetImeCfg(userId_); 490 int ret = core->InitInputControlChannel(inputControlChannel, cfg.currentIme); 491 if (ret != ErrorCode::NO_ERROR) { 492 IMSA_HILOGI("PerUserSession::InitInputControlChannel fail %{public}s", ErrorCode::ToString(ret)); 493 } 494 } 495 496 /*! Stop input. Called by an input client. 497 \n Run in work thread of this user 498 \param the parameters from remote client 499 \return ErrorCode 500 */ OnStopInput(sptr<IInputClient> client)501 int32_t PerUserSession::OnStopInput(sptr<IInputClient> client) 502 { 503 IMSA_HILOGD("PerUserSession::OnStopInput"); 504 return HideKeyboard(client); 505 } 506 StopInputService(std::string imeId)507 void PerUserSession::StopInputService(std::string imeId) 508 { 509 IMSA_HILOGI("PerUserSession::StopInputService"); 510 sptr<IInputMethodCore> core = GetImsCore(CURRENT_IME); 511 if (core == nullptr) { 512 IMSA_HILOGE("imsCore[0] is nullptr"); 513 return; 514 } 515 IMSA_HILOGI("Remove death recipient"); 516 core->AsObject()->RemoveDeathRecipient(imsDeathRecipient); 517 core->StopInputService(imeId); 518 } 519 IsRestartIme(uint32_t index)520 bool PerUserSession::IsRestartIme(uint32_t index) 521 { 522 IMSA_HILOGD("PerUserSession::IsRestartIme"); 523 std::lock_guard<std::mutex> lock(resetLock); 524 auto now = time(nullptr); 525 if (difftime(now, manager[index].last) > IME_RESET_TIME_OUT) { 526 manager[index] = { 0, now }; 527 } 528 ++manager[index].num; 529 return manager[index].num <= MAX_RESTART_NUM; 530 } 531 ClearImeData(uint32_t index)532 void PerUserSession::ClearImeData(uint32_t index) 533 { 534 IMSA_HILOGI("Clear ime...index = %{public}d", index); 535 sptr<IInputMethodCore> core = GetImsCore(index); 536 if (core != nullptr) { 537 core->AsObject()->RemoveDeathRecipient(imsDeathRecipient); 538 SetImsCore(index, nullptr); 539 } 540 inputControlChannel[index] = nullptr; 541 } 542 SetCurrentClient(sptr<IInputClient> client)543 void PerUserSession::SetCurrentClient(sptr<IInputClient> client) 544 { 545 IMSA_HILOGI("set current client"); 546 std::lock_guard<std::mutex> lock(clientLock_); 547 currentClient = client; 548 } 549 GetCurrentClient()550 sptr<IInputClient> PerUserSession::GetCurrentClient() 551 { 552 std::lock_guard<std::mutex> lock(clientLock_); 553 return currentClient; 554 } 555 OnInputMethodSwitched(const Property & property,const SubProperty & subProperty)556 void PerUserSession::OnInputMethodSwitched(const Property &property, const SubProperty &subProperty) 557 { 558 IMSA_HILOGD("PerUserSession::OnInputMethodSwitched"); 559 std::lock_guard<std::recursive_mutex> lock(mtx); 560 for (const auto &client : mapClients) { 561 auto clientInfo = client.second; 562 if (clientInfo == nullptr) { 563 IMSA_HILOGD("PerUserSession::clientInfo is nullptr"); 564 continue; 565 } 566 int32_t ret = clientInfo->client->OnSwitchInput(property, subProperty); 567 if (ret != ErrorCode::NO_ERROR) { 568 IMSA_HILOGE("OnSwitchInput failed, ret: %{public}d, uid: %{public}d", ret, 569 static_cast<int32_t>(clientInfo->uid)); 570 continue; 571 } 572 } 573 if (subProperty.name != currentSubProperty.name) { 574 SetCurrentSubProperty(subProperty); 575 return; 576 } 577 SetCurrentSubProperty(subProperty); 578 sptr<IInputMethodCore> core = GetImsCore(CURRENT_IME); 579 if (core == nullptr) { 580 IMSA_HILOGE("imsCore is nullptr"); 581 return; 582 } 583 int32_t ret = core->SetSubtype(subProperty); 584 if (ret != ErrorCode::NO_ERROR) { 585 IMSA_HILOGE("PerUserSession::SetSubtype failed, ret %{public}d", ret); 586 } 587 } 588 GetCurrentSubProperty()589 SubProperty PerUserSession::GetCurrentSubProperty() 590 { 591 IMSA_HILOGD("PerUserSession::GetCurrentSubProperty"); 592 std::lock_guard<std::mutex> lock(propertyLock_); 593 return currentSubProperty; 594 } 595 SetCurrentSubProperty(const SubProperty & subProperty)596 void PerUserSession::SetCurrentSubProperty(const SubProperty &subProperty) 597 { 598 IMSA_HILOGD("PerUserSession::SetCurrentSubProperty"); 599 std::lock_guard<std::mutex> lock(propertyLock_); 600 currentSubProperty = subProperty; 601 } 602 GetImsCore(int32_t index)603 sptr<IInputMethodCore> PerUserSession::GetImsCore(int32_t index) 604 { 605 std::lock_guard<std::mutex> lock(imsCoreLock_); 606 if (!IsValid(index)) { 607 return nullptr; 608 } 609 return imsCore[index]; 610 } 611 SetImsCore(int32_t index,sptr<IInputMethodCore> core)612 void PerUserSession::SetImsCore(int32_t index, sptr<IInputMethodCore> core) 613 { 614 std::lock_guard<std::mutex> lock(imsCoreLock_); 615 if (!IsValid(index)) { 616 return; 617 } 618 imsCore[index] = core; 619 } 620 } // namespace MiscServices 621 } // namespace OHOS 622