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