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 <chrono>
19 #include <vector>
20
21 #include "ability_manager_client.h"
22 #include "app_mgr_client.h"
23 #include "element_name.h"
24 #include "identity_checker_impl.h"
25 #include "ime_cfg_manager.h"
26 #include "ime_connection.h"
27 #include "ime_info_inquirer.h"
28 #include "input_control_channel_stub.h"
29 #include "input_type_manager.h"
30 #include "ipc_skeleton.h"
31 #include "iservice_registry.h"
32 #include "mem_mgr_client.h"
33 #include "message_parcel.h"
34 #include "os_account_adapter.h"
35 #include "parcel.h"
36 #include "running_process_info.h"
37 #include "scene_board_judgement.h"
38 #include "security_mode_parser.h"
39 #include "system_ability_definition.h"
40 #include "unistd.h"
41 #include "wms_connection_observer.h"
42
43 namespace OHOS {
44 namespace MiscServices {
45 using namespace std::chrono;
46 using namespace MessageID;
47 using namespace OHOS::AppExecFwk;
48 constexpr int64_t INVALID_PID = -1;
49 constexpr uint32_t STOP_IME_TIME = 600;
50 constexpr const char *STRICT_MODE = "strictMode";
51 constexpr const char *ISOLATED_SANDBOX = "isolatedSandbox";
52 constexpr uint32_t CHECK_IME_RUNNING_RETRY_INTERVAL = 60;
53 constexpr uint32_t CHECK_IME_RUNNING_RETRY_TIMES = 10;
PerUserSession(int userId)54 PerUserSession::PerUserSession(int userId) : userId_(userId)
55 {
56 }
57
PerUserSession(int32_t userId,const std::shared_ptr<AppExecFwk::EventHandler> & eventHandler)58 PerUserSession::PerUserSession(int32_t userId, const std::shared_ptr<AppExecFwk::EventHandler> &eventHandler)
59 : userId_(userId), eventHandler_(eventHandler)
60 {
61 // if bms not start, AppMgrClient::GetProcessRunningInfosByUserId will blocked
62 if (IsReady(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID)) {
63 auto bundleNames = ImeInfoInquirer::GetInstance().GetRunningIme(userId_);
64 if (!bundleNames.empty()) {
65 runningIme_ = bundleNames[0]; // one user only has one ime at present
66 }
67 }
68 }
69
~PerUserSession()70 PerUserSession::~PerUserSession()
71 {
72 }
73
AddClientInfo(sptr<IRemoteObject> inputClient,const InputClientInfo & clientInfo,ClientAddEvent event)74 int PerUserSession::AddClientInfo(
75 sptr<IRemoteObject> inputClient, const InputClientInfo &clientInfo, ClientAddEvent event)
76 {
77 IMSA_HILOGD("PerUserSession start.");
78 auto cacheInfo = GetClientInfo(inputClient);
79 if (cacheInfo != nullptr) {
80 IMSA_HILOGD("info is existed.");
81 if (cacheInfo->uiExtensionTokenId == IMF_INVALID_TOKENID &&
82 clientInfo.uiExtensionTokenId != IMF_INVALID_TOKENID) {
83 UpdateClientInfo(inputClient, { { UpdateFlag::UIEXTENSION_TOKENID, clientInfo.uiExtensionTokenId } });
84 }
85 UpdateClientInfo(inputClient, { { UpdateFlag::TEXT_CONFIG, clientInfo.config } });
86 if (event == START_LISTENING) {
87 UpdateClientInfo(inputClient, { { UpdateFlag::EVENTFLAG, clientInfo.eventFlag } });
88 }
89 return ErrorCode::NO_ERROR;
90 }
91 auto info = std::make_shared<InputClientInfo>(clientInfo);
92 std::weak_ptr<InputClientInfo> weakClientInfo = info;
93 info->deathRecipient->SetDeathRecipient([this, weakClientInfo](const wptr<IRemoteObject> &) {
94 auto clientInfo = weakClientInfo.lock();
95 if (clientInfo == nullptr) {
96 IMSA_HILOGD("clientInfo is nullptr.");
97 return;
98 }
99 this->OnClientDied(clientInfo->client);
100 });
101 auto obj = info->client->AsObject();
102 if (obj == nullptr) {
103 IMSA_HILOGE("client obj is nullptr!");
104 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
105 }
106 if (obj->IsProxyObject() && !obj->AddDeathRecipient(info->deathRecipient)) {
107 IMSA_HILOGE("failed to add client death recipient!");
108 return ErrorCode::ERROR_CLIENT_ADD_FAILED;
109 }
110 std::lock_guard<std::recursive_mutex> lock(mtx);
111 mapClients_.insert({ inputClient, info });
112 IMSA_HILOGI("add client end.");
113 return ErrorCode::NO_ERROR;
114 }
115
RemoveClientInfo(const sptr<IRemoteObject> & client,bool isClientDied)116 void PerUserSession::RemoveClientInfo(const sptr<IRemoteObject> &client, bool isClientDied)
117 {
118 std::lock_guard<std::recursive_mutex> lock(mtx);
119 auto clientInfo = GetClientInfo(client);
120 if (clientInfo == nullptr) {
121 IMSA_HILOGD("client already removed.");
122 return;
123 }
124 // if client is subscriber and the release is not because of the client died, do not remove
125 if (clientInfo->eventFlag != NO_EVENT_ON && !isClientDied) {
126 IMSA_HILOGD("is subscriber, do not remove.");
127 auto isShowKeyboard = false;
128 auto bindImeType = ImeType::NONE;
129 UpdateClientInfo(
130 client, { { UpdateFlag::BINDIMETYPE, bindImeType }, { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
131 return;
132 }
133 if (clientInfo->deathRecipient != nullptr) {
134 IMSA_HILOGD("deathRecipient remove.");
135 client->RemoveDeathRecipient(clientInfo->deathRecipient);
136 }
137 mapClients_.erase(client);
138 IMSA_HILOGI("client[%{public}d] is removed.", clientInfo->pid);
139 }
140
UpdateClientInfo(const sptr<IRemoteObject> & client,const std::unordered_map<UpdateFlag,std::variant<bool,uint32_t,ImeType,ClientState,TextTotalConfig>> & updateInfos)141 void PerUserSession::UpdateClientInfo(const sptr<IRemoteObject> &client, const std::unordered_map<UpdateFlag,
142 std::variant<bool, uint32_t, ImeType, ClientState, TextTotalConfig>> &updateInfos)
143 {
144 if (client == nullptr) {
145 IMSA_HILOGE("client is nullptr!");
146 return;
147 }
148 auto info = GetClientInfo(client);
149 if (info == nullptr) {
150 IMSA_HILOGE("client info is not exist!");
151 return;
152 }
153 for (const auto &updateInfo : updateInfos) {
154 switch (updateInfo.first) {
155 case UpdateFlag::EVENTFLAG: {
156 info->eventFlag = std::get<uint32_t>(updateInfo.second);
157 break;
158 }
159 case UpdateFlag::ISSHOWKEYBOARD: {
160 info->isShowKeyboard = std::get<bool>(updateInfo.second);
161 break;
162 }
163 case UpdateFlag::BINDIMETYPE: {
164 info->bindImeType = std::get<ImeType>(updateInfo.second);
165 break;
166 }
167 case UpdateFlag::STATE: {
168 info->state = std::get<ClientState>(updateInfo.second);
169 break;
170 }
171 case UpdateFlag::TEXT_CONFIG: {
172 info->config = std::get<TextTotalConfig>(updateInfo.second);
173 break;
174 }
175 case UpdateFlag::UIEXTENSION_TOKENID: {
176 info->uiExtensionTokenId = std::get<uint32_t>(updateInfo.second);
177 break;
178 }
179 default:
180 break;
181 }
182 }
183 }
184
HideKeyboard(const sptr<IInputClient> & currentClient)185 int32_t PerUserSession::HideKeyboard(const sptr<IInputClient> ¤tClient)
186 {
187 IMSA_HILOGD("PerUserSession::HideKeyboard start.");
188 auto clientInfo = GetClientInfo(currentClient->AsObject());
189 if (clientInfo == nullptr) {
190 IMSA_HILOGE("client info is nullptr!");
191 return ErrorCode::ERROR_CLIENT_NOT_FOUND;
192 }
193 auto data = GetReadyImeData(clientInfo->bindImeType);
194 if (data == nullptr) {
195 IMSA_HILOGE("ime: %{public}d is not exist!", clientInfo->bindImeType);
196 return ErrorCode::ERROR_IME_NOT_STARTED;
197 }
198 auto ret = RequestIme(data, RequestType::NORMAL, [&data] { return data->core->HideKeyboard(); });
199 if (ret != ErrorCode::NO_ERROR) {
200 IMSA_HILOGE("failed to hide keyboard, ret: %{public}d!", ret);
201 return ErrorCode::ERROR_KBD_HIDE_FAILED;
202 }
203 bool isShowKeyboard = false;
204 UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
205 RestoreCurrentImeSubType();
206 return ErrorCode::NO_ERROR;
207 }
208
ShowKeyboard(const sptr<IInputClient> & currentClient)209 int32_t PerUserSession::ShowKeyboard(const sptr<IInputClient> ¤tClient)
210 {
211 IMSA_HILOGD("PerUserSession::ShowKeyboard start.");
212 auto clientInfo = GetClientInfo(currentClient->AsObject());
213 if (clientInfo == nullptr) {
214 IMSA_HILOGE("client info is nullptr!");
215 return ErrorCode::ERROR_CLIENT_NOT_FOUND;
216 }
217 auto data = GetReadyImeData(clientInfo->bindImeType);
218 if (data == nullptr) {
219 IMSA_HILOGE("ime: %{public}d is not exist!", clientInfo->bindImeType);
220 return ErrorCode::ERROR_IME_NOT_STARTED;
221 }
222 auto ret = RequestIme(data, RequestType::REQUEST_SHOW, [&data] { return data->core->ShowKeyboard(); });
223 if (ret != ErrorCode::NO_ERROR) {
224 IMSA_HILOGE("failed to show keyboard, ret: %{public}d!", ret);
225 return ErrorCode::ERROR_KBD_SHOW_FAILED;
226 }
227 bool isShowKeyboard = true;
228 UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, isShowKeyboard } });
229 return ErrorCode::NO_ERROR;
230 }
231
232 /** Handle the situation a remote input client died.
233 * It's called when a remote input client died
234 * @param the remote object handler of the input client died.
235 */
OnClientDied(sptr<IInputClient> remote)236 void PerUserSession::OnClientDied(sptr<IInputClient> remote)
237 {
238 if (remote == nullptr) {
239 return;
240 }
241 auto clientInfo = GetClientInfo(remote->AsObject());
242 IMSA_HILOGI("userId: %{public}d.", userId_);
243 if (IsSameClient(remote, GetCurrentClient())) {
244 if (clientInfo != nullptr) {
245 StopImeInput(clientInfo->bindImeType, clientInfo->channel);
246 }
247 SetCurrentClient(nullptr);
248 RestoreCurrentImeSubType();
249 }
250 if (IsSameClient(remote, GetInactiveClient())) {
251 if (clientInfo != nullptr) {
252 StopImeInput(clientInfo->bindImeType, clientInfo->channel);
253 }
254 SetInactiveClient(nullptr);
255 RestoreCurrentImeSubType();
256 }
257 RemoveClientInfo(remote->AsObject(), true);
258 }
259
260 /** Handle the situation that an ime died
261 * It's called when an ime died
262 * @param the remote object handler of the ime who died.
263 */
OnImeDied(const sptr<IInputMethodCore> & remote,ImeType type)264 void PerUserSession::OnImeDied(const sptr<IInputMethodCore> &remote, ImeType type)
265 {
266 if (remote == nullptr) {
267 return;
268 }
269 IMSA_HILOGI("type: %{public}d.", type);
270 auto imeData = GetImeData(type);
271 if (imeData != nullptr && imeData->imeStatus == ImeStatus::EXITING) {
272 RemoveImeData(type, true);
273 InputTypeManager::GetInstance().Set(false);
274 NotifyImeStopFinished();
275 IMSA_HILOGI("%{public}d not current imeData.", type);
276 return;
277 }
278 RemoveImeData(type, true);
279 if (!OsAccountAdapter::IsOsAccountForeground(userId_)) {
280 IMSA_HILOGW("userId:%{public}d in background, no need to restart ime.", userId_);
281 return;
282 }
283 auto client = GetCurrentClient();
284 auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
285 if (clientInfo != nullptr && clientInfo->bindImeType == type) {
286 StopClientInput(clientInfo);
287 if (type == ImeType::IME) {
288 StartImeInImeDied();
289 }
290 return;
291 }
292 auto currentImeInfo = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
293 if (currentImeInfo == nullptr) {
294 IMSA_HILOGE("currentImeInfo is nullptr!");
295 return;
296 }
297 auto defaultImeInfo = ImeInfoInquirer::GetInstance().GetDefaultImeCfgProp();
298 if (defaultImeInfo == nullptr) {
299 IMSA_HILOGE("defaultImeInfo is nullptr!");
300 return;
301 }
302 if (type == ImeType::IME && currentImeInfo->bundleName == defaultImeInfo->name) {
303 StartImeInImeDied();
304 }
305 }
306
RemoveIme(const sptr<IInputMethodCore> & core,ImeType type)307 int32_t PerUserSession::RemoveIme(const sptr<IInputMethodCore> &core, ImeType type)
308 {
309 if (core == nullptr) {
310 return ErrorCode::ERROR_NULL_POINTER;
311 }
312 auto data = GetReadyImeData(type);
313 if (data == nullptr || data->core->AsObject() != core->AsObject()) {
314 return ErrorCode::ERROR_IME_NOT_STARTED;
315 }
316
317 auto client = GetCurrentClient();
318 auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
319 if (clientInfo != nullptr && clientInfo->bindImeType == type) {
320 UnBindClientWithIme(clientInfo);
321 }
322 RemoveImeData(type, true);
323 return ErrorCode::NO_ERROR;
324 }
325
OnHideCurrentInput()326 int32_t PerUserSession::OnHideCurrentInput()
327 {
328 sptr<IInputClient> client = GetCurrentClient();
329 if (client == nullptr) {
330 IMSA_HILOGE("current client is nullptr!");
331 return ErrorCode::ERROR_CLIENT_NOT_FOUND;
332 }
333 return HideKeyboard(client);
334 }
335
OnShowCurrentInput()336 int32_t PerUserSession::OnShowCurrentInput()
337 {
338 IMSA_HILOGD("PerUserSession::OnShowCurrentInput start.");
339 sptr<IInputClient> client = GetCurrentClient();
340 if (client == nullptr) {
341 IMSA_HILOGE("current client is nullptr!");
342 return ErrorCode::ERROR_CLIENT_NOT_FOUND;
343 }
344 return ShowKeyboard(client);
345 }
346
OnHideInput(sptr<IInputClient> client)347 int32_t PerUserSession::OnHideInput(sptr<IInputClient> client)
348 {
349 IMSA_HILOGD("PerUserSession::OnHideInput start.");
350 if (!IsSameClient(client, GetCurrentClient())) {
351 IMSA_HILOGE("client is not current client!");
352 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
353 }
354 return HideKeyboard(client);
355 }
356
OnShowInput(sptr<IInputClient> client)357 int32_t PerUserSession::OnShowInput(sptr<IInputClient> client)
358 {
359 IMSA_HILOGD("PerUserSession::OnShowInput start.");
360 if (!IsSameClient(client, GetCurrentClient())) {
361 IMSA_HILOGE("client is not current client!");
362 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
363 }
364 return ShowKeyboard(client);
365 }
366
OnHideSoftKeyBoardSelf()367 void PerUserSession::OnHideSoftKeyBoardSelf()
368 {
369 IMSA_HILOGD("PerUserSession::OnHideSoftKeyBoardSel start.");
370 sptr<IInputClient> client = GetCurrentClient();
371 if (client == nullptr) {
372 IMSA_HILOGE("current client is nullptr!");
373 return;
374 }
375 UpdateClientInfo(client->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, false } });
376 RestoreCurrentImeSubType();
377 }
378
OnRequestShowInput()379 int32_t PerUserSession::OnRequestShowInput()
380 {
381 IMSA_HILOGD("PerUserSession::OnRequestShowInput start.");
382 auto data = GetReadyImeData(ImeType::IME);
383 if (data == nullptr) {
384 IMSA_HILOGE("ime: %{public}d doesn't exist!", ImeType::IME);
385 return ErrorCode::ERROR_IME_NOT_STARTED;
386 }
387 auto ret = RequestIme(data, RequestType::REQUEST_SHOW, [&data] { return data->core->ShowKeyboard(); });
388 if (ret != ErrorCode::NO_ERROR) {
389 IMSA_HILOGE("failed to show keyboard, ret: %{public}d!", ret);
390 return ErrorCode::ERROR_KBD_SHOW_FAILED;
391 }
392 InputMethodSysEvent::GetInstance().ReportImeState(
393 ImeState::BIND, data->pid, ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
394 Memory::MemMgrClient::GetInstance().SetCritical(getpid(), true, INPUT_METHOD_SYSTEM_ABILITY_ID);
395 auto currentClient = GetCurrentClient();
396 if (currentClient != nullptr) {
397 UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, true } });
398 }
399 return ErrorCode::NO_ERROR;
400 }
401
OnRequestHideInput()402 int32_t PerUserSession::OnRequestHideInput()
403 {
404 IMSA_HILOGD("PerUserSession::OnRequestHideInput start.");
405 auto data = GetReadyImeData(ImeType::IME);
406 if (data != nullptr) {
407 auto ret = RequestIme(data, RequestType::REQUEST_HIDE, [&data] { return data->core->HideKeyboard(); });
408 if (ret != ErrorCode::NO_ERROR) {
409 IMSA_HILOGE("failed to hide keyboard, ret: %{public}d!", ret);
410 return ErrorCode::ERROR_KBD_HIDE_FAILED;
411 }
412 }
413
414 auto currentClient = GetCurrentClient();
415 if (currentClient != nullptr) {
416 UpdateClientInfo(currentClient->AsObject(), { { UpdateFlag::ISSHOWKEYBOARD, false } });
417 }
418 auto inactiveClient = GetInactiveClient();
419 if (inactiveClient != nullptr) {
420 RemoveClient(inactiveClient, false, true);
421 }
422 RestoreCurrentImeSubType();
423 return ErrorCode::NO_ERROR;
424 }
425
426 /** Get ClientInfo
427 * @param inputClient the IRemoteObject remote handler of given input client
428 * @return a pointer of ClientInfo if client is found
429 * null if client is not found
430 * @note the clientInfo pointer should not be freed by caller
431 */
GetClientInfo(sptr<IRemoteObject> inputClient)432 std::shared_ptr<InputClientInfo> PerUserSession::GetClientInfo(sptr<IRemoteObject> inputClient)
433 {
434 if (inputClient == nullptr) {
435 IMSA_HILOGE("inputClient is nullptr!");
436 return nullptr;
437 }
438 std::lock_guard<std::recursive_mutex> lock(mtx);
439 auto it = mapClients_.find(inputClient);
440 if (it == mapClients_.end()) {
441 IMSA_HILOGD("client not found.");
442 return nullptr;
443 }
444 return it->second;
445 }
446
GetClientInfo(pid_t pid)447 std::shared_ptr<InputClientInfo> PerUserSession::GetClientInfo(pid_t pid)
448 {
449 std::lock_guard<std::recursive_mutex> lock(mtx);
450 auto iter = std::find_if(
451 mapClients_.begin(), mapClients_.end(), [pid](const auto &mapClient) { return mapClient.second->pid == pid; });
452 if (iter == mapClients_.end()) {
453 IMSA_HILOGD("not found.");
454 return nullptr;
455 }
456 return iter->second;
457 }
458
OnPrepareInput(const InputClientInfo & clientInfo)459 int32_t PerUserSession::OnPrepareInput(const InputClientInfo &clientInfo)
460 {
461 IMSA_HILOGD("PerUserSession::OnPrepareInput start");
462 return AddClientInfo(clientInfo.client->AsObject(), clientInfo, PREPARE_INPUT);
463 }
464
465 /** Release input. Called by an input client.Run in work thread of this user
466 * @param the parameters from remote client
467 * @return ErrorCode
468 */
OnReleaseInput(const sptr<IInputClient> & client)469 int32_t PerUserSession::OnReleaseInput(const sptr<IInputClient> &client)
470 {
471 IMSA_HILOGD("PerUserSession::OnReleaseInput start");
472 return RemoveClient(client, true);
473 }
474
RemoveClient(const sptr<IInputClient> & client,bool isUnbindFromClient,bool isInactiveClient)475 int32_t PerUserSession::RemoveClient(const sptr<IInputClient> &client, bool isUnbindFromClient, bool isInactiveClient)
476 {
477 if (client == nullptr) {
478 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
479 }
480 // if client is current client, unbind firstly
481 auto clientInfo = GetClientInfo(client->AsObject());
482 if (IsSameClient(client, GetCurrentClient())) {
483 UnBindClientWithIme(clientInfo, isUnbindFromClient);
484 SetCurrentClient(nullptr);
485 RestoreCurrentImeSubType();
486 StopClientInput(clientInfo);
487 }
488 if (IsSameClient(client, GetInactiveClient())) {
489 SetInactiveClient(nullptr);
490 StopClientInput(clientInfo, isInactiveClient);
491 }
492 RemoveClientInfo(client->AsObject());
493 return ErrorCode::NO_ERROR;
494 }
495
DeactivateClient(const sptr<IInputClient> & client)496 void PerUserSession::DeactivateClient(const sptr<IInputClient> &client)
497 {
498 if (client == nullptr) {
499 IMSA_HILOGD("client is nullptr.");
500 return;
501 }
502 auto clientInfo = GetClientInfo(client->AsObject());
503 if (clientInfo == nullptr) {
504 return;
505 }
506 IMSA_HILOGI("deactivate client[%{public}d].", clientInfo->pid);
507 UpdateClientInfo(client->AsObject(), { { UpdateFlag::STATE, ClientState::INACTIVE } });
508 if (IsSameClient(client, GetCurrentClient())) {
509 SetCurrentClient(nullptr);
510 }
511 SetInactiveClient(client);
512 client->DeactivateClient();
513 if (InputTypeManager::GetInstance().IsStarted()) {
514 RestoreCurrentImeSubType();
515 return;
516 }
517 auto data = GetReadyImeData(clientInfo->bindImeType);
518 if (data == nullptr) {
519 IMSA_HILOGE("ime %{public}d doesn't exist!", clientInfo->bindImeType);
520 return;
521 }
522 RequestIme(data, RequestType::NORMAL, [&data, &clientInfo] {
523 data->core->OnClientInactive(clientInfo->channel);
524 return ErrorCode::NO_ERROR;
525 });
526 InputMethodSysEvent::GetInstance().ReportImeState(
527 ImeState::UNBIND, data->pid, ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
528 Memory::MemMgrClient::GetInstance().SetCritical(getpid(), false, INPUT_METHOD_SYSTEM_ABILITY_ID);
529 }
530
IsProxyImeEnable()531 bool PerUserSession::IsProxyImeEnable()
532 {
533 auto data = GetReadyImeData(ImeType::PROXY_IME);
534 return data != nullptr && data->core != nullptr && data->core->IsEnable();
535 }
536
OnStartInput(const InputClientInfo & inputClientInfo,sptr<IRemoteObject> & agent)537 int32_t PerUserSession::OnStartInput(const InputClientInfo &inputClientInfo, sptr<IRemoteObject> &agent)
538 {
539 const sptr<IInputClient> &client = inputClientInfo.client;
540 if (client == nullptr) {
541 IMSA_HILOGE("client is nullptr!");
542 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
543 }
544 auto clientInfo = GetClientInfo(client->AsObject());
545 if (clientInfo == nullptr) {
546 return ErrorCode::ERROR_CLIENT_NOT_FOUND;
547 }
548 IMSA_HILOGD("start input with keyboard[%{public}d].", inputClientInfo.isShowKeyboard);
549 if (IsSameClient(client, GetCurrentClient()) && IsImeBindChanged(clientInfo->bindImeType)) {
550 UnBindClientWithIme(clientInfo);
551 }
552 InputClientInfo infoTemp = *clientInfo;
553 infoTemp.isShowKeyboard = inputClientInfo.isShowKeyboard;
554 infoTemp.isNotifyInputStart = inputClientInfo.isNotifyInputStart;
555 infoTemp.needHide = inputClientInfo.needHide;
556 auto imeType = IsProxyImeEnable() ? ImeType::PROXY_IME : ImeType::IME;
557 int32_t ret = BindClientWithIme(std::make_shared<InputClientInfo>(infoTemp), imeType, true);
558 if (ret != ErrorCode::NO_ERROR) {
559 IMSA_HILOGE("bind failed, ret: %{public}d!", ret);
560 return ret;
561 }
562 auto data = GetReadyImeData(imeType);
563 if (data == nullptr || data->agent == nullptr) {
564 IMSA_HILOGE("data or agent is nullptr!");
565 return ErrorCode::ERROR_IME_NOT_STARTED;
566 }
567 agent = data->agent;
568 return ErrorCode::NO_ERROR;
569 }
570
BindClientWithIme(const std::shared_ptr<InputClientInfo> & clientInfo,ImeType type,bool isBindFromClient)571 int32_t PerUserSession::BindClientWithIme(
572 const std::shared_ptr<InputClientInfo> &clientInfo, ImeType type, bool isBindFromClient)
573 {
574 if (clientInfo == nullptr) {
575 IMSA_HILOGE("clientInfo is nullptr!");
576 return ErrorCode::ERROR_NULL_POINTER;
577 }
578 IMSA_HILOGD("imeType: %{public}d, isShowKeyboard: %{public}d, isBindFromClient: %{public}d.", type,
579 clientInfo->isShowKeyboard, isBindFromClient);
580 auto data = GetValidIme(type);
581 if (data == nullptr) {
582 return ErrorCode::ERROR_IME_NOT_STARTED;
583 }
584 auto ret = RequestIme(data, RequestType::START_INPUT,
585 [&data, &clientInfo, isBindFromClient]() { return data->core->StartInput(*clientInfo, isBindFromClient); });
586 if (ret != ErrorCode::NO_ERROR) {
587 IMSA_HILOGE("start input failed, ret: %{public}d!", ret);
588 return ErrorCode::ERROR_IME_START_INPUT_FAILED;
589 }
590 if (type == ImeType::IME) {
591 InputMethodSysEvent::GetInstance().ReportImeState(
592 ImeState::BIND, data->pid, ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
593 Memory::MemMgrClient::GetInstance().SetCritical(getpid(), true, INPUT_METHOD_SYSTEM_ABILITY_ID);
594 }
595 if (!isBindFromClient && clientInfo->client->OnInputReady(data->agent) != ErrorCode::NO_ERROR) {
596 IMSA_HILOGE("start client input failed, ret: %{public}d!", ret);
597 return ErrorCode::ERROR_EX_PARCELABLE;
598 }
599 UpdateClientInfo(clientInfo->client->AsObject(),
600 { { UpdateFlag::BINDIMETYPE, type }, { UpdateFlag::ISSHOWKEYBOARD, clientInfo->isShowKeyboard },
601 { UpdateFlag::STATE, ClientState::ACTIVE } });
602 ReplaceCurrentClient(clientInfo->client);
603 return ErrorCode::NO_ERROR;
604 }
605
UnBindClientWithIme(const std::shared_ptr<InputClientInfo> & currentClientInfo,bool isUnbindFromClient)606 void PerUserSession::UnBindClientWithIme(
607 const std::shared_ptr<InputClientInfo> ¤tClientInfo, bool isUnbindFromClient)
608 {
609 if (currentClientInfo == nullptr) {
610 return;
611 }
612 if (!isUnbindFromClient) {
613 IMSA_HILOGD("unbind from service.");
614 StopClientInput(currentClientInfo);
615 }
616 StopImeInput(currentClientInfo->bindImeType, currentClientInfo->channel);
617 }
618
StopClientInput(const std::shared_ptr<InputClientInfo> & clientInfo,bool isStopInactiveClient)619 void PerUserSession::StopClientInput(const std::shared_ptr<InputClientInfo> &clientInfo, bool isStopInactiveClient)
620 {
621 if (clientInfo == nullptr || clientInfo->client == nullptr) {
622 return;
623 }
624 auto ret = clientInfo->client->OnInputStop(isStopInactiveClient);
625 IMSA_HILOGI("isStopInactiveClient: %{public}d, client pid: %{public}d, ret: %{public}d.", isStopInactiveClient,
626 clientInfo->pid, ret);
627 }
628
StopImeInput(ImeType currentType,const sptr<IRemoteObject> & currentChannel)629 void PerUserSession::StopImeInput(ImeType currentType, const sptr<IRemoteObject> ¤tChannel)
630 {
631 auto data = GetReadyImeData(currentType);
632 if (data == nullptr) {
633 return;
634 }
635 auto ret = RequestIme(data, RequestType::STOP_INPUT,
636 [&data, ¤tChannel]() { return data->core->StopInput(currentChannel); });
637 IMSA_HILOGI("stop ime input, ret: %{public}d.", ret);
638 if (ret == ErrorCode::NO_ERROR && currentType == ImeType::IME) {
639 InputMethodSysEvent::GetInstance().ReportImeState(
640 ImeState::UNBIND, data->pid, ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName);
641 Memory::MemMgrClient::GetInstance().SetCritical(getpid(), false, INPUT_METHOD_SYSTEM_ABILITY_ID);
642 }
643 if (currentType == ImeType::IME) {
644 RestoreCurrentImeSubType();
645 }
646 }
647
OnSecurityChange(int32_t security)648 void PerUserSession::OnSecurityChange(int32_t security)
649 {
650 auto data = GetReadyImeData(ImeType::IME);
651 if (data == nullptr) {
652 IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
653 return;
654 }
655 auto ret =
656 RequestIme(data, RequestType::NORMAL, [&data, security] { return data->core->OnSecurityChange(security); });
657 IMSA_HILOGD("on security change, ret: %{public}d.", ret);
658 }
659
OnSetCoreAndAgent(const sptr<IInputMethodCore> & core,const sptr<IRemoteObject> & agent)660 int32_t PerUserSession::OnSetCoreAndAgent(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
661 {
662 IMSA_HILOGI("start.");
663 auto ret = UpdateImeData(core, agent, IPCSkeleton::GetCallingPid());
664 if (ret != ErrorCode::NO_ERROR) {
665 return ret;
666 }
667 auto action = GetImeAction(ImeEvent::SET_CORE_AND_AGENT);
668 if (action == ImeAction::DO_NOTHING) {
669 return ErrorCode::NO_ERROR;
670 }
671 if (action != ImeAction::DO_SET_CORE_AND_AGENT) {
672 return ErrorCode::ERROR_IME;
673 }
674 ret = InitInputControlChannel();
675 IMSA_HILOGI("init input control channel ret: %{public}d.", ret);
676 auto imeType = ImeType::IME;
677 auto client = GetCurrentClient();
678 auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
679 if (clientInfo != nullptr && IsImeStartInBind(clientInfo->bindImeType, imeType)) {
680 BindClientWithIme(clientInfo, imeType);
681 }
682 bool isStarted = true;
683 isImeStarted_.SetValue(isStarted);
684 return ErrorCode::NO_ERROR;
685 }
686
OnRegisterProxyIme(const sptr<IInputMethodCore> & core,const sptr<IRemoteObject> & agent)687 int32_t PerUserSession::OnRegisterProxyIme(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
688 {
689 IMSA_HILOGD("start.");
690 auto imeType = ImeType::PROXY_IME;
691 auto ret = AddImeData(imeType, core, agent, IPCSkeleton::GetCallingPid());
692 if (ret != ErrorCode::NO_ERROR) {
693 return ret;
694 }
695 auto client = GetCurrentClient();
696 auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
697 if (clientInfo != nullptr) {
698 if (IsProxyImeStartInBind(clientInfo->bindImeType, imeType)) {
699 BindClientWithIme(clientInfo, imeType);
700 }
701 if (IsProxyImeStartInImeBind(clientInfo->bindImeType, imeType)) {
702 UnBindClientWithIme(clientInfo);
703 BindClientWithIme(clientInfo, imeType);
704 }
705 }
706 return ErrorCode::NO_ERROR;
707 }
708
OnUnRegisteredProxyIme(UnRegisteredType type,const sptr<IInputMethodCore> & core)709 int32_t PerUserSession::OnUnRegisteredProxyIme(UnRegisteredType type, const sptr<IInputMethodCore> &core)
710 {
711 IMSA_HILOGD("proxy unregister type: %{public}d.", type);
712 // 0: stop proxy 1: switch to ima
713 if (type == UnRegisteredType::REMOVE_PROXY_IME) {
714 RemoveIme(core, ImeType::PROXY_IME);
715 return ErrorCode::NO_ERROR;
716 }
717 if (type == UnRegisteredType::SWITCH_PROXY_IME_TO_IME) {
718 auto client = GetCurrentClient();
719 auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
720 if (clientInfo == nullptr) {
721 IMSA_HILOGE("not found current client!");
722 return ErrorCode::ERROR_CLIENT_NOT_BOUND;
723 }
724 if (clientInfo->bindImeType == ImeType::PROXY_IME) {
725 UnBindClientWithIme(clientInfo);
726 }
727 InputClientInfo infoTemp = {
728 .isShowKeyboard = true, .client = clientInfo->client, .channel = clientInfo->channel
729 };
730 return BindClientWithIme(std::make_shared<InputClientInfo>(infoTemp), ImeType::IME);
731 }
732 return ErrorCode::ERROR_BAD_PARAMETERS;
733 }
734
InitInputControlChannel()735 int32_t PerUserSession::InitInputControlChannel()
736 {
737 IMSA_HILOGD("PerUserSession::InitInputControlChannel start.");
738 sptr<IInputControlChannel> inputControlChannel = new InputControlChannelStub(userId_);
739 auto data = GetReadyImeData(ImeType::IME);
740 if (data == nullptr) {
741 IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
742 return ErrorCode::ERROR_IME_NOT_STARTED;
743 }
744 return RequestIme(data, RequestType::NORMAL,
745 [&data, &inputControlChannel] { return data->core->InitInputControlChannel(inputControlChannel); });
746 }
747
StartImeInImeDied()748 void PerUserSession::StartImeInImeDied()
749 {
750 IMSA_HILOGD("StartImeInImeDied.");
751 {
752 std::lock_guard<std::mutex> lock(resetLock);
753 auto now = time(nullptr);
754 if (difftime(now, manager.last) > IME_RESET_TIME_OUT) {
755 manager = { 0, now };
756 }
757 ++manager.num;
758 if (manager.num > MAX_RESTART_NUM) {
759 return;
760 }
761 }
762 if (!IsWmsReady()) {
763 IMSA_HILOGW("not ready to start ime.");
764 return;
765 }
766 StartCurrentIme();
767 }
768
SetCurrentClient(sptr<IInputClient> client)769 void PerUserSession::SetCurrentClient(sptr<IInputClient> client)
770 {
771 IMSA_HILOGD("set current client.");
772 std::lock_guard<std::mutex> lock(clientLock_);
773 currentClient_ = client;
774 }
775
GetCurrentClient()776 sptr<IInputClient> PerUserSession::GetCurrentClient()
777 {
778 IMSA_HILOGD("get current client.");
779 std::lock_guard<std::mutex> lock(clientLock_);
780 return currentClient_;
781 }
782
ReplaceCurrentClient(const sptr<IInputClient> & client)783 void PerUserSession::ReplaceCurrentClient(const sptr<IInputClient> &client)
784 {
785 std::lock_guard<std::mutex> lock(focusedClientLock_);
786 if (client == nullptr) {
787 return;
788 }
789 auto clientInfo = GetClientInfo(client->AsObject());
790 if (clientInfo == nullptr) {
791 return;
792 }
793 auto replacedClient = GetCurrentClient();
794 SetCurrentClient(client);
795 if (replacedClient != nullptr) {
796 auto replacedClientInfo = GetClientInfo(replacedClient->AsObject());
797 if (replacedClientInfo != nullptr && replacedClientInfo->pid != clientInfo->pid) {
798 IMSA_HILOGI("remove replaced client: [%{public}d]", replacedClientInfo->pid);
799 RemoveClient(replacedClient);
800 }
801 }
802 auto inactiveClient = GetInactiveClient();
803 if (inactiveClient != nullptr) {
804 auto inactiveClientInfo = GetClientInfo(inactiveClient->AsObject());
805 if (inactiveClientInfo != nullptr && inactiveClientInfo->pid != clientInfo->pid) {
806 IMSA_HILOGI("remove inactive client: [%{public}d]", inactiveClientInfo->pid);
807 RemoveClient(inactiveClient, false);
808 }
809 }
810 }
811
SetInactiveClient(sptr<IInputClient> client)812 void PerUserSession::SetInactiveClient(sptr<IInputClient> client)
813 {
814 IMSA_HILOGD("set inactive client.");
815 std::lock_guard<std::mutex> lock(inactiveClientLock_);
816 inactiveClient_ = client;
817 }
818
GetInactiveClient()819 sptr<IInputClient> PerUserSession::GetInactiveClient()
820 {
821 std::lock_guard<std::mutex> lock(inactiveClientLock_);
822 return inactiveClient_;
823 }
824
NotifyImeChangeToClients(const Property & property,const SubProperty & subProperty)825 void PerUserSession::NotifyImeChangeToClients(const Property &property, const SubProperty &subProperty)
826 {
827 IMSA_HILOGD("start.");
828 std::lock_guard<std::recursive_mutex> lock(mtx);
829 for (const auto &client : mapClients_) {
830 auto clientInfo = client.second;
831 if (clientInfo == nullptr || !EventStatusManager::IsImeChangeOn(clientInfo->eventFlag)) {
832 IMSA_HILOGD("client nullptr or no need to notify.");
833 continue;
834 }
835 IMSA_HILOGD("notify client: [%{public}d]", static_cast<int32_t>(clientInfo->pid));
836 int32_t ret = clientInfo->client->OnSwitchInput(property, subProperty);
837 if (ret != ErrorCode::NO_ERROR) {
838 IMSA_HILOGE("notify failed, ret: %{public}d, uid: %{public}d!", ret, static_cast<int32_t>(clientInfo->uid));
839 continue;
840 }
841 }
842 }
843
AddImeData(ImeType type,sptr<IInputMethodCore> core,sptr<IRemoteObject> agent,pid_t pid)844 int32_t PerUserSession::AddImeData(ImeType type, sptr<IInputMethodCore> core, sptr<IRemoteObject> agent, pid_t pid)
845 {
846 if (core == nullptr || agent == nullptr) {
847 IMSA_HILOGE("core or agent is nullptr!");
848 return ErrorCode::ERROR_NULL_POINTER;
849 }
850 sptr<InputDeathRecipient> deathRecipient = new (std::nothrow) InputDeathRecipient();
851 if (deathRecipient == nullptr) {
852 IMSA_HILOGE("failed to new deathRecipient!");
853 return ErrorCode::ERROR_NULL_POINTER;
854 }
855 deathRecipient->SetDeathRecipient([this, core, type](const wptr<IRemoteObject> &) { this->OnImeDied(core, type); });
856 auto coreObject = core->AsObject();
857 if (coreObject == nullptr || (coreObject->IsProxyObject() && !coreObject->AddDeathRecipient(deathRecipient))) {
858 IMSA_HILOGE("failed to add death recipient!");
859 return ErrorCode::ERROR_ADD_DEATH_RECIPIENT_FAILED;
860 }
861 std::lock_guard<std::mutex> lock(imeDataLock_);
862 auto imeData = std::make_shared<ImeData>(core, agent, deathRecipient, pid);
863 imeData->imeStatus = ImeStatus::READY;
864 imeData_.insert_or_assign(type, imeData);
865 return ErrorCode::NO_ERROR;
866 }
867
GetReadyImeData(ImeType type)868 std::shared_ptr<ImeData> PerUserSession::GetReadyImeData(ImeType type)
869 {
870 std::lock_guard<std::mutex> lock(imeDataLock_);
871 auto it = imeData_.find(type);
872 if (it == imeData_.end()) {
873 return nullptr;
874 }
875 if (it->second->imeStatus != ImeStatus::READY) {
876 return nullptr;
877 }
878 return it->second;
879 }
880
GetValidIme(ImeType type)881 std::shared_ptr<ImeData> PerUserSession::GetValidIme(ImeType type)
882 {
883 auto data = GetReadyImeData(type);
884 if (data != nullptr || type != ImeType::IME) {
885 return data;
886 }
887 IMSA_HILOGI("current ime is empty, try to restart it.");
888 StartCurrentIme();
889 return GetReadyImeData(type);
890 }
891
RemoveImeData(ImeType type,bool isImeDied)892 void PerUserSession::RemoveImeData(ImeType type, bool isImeDied)
893 {
894 std::lock_guard<std::mutex> lock(imeDataLock_);
895 auto it = imeData_.find(type);
896 if (it == imeData_.end()) {
897 IMSA_HILOGD("imeData not found.");
898 return;
899 }
900 auto data = it->second;
901 if (isImeDied && data->core != nullptr && data->core->AsObject() != nullptr) {
902 data->core->AsObject()->RemoveDeathRecipient(data->deathRecipient);
903 }
904 imeData_.erase(type);
905 }
906
OnFocused(int32_t pid,int32_t uid)907 void PerUserSession::OnFocused(int32_t pid, int32_t uid)
908 {
909 std::lock_guard<std::mutex> lock(focusedClientLock_);
910 auto client = GetCurrentClient();
911 if (client == nullptr) {
912 return;
913 }
914 if (IsCurClientFocused(pid, uid)) {
915 IMSA_HILOGD("current client focused, focusedPid: %{public}d", pid);
916 return;
917 }
918 if (!OHOS::Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
919 IMSA_HILOGI("focus shifts to pid: %{public}d, remove current client.", pid);
920 RemoveClient(client);
921 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED);
922 return;
923 }
924 IMSA_HILOGI("focus shifts to pid: %{public}d, deactivate current client.", pid);
925 DeactivateClient(client);
926 }
927
OnUnfocused(int32_t pid,int32_t uid)928 void PerUserSession::OnUnfocused(int32_t pid, int32_t uid)
929 {
930 if (GetCurrentClient() == nullptr) {
931 return;
932 }
933 if (IsCurClientUnFocused(pid, uid)) {
934 IMSA_HILOGD("current client Unfocused, unFocusedPid: %{public}d", pid);
935 return;
936 }
937 auto clientInfo = GetClientInfo(pid);
938 if (clientInfo == nullptr) {
939 return;
940 }
941 RemoveClient(clientInfo->client);
942 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED);
943 }
944
OnUserUnlocked()945 void PerUserSession::OnUserUnlocked()
946 {
947 isUserUnlocked_.store(true);
948 ImeCfgManager::GetInstance().ModifyTempScreenLockImeCfg(userId_, "");
949 auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
950 if (currentIme == nullptr) {
951 IMSA_HILOGE("currentIme nullptr");
952 return;
953 }
954 auto imeData = GetImeData(ImeType::IME);
955 if (imeData != nullptr && imeData->ime.first == currentIme->bundleName) {
956 IMSA_HILOGD("no need to switch");
957 return;
958 }
959 IMSA_HILOGI("user %{public}d unlocked, start current ime", userId_);
960 AddRestartIme();
961 }
962
UpdateUserLockState()963 void PerUserSession::UpdateUserLockState()
964 {
965 bool isUnlocked = false;
966 if (OsAccountAdapter::IsOsAccountVerified(userId_, isUnlocked) != ErrorCode::NO_ERROR) {
967 return;
968 }
969 IMSA_HILOGI("isUnlocked: %{public}d", isUnlocked);
970 isUserUnlocked_.store(isUnlocked);
971 if (isUnlocked) {
972 OnUserUnlocked();
973 }
974 }
975
GetCurClientInfo()976 std::shared_ptr<InputClientInfo> PerUserSession::GetCurClientInfo()
977 {
978 auto client = GetCurrentClient();
979 if (client == nullptr) {
980 IMSA_HILOGD("no client in bound state.");
981 return nullptr;
982 }
983 return GetClientInfo(client->AsObject());
984 }
985
IsCurClientFocused(int32_t pid,int32_t uid)986 bool PerUserSession::IsCurClientFocused(int32_t pid, int32_t uid)
987 {
988 auto clientInfo = GetCurClientInfo();
989 if (clientInfo == nullptr) {
990 IMSA_HILOGE("failed to get cur client info!");
991 return false;
992 }
993 auto identityChecker = std::make_shared<IdentityCheckerImpl>();
994 if (clientInfo->uiExtensionTokenId != IMF_INVALID_TOKENID &&
995 identityChecker->IsFocusedUIExtension(clientInfo->uiExtensionTokenId)) {
996 IMSA_HILOGI("UIExtension focused");
997 return true;
998 }
999 return clientInfo->pid == pid && clientInfo->uid == uid;
1000 }
1001
IsCurClientUnFocused(int32_t pid,int32_t uid)1002 bool PerUserSession::IsCurClientUnFocused(int32_t pid, int32_t uid)
1003 {
1004 auto clientInfo = GetCurClientInfo();
1005 if (clientInfo == nullptr) {
1006 IMSA_HILOGE("failed to get cur client info!");
1007 return false;
1008 }
1009 auto identityChecker = std::make_shared<IdentityCheckerImpl>();
1010 if (clientInfo->uiExtensionTokenId != IMF_INVALID_TOKENID &&
1011 !identityChecker->IsFocusedUIExtension(clientInfo->uiExtensionTokenId)) {
1012 IMSA_HILOGI("UIExtension UnFocused.");
1013 return true;
1014 }
1015 return clientInfo->pid == pid && clientInfo->uid == uid;
1016 }
1017
IsSameClient(sptr<IInputClient> source,sptr<IInputClient> dest)1018 bool PerUserSession::IsSameClient(sptr<IInputClient> source, sptr<IInputClient> dest)
1019 {
1020 return source != nullptr && dest != nullptr && source->AsObject() == dest->AsObject();
1021 }
1022
StartCurrentIme(bool isStopCurrentIme)1023 bool PerUserSession::StartCurrentIme(bool isStopCurrentIme)
1024 {
1025 std::shared_ptr<ImeNativeCfg> imeToStart = nullptr;
1026 if (!GetInputTypeToStart(imeToStart)) {
1027 imeToStart = ImeInfoInquirer::GetInstance().GetImeToStart(userId_);
1028 }
1029 if (imeToStart == nullptr) {
1030 IMSA_HILOGE("imeToStart is nullptr!");
1031 return false;
1032 }
1033 auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
1034 IMSA_HILOGD("currentIme: %{public}s, imeToStart: %{public}s.", currentIme->imeId.c_str(),
1035 imeToStart->imeId.c_str());
1036 if (!StartIme(imeToStart, isStopCurrentIme)) {
1037 IMSA_HILOGE("failed to start ime!");
1038 InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ErrorCode::ERROR_IME_START_FAILED,
1039 imeToStart->imeId, "start ime failed!");
1040 return false;
1041 }
1042 currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
1043 IMSA_HILOGI("current ime changed to %{public}s.", currentIme->imeId.c_str());
1044 auto currentImeInfo =
1045 ImeInfoInquirer::GetInstance().GetImeInfo(userId_, currentIme->bundleName, currentIme->subName);
1046 if (currentImeInfo == nullptr) {
1047 IMSA_HILOGD("currentImeInfo is nullptr!");
1048 return true;
1049 }
1050
1051 NotifyImeChangeToClients(currentImeInfo->prop, currentImeInfo->subProp);
1052 auto ret = SwitchSubtypeWithoutStartIme(currentImeInfo->subProp);
1053 if (ret != ErrorCode::NO_ERROR) {
1054 IMSA_HILOGE("SwitchSubtype failed!");
1055 }
1056 return true;
1057 }
1058
GetCurrentUsingImeId(ImeIdentification & imeId)1059 bool PerUserSession::GetCurrentUsingImeId(ImeIdentification &imeId)
1060 {
1061 if (InputTypeManager::GetInstance().IsStarted()) {
1062 IMSA_HILOGI("get right click on state current ime.");
1063 auto currentIme = InputTypeManager::GetInstance().GetCurrentIme();
1064 imeId = currentIme;
1065 return true;
1066 }
1067 auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
1068 if (currentImeCfg == nullptr) {
1069 IMSA_HILOGE("currentImeCfg is nullptr");
1070 return false;
1071 }
1072 imeId.bundleName = currentImeCfg->bundleName;
1073 imeId.subName = currentImeCfg->extName;
1074 return true;
1075 }
1076
CanStartIme()1077 bool PerUserSession::CanStartIme()
1078 {
1079 return IsReady(MEMORY_MANAGER_SA_ID) && IsWmsReady() && runningIme_.empty();
1080 }
1081
ChangeToDefaultImeIfNeed(const std::shared_ptr<ImeNativeCfg> & targetIme,std::shared_ptr<ImeNativeCfg> & imeToStart)1082 int32_t PerUserSession::ChangeToDefaultImeIfNeed(
1083 const std::shared_ptr<ImeNativeCfg> &targetIme, std::shared_ptr<ImeNativeCfg> &imeToStart)
1084 {
1085 if (isUserUnlocked_.load()) {
1086 IMSA_HILOGD("no need");
1087 imeToStart = targetIme;
1088 return ErrorCode::NO_ERROR;
1089 }
1090 IMSA_HILOGI("Screen is locked, start default ime");
1091 auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeCfg();
1092 if (defaultIme == nullptr) {
1093 IMSA_HILOGE("failed to get default ime");
1094 return ErrorCode::ERROR_PERSIST_CONFIG;
1095 }
1096 if (defaultIme->bundleName == targetIme->bundleName) {
1097 IMSA_HILOGD("no need");
1098 imeToStart = targetIme;
1099 return ErrorCode::NO_ERROR;
1100 }
1101 imeToStart = defaultIme;
1102 ImeCfgManager::GetInstance().ModifyTempScreenLockImeCfg(userId_, imeToStart->imeId);
1103 return ErrorCode::NO_ERROR;
1104 }
1105
GetWant(const std::shared_ptr<ImeNativeCfg> & ime)1106 AAFwk::Want PerUserSession::GetWant(const std::shared_ptr<ImeNativeCfg> &ime)
1107 {
1108 SecurityMode mode;
1109 bool isolatedSandBox = true;
1110 if (SecurityModeParser::GetInstance()->IsDefaultFullMode(ime->bundleName, userId_)) {
1111 mode = SecurityMode::FULL;
1112 isolatedSandBox = false;
1113 } else if (ImeInfoInquirer::GetInstance().IsEnableSecurityMode()) {
1114 mode = SecurityModeParser::GetInstance()->GetSecurityMode(ime->bundleName, userId_);
1115 } else {
1116 mode = SecurityMode::FULL;
1117 }
1118 AAFwk::Want want;
1119 want.SetElementName(ime->bundleName, ime->extName);
1120 want.SetParam(STRICT_MODE, !(mode == SecurityMode::FULL));
1121 want.SetParam(ISOLATED_SANDBOX, isolatedSandBox);
1122 IMSA_HILOGI("StartInputService userId: %{public}d, ime: %{public}s, mode: %{public}d, isolatedSandbox: %{public}d",
1123 userId_, ime->imeId.c_str(), static_cast<int32_t>(mode), isolatedSandBox);
1124 return want;
1125 }
1126
StartInputService(const std::shared_ptr<ImeNativeCfg> & ime)1127 bool PerUserSession::StartInputService(const std::shared_ptr<ImeNativeCfg> &ime)
1128 {
1129 if (ime == nullptr) {
1130 return false;
1131 }
1132 auto imeToStart = std::make_shared<ImeNativeCfg>();
1133 if (ChangeToDefaultImeIfNeed(ime, imeToStart) != ErrorCode::NO_ERROR) {
1134 return false;
1135 }
1136 InitImeData({ imeToStart->bundleName, imeToStart->extName });
1137 isImeStarted_.Clear(false);
1138 sptr<AAFwk::IAbilityConnection> connection = new (std::nothrow) ImeConnection();
1139 if (connection == nullptr) {
1140 IMSA_HILOGE("failed to create connection!");
1141 return false;
1142 }
1143 auto want = GetWant(imeToStart);
1144 auto ret = AAFwk::AbilityManagerClient::GetInstance()->ConnectExtensionAbility(want, connection, userId_);
1145 if (ret != ErrorCode::NO_ERROR) {
1146 IMSA_HILOGE("connect %{public}s failed, ret: %{public}d!", imeToStart->imeId.c_str(), ret);
1147 InputMethodSysEvent::GetInstance().InputmethodFaultReporter(
1148 ErrorCode::ERROR_IME_START_FAILED, imeToStart->imeId, "failed to start ability.");
1149 return false;
1150 }
1151 if (!isImeStarted_.GetValue()) {
1152 IMSA_HILOGE("start %{public}s timeout!", imeToStart->imeId.c_str());
1153 return false;
1154 }
1155 IMSA_HILOGI("%{public}s started successfully.", imeToStart->imeId.c_str());
1156 InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::START_IME);
1157 return true;
1158 }
1159
GetCurrentClientPid()1160 int64_t PerUserSession::GetCurrentClientPid()
1161 {
1162 auto client = GetCurrentClient();
1163 if (client == nullptr) {
1164 return INVALID_PID;
1165 }
1166 auto clientInfo = GetClientInfo(client->AsObject());
1167 if (clientInfo == nullptr) {
1168 return INVALID_PID;
1169 }
1170 return clientInfo->pid;
1171 }
1172
GetInactiveClientPid()1173 int64_t PerUserSession::GetInactiveClientPid()
1174 {
1175 auto client = GetInactiveClient();
1176 if (client == nullptr) {
1177 return INVALID_PID;
1178 }
1179 auto clientInfo = GetClientInfo(client->AsObject());
1180 if (clientInfo == nullptr) {
1181 return INVALID_PID;
1182 }
1183 return clientInfo->pid;
1184 }
1185
OnPanelStatusChange(const InputWindowStatus & status,const ImeWindowInfo & info)1186 int32_t PerUserSession::OnPanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info)
1187 {
1188 auto clientMap = GetClientMap();
1189 for (const auto &client : clientMap) {
1190 auto clientInfo = client.second;
1191 if (clientInfo == nullptr) {
1192 IMSA_HILOGD("client nullptr or no need to notify.");
1193 continue;
1194 }
1195 if (status == InputWindowStatus::SHOW && !EventStatusManager::IsImeShowOn(clientInfo->eventFlag)) {
1196 IMSA_HILOGD("has not imeShow callback");
1197 continue;
1198 }
1199 if (status == InputWindowStatus::HIDE && !EventStatusManager::IsImeHideOn(clientInfo->eventFlag)) {
1200 IMSA_HILOGD("has not imeHide callback");
1201 continue;
1202 }
1203 int32_t ret = clientInfo->client->OnPanelStatusChange(status, info);
1204 if (ret != ErrorCode::NO_ERROR) {
1205 IMSA_HILOGE("failed to OnPanelStatusChange, ret: %{public}d", ret);
1206 continue;
1207 }
1208 }
1209 return ErrorCode::NO_ERROR;
1210 }
1211
OnUpdateListenEventFlag(const InputClientInfo & clientInfo)1212 int32_t PerUserSession::OnUpdateListenEventFlag(const InputClientInfo &clientInfo)
1213 {
1214 auto remoteClient = clientInfo.client->AsObject();
1215 auto ret = AddClientInfo(remoteClient, clientInfo, START_LISTENING);
1216 if (ret != ErrorCode::NO_ERROR) {
1217 IMSA_HILOGE("failed to AddClientInfo");
1218 return ret;
1219 }
1220 auto info = GetClientInfo(remoteClient);
1221 if (info == nullptr) {
1222 IMSA_HILOGE("info is nullptr!");
1223 return ErrorCode::ERROR_CLIENT_NOT_FOUND;
1224 }
1225 if (info->eventFlag == NO_EVENT_ON && info->bindImeType == ImeType::NONE) {
1226 RemoveClientInfo(remoteClient, false);
1227 }
1228 return ErrorCode::NO_ERROR;
1229 }
1230
IsImeStartInBind(ImeType bindImeType,ImeType startImeType)1231 bool PerUserSession::IsImeStartInBind(ImeType bindImeType, ImeType startImeType)
1232 {
1233 return startImeType == ImeType::IME && bindImeType == ImeType::IME;
1234 }
1235
IsProxyImeStartInBind(ImeType bindImeType,ImeType startImeType)1236 bool PerUserSession::IsProxyImeStartInBind(ImeType bindImeType, ImeType startImeType)
1237 {
1238 return startImeType == ImeType::PROXY_IME && bindImeType == ImeType::PROXY_IME;
1239 }
1240
IsProxyImeStartInImeBind(ImeType bindImeType,ImeType startImeType)1241 bool PerUserSession::IsProxyImeStartInImeBind(ImeType bindImeType, ImeType startImeType)
1242 {
1243 return startImeType == ImeType::PROXY_IME && bindImeType == ImeType::IME;
1244 }
1245
IsImeBindChanged(ImeType bindImeType)1246 bool PerUserSession::IsImeBindChanged(ImeType bindImeType)
1247 {
1248 return (bindImeType == ImeType::IME && IsProxyImeEnable())
1249 || (bindImeType == ImeType::PROXY_IME && !IsProxyImeEnable());
1250 }
1251
SwitchSubtype(const SubProperty & subProperty)1252 int32_t PerUserSession::SwitchSubtype(const SubProperty &subProperty)
1253 {
1254 auto data = GetValidIme(ImeType::IME);
1255 if (data == nullptr) {
1256 IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
1257 return ErrorCode::ERROR_IME_NOT_STARTED;
1258 }
1259 return RequestIme(data, RequestType::NORMAL, [&data, &subProperty] { return data->core->SetSubtype(subProperty); });
1260 }
1261
SwitchSubtypeWithoutStartIme(const SubProperty & subProperty)1262 int32_t PerUserSession::SwitchSubtypeWithoutStartIme(const SubProperty &subProperty)
1263 {
1264 auto data = GetReadyImeData(ImeType::IME);
1265 if (data == nullptr || data->core == nullptr) {
1266 IMSA_HILOGE("ime: %{public}d is not exist, or core is nullptr.", ImeType::IME);
1267 return ErrorCode::ERROR_IME_NOT_STARTED;
1268 }
1269 return RequestIme(data, RequestType::NORMAL,
1270 [&data, &subProperty] { return data->core->SetSubtype(subProperty); });
1271 }
1272
IsBoundToClient()1273 bool PerUserSession::IsBoundToClient()
1274 {
1275 if (GetCurrentClient() == nullptr) {
1276 IMSA_HILOGE("not in bound state!");
1277 return false;
1278 }
1279 return true;
1280 }
1281
RestoreCurrentImeSubType()1282 int32_t PerUserSession::RestoreCurrentImeSubType()
1283 {
1284 if (!InputTypeManager::GetInstance().IsStarted()) {
1285 IMSA_HILOGD("already exit.");
1286 return ErrorCode::NO_ERROR;
1287 }
1288 auto typeIme = InputTypeManager::GetInstance().GetCurrentIme();
1289 auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
1290 if (cfgIme->bundleName != typeIme.bundleName) {
1291 IMSA_HILOGD("diff ime, not deal, restore ime when attach.");
1292 return ErrorCode::NO_ERROR;
1293 }
1294 auto imeData = GetReadyImeData(ImeType::IME);
1295 InputTypeManager::GetInstance().Set(false);
1296 if (imeData == nullptr || imeData->ime.first != cfgIme->bundleName || imeData->ime.second != cfgIme->extName) {
1297 return ErrorCode::NO_ERROR;
1298 }
1299 SubProperty subProp = { .name = cfgIme->bundleName, .id = cfgIme->subName };
1300 auto subPropTemp = ImeInfoInquirer::GetInstance().GetCurrentSubtype(userId_);
1301 if (subPropTemp != nullptr) {
1302 subProp = *subPropTemp;
1303 }
1304 IMSA_HILOGD("same ime, restore subtype: %{public}s.", cfgIme->subName.c_str());
1305 return SwitchSubtype(subProp);
1306 }
1307
IsCurrentImeByPid(int32_t pid)1308 bool PerUserSession::IsCurrentImeByPid(int32_t pid)
1309 {
1310 auto imeData = GetImeData(ImeType::IME);
1311 if (imeData == nullptr) {
1312 IMSA_HILOGE("ime not started!");
1313 return false;
1314 }
1315 IMSA_HILOGD("userId: %{public}d, pid: %{public}d, current pid: %{public}d.", userId_, pid, imeData->pid);
1316 return imeData->pid == pid;
1317 }
1318
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)1319 int32_t PerUserSession::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
1320 {
1321 if (GetCurrentClient() == nullptr) {
1322 IMSA_HILOGI("not in bound state.");
1323 isShown = false;
1324 return ErrorCode::NO_ERROR;
1325 }
1326 auto ime = GetReadyImeData(ImeType::IME);
1327 if (ime == nullptr) {
1328 IMSA_HILOGE("ime not started!");
1329 return ErrorCode::ERROR_IME_NOT_STARTED;
1330 }
1331 return RequestIme(ime, RequestType::NORMAL,
1332 [&ime, &panelInfo, &isShown] { return ime->core->IsPanelShown(panelInfo, isShown); });
1333 }
1334
CheckSecurityMode()1335 bool PerUserSession::CheckSecurityMode()
1336 {
1337 auto client = GetCurrentClient();
1338 auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
1339 if (clientInfo != nullptr) {
1340 return clientInfo->config.inputAttribute.GetSecurityFlag();
1341 }
1342 return false;
1343 }
1344
GetClientMap()1345 std::map<sptr<IRemoteObject>, std::shared_ptr<InputClientInfo>> PerUserSession::GetClientMap()
1346 {
1347 std::lock_guard<std::recursive_mutex> lock(mtx);
1348 return mapClients_;
1349 }
1350
RequestIme(const std::shared_ptr<ImeData> & data,RequestType type,const IpcExec & exec)1351 int32_t PerUserSession::RequestIme(const std::shared_ptr<ImeData> &data, RequestType type, const IpcExec &exec)
1352 {
1353 if (IsProxyImeEnable()) {
1354 IMSA_HILOGD("proxy enable.");
1355 return exec();
1356 }
1357 if (data == nullptr || data->freezeMgr == nullptr) {
1358 IMSA_HILOGE("data is nullptr");
1359 return ErrorCode::NO_ERROR;
1360 }
1361 if (!data->freezeMgr->IsIpcNeeded(type)) {
1362 IMSA_HILOGD("no need to request, type: %{public}d.", type);
1363 return ErrorCode::NO_ERROR;
1364 }
1365 data->freezeMgr->BeforeIpc(type);
1366 auto ret = exec();
1367 data->freezeMgr->AfterIpc(type, ret == ErrorCode::NO_ERROR);
1368 return ret;
1369 }
1370
OnConnectSystemCmd(const sptr<IRemoteObject> & channel,sptr<IRemoteObject> & agent)1371 int32_t PerUserSession::OnConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)
1372 {
1373 auto data = GetReadyImeData(ImeType::IME);
1374 if (data == nullptr) {
1375 IMSA_HILOGE("ime: %{public}d is not exist!", ImeType::IME);
1376 return ErrorCode::ERROR_IME_NOT_STARTED;
1377 }
1378 auto ret = RequestIme(data, RequestType::NORMAL,
1379 [&data, &channel, &agent] { return data->core->OnConnectSystemCmd(channel, agent); });
1380 IMSA_HILOGD("on connect systemCmd, ret: %{public}d.", ret);
1381 if (ret != ErrorCode::NO_ERROR) {
1382 IMSA_HILOGE("bind failed, ret: %{public}d!", ret);
1383 return ret;
1384 }
1385 return ErrorCode::NO_ERROR;
1386 }
1387
WaitForCurrentImeStop()1388 bool PerUserSession::WaitForCurrentImeStop()
1389 {
1390 IMSA_HILOGI("start.");
1391 std::unique_lock<std::mutex> lock(imeStopMutex_);
1392 isSwitching_.store(true);
1393 return imeStopCv_.wait_for(lock, std::chrono::milliseconds(STOP_IME_TIME), [this]() { return !isSwitching_; });
1394 }
1395
NotifyImeStopFinished()1396 void PerUserSession::NotifyImeStopFinished()
1397 {
1398 IMSA_HILOGI("start.");
1399 std::unique_lock<std::mutex> lock(imeStopMutex_);
1400 isSwitching_.store(false);
1401 imeStopCv_.notify_one();
1402 }
1403
RemoveCurrentClient()1404 int32_t PerUserSession::RemoveCurrentClient()
1405 {
1406 auto currentClient = GetCurrentClient();
1407 if (currentClient == nullptr) {
1408 IMSA_HILOGE("currentClient is nullptr");
1409 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1410 }
1411 return RemoveClient(currentClient, false);
1412 }
1413
IsWmsReady()1414 bool PerUserSession::IsWmsReady()
1415 {
1416 if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
1417 IMSA_HILOGD("scb enable");
1418 return WmsConnectionObserver::IsWmsConnected(userId_);
1419 }
1420 return IsReady(WINDOW_MANAGER_SERVICE_ID);
1421 }
1422
IsReady(int32_t saId)1423 bool PerUserSession::IsReady(int32_t saId)
1424 {
1425 auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1426 if (saMgr == nullptr) {
1427 IMSA_HILOGE("get saMgr failed!");
1428 return false;
1429 }
1430 if (saMgr->CheckSystemAbility(saId) == nullptr) {
1431 IMSA_HILOGE("sa:%{public}d not ready!", saId);
1432 return false;
1433 }
1434 return true;
1435 }
1436
AddRestartIme()1437 void PerUserSession::AddRestartIme()
1438 {
1439 int32_t tasks = 0;
1440 {
1441 std::lock_guard<std::mutex> lock(restartMutex_);
1442 if (restartTasks_ >= MAX_RESTART_TASKS) {
1443 return;
1444 }
1445 restartTasks_ = std::max(restartTasks_, 0);
1446 tasks = ++restartTasks_;
1447 }
1448 if (tasks == 1 && !RestartIme()) {
1449 std::lock_guard<std::mutex> lock(restartMutex_);
1450 restartTasks_ = 0;
1451 }
1452 }
1453
RestartIme()1454 bool PerUserSession::RestartIme()
1455 {
1456 auto task = [this]() {
1457 if (CanStartIme()) {
1458 auto ret = StartCurrentIme(true);
1459 if (!ret) {
1460 IMSA_HILOGE("start ime failed");
1461 }
1462 }
1463 int32_t tasks = 0;
1464 {
1465 std::lock_guard<std::mutex> lock(restartMutex_);
1466 tasks = --restartTasks_;
1467 }
1468 if (tasks > 0 && !RestartIme()) {
1469 std::lock_guard<std::mutex> lock(restartMutex_);
1470 restartTasks_ = 0;
1471 }
1472 };
1473 if (eventHandler_ == nullptr) {
1474 IMSA_HILOGE("eventHandler_ is nullptr!");
1475 return false;
1476 }
1477 return eventHandler_->PostTask(task, "RestartCurrentImeTask", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1478 }
1479
GetSwitchQueue()1480 BlockQueue<SwitchInfo>& PerUserSession::GetSwitchQueue()
1481 {
1482 return switchQueue_;
1483 }
1484
InitImeData(const std::pair<std::string,std::string> & ime)1485 int32_t PerUserSession::InitImeData(const std::pair<std::string, std::string> &ime)
1486 {
1487 std::lock_guard<std::mutex> lock(imeDataLock_);
1488 auto it = imeData_.find(ImeType::IME);
1489 if (it != imeData_.end()) {
1490 return ErrorCode::NO_ERROR;
1491 }
1492 auto imeData = std::make_shared<ImeData>(nullptr, nullptr, nullptr, -1);
1493 imeData->startTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1494 imeData->ime = ime;
1495 imeData_.insert({ ImeType::IME, imeData });
1496 return ErrorCode::NO_ERROR;
1497 }
1498
UpdateImeData(sptr<IInputMethodCore> core,sptr<IRemoteObject> agent,pid_t pid)1499 int32_t PerUserSession::UpdateImeData(sptr<IInputMethodCore> core, sptr<IRemoteObject> agent, pid_t pid)
1500 {
1501 if (core == nullptr || agent == nullptr) {
1502 IMSA_HILOGE("core or agent is nullptr!");
1503 return ErrorCode::ERROR_NULL_POINTER;
1504 }
1505 std::lock_guard<std::mutex> lock(imeDataLock_);
1506 auto it = imeData_.find(ImeType::IME);
1507 if (it == imeData_.end()) {
1508 return ErrorCode::ERROR_NULL_POINTER;
1509 }
1510 it->second->core = core;
1511 it->second->agent = agent;
1512 it->second->pid = pid;
1513 it->second->freezeMgr = std::make_shared<FreezeManager>(pid);
1514 sptr<InputDeathRecipient> deathRecipient = new (std::nothrow) InputDeathRecipient();
1515 if (deathRecipient == nullptr) {
1516 IMSA_HILOGE("failed to new deathRecipient!");
1517 return ErrorCode::ERROR_NULL_POINTER;
1518 }
1519 auto type = ImeType::IME;
1520 deathRecipient->SetDeathRecipient([this, core, type](const wptr<IRemoteObject> &) { this->OnImeDied(core, type); });
1521 auto coreObject = core->AsObject();
1522 if (coreObject == nullptr || (coreObject->IsProxyObject() && !coreObject->AddDeathRecipient(deathRecipient))) {
1523 IMSA_HILOGE("failed to add death recipient!");
1524 return ErrorCode::ERROR_ADD_DEATH_RECIPIENT_FAILED;
1525 }
1526 it->second->deathRecipient = deathRecipient;
1527 return ErrorCode::NO_ERROR;
1528 }
1529
InitConnect(pid_t pid)1530 int32_t PerUserSession::InitConnect(pid_t pid)
1531 {
1532 std::lock_guard<std::mutex> lock(imeDataLock_);
1533 auto it = imeData_.find(ImeType::IME);
1534 if (it == imeData_.end()) {
1535 return ErrorCode::ERROR_NULL_POINTER;
1536 }
1537 it->second->pid = pid;
1538 return ErrorCode::NO_ERROR;
1539 }
1540
GetImeData(ImeType type)1541 std::shared_ptr<ImeData> PerUserSession::GetImeData(ImeType type)
1542 {
1543 std::lock_guard<std::mutex> lock(imeDataLock_);
1544 auto it = imeData_.find(type);
1545 if (it == imeData_.end()) {
1546 return nullptr;
1547 }
1548 return it->second;
1549 }
1550
StartIme(const std::shared_ptr<ImeNativeCfg> & ime,bool isStopCurrentIme)1551 bool PerUserSession::StartIme(const std::shared_ptr<ImeNativeCfg> &ime, bool isStopCurrentIme)
1552 {
1553 std::lock_guard<std::mutex> lock(imeStartLock_);
1554 if (ime == nullptr) {
1555 return false;
1556 }
1557 auto imeData = GetImeData(ImeType::IME);
1558 if (imeData == nullptr) {
1559 return HandleFirstStart(ime, isStopCurrentIme);
1560 }
1561 if (imeData->ime.first == ime->bundleName && imeData->ime.second == ime->extName) {
1562 if (isStopCurrentIme) {
1563 return StartNewIme(ime);
1564 }
1565 return StartCurrentIme(ime);
1566 }
1567 return StartNewIme(ime);
1568 }
1569
GetImeAction(ImeEvent action)1570 ImeAction PerUserSession::GetImeAction(ImeEvent action)
1571 {
1572 std::lock_guard<std::mutex> lock(imeDataLock_);
1573 auto it = imeData_.find(ImeType::IME);
1574 if (it == imeData_.end()) {
1575 return ImeAction::DO_ACTION_IN_NULL_IME_DATA;
1576 }
1577 auto iter = imeEventConverter_.find({ it->second->imeStatus, action });
1578 if (iter == imeEventConverter_.end()) {
1579 IMSA_HILOGE("abnormal!");
1580 return ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED;
1581 }
1582 it->second->imeStatus = iter->second.first;
1583 return iter->second.second;
1584 }
1585
StartCurrentIme(const std::shared_ptr<ImeNativeCfg> & ime)1586 bool PerUserSession::StartCurrentIme(const std::shared_ptr<ImeNativeCfg> &ime)
1587 {
1588 auto imeData = GetImeData(ImeType::IME);
1589 if (imeData == nullptr) {
1590 return StartInputService(ime);
1591 }
1592 auto action = GetImeAction(ImeEvent::START_IME);
1593 if (action == ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED) {
1594 return false;
1595 }
1596 if (action == ImeAction::DO_ACTION_IN_NULL_IME_DATA) {
1597 return StartInputService(ime);
1598 }
1599 if (action == ImeAction::DO_NOTHING) {
1600 return true;
1601 }
1602 if (action == ImeAction::HANDLE_STARTING_IME) {
1603 int64_t time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1604 if (time - imeData->startTime > ImeData::START_TIME_OUT) {
1605 IMSA_HILOGE("[%{public}s, %{public}s] start abnormal, more than eight second!", imeData->ime.first.c_str(),
1606 imeData->ime.second.c_str());
1607 return HandleStartImeTimeout(ime);
1608 }
1609 return StartInputService(ime);
1610 }
1611 if (!StopExitingCurrentIme()) {
1612 return false;
1613 }
1614 return StartInputService(ime);
1615 }
1616
HandleStartImeTimeout(const std::shared_ptr<ImeNativeCfg> & ime)1617 bool PerUserSession::HandleStartImeTimeout(const std::shared_ptr<ImeNativeCfg> &ime)
1618 {
1619 auto action = GetImeAction(ImeEvent::START_IME_TIMEOUT);
1620 if (action == ImeAction::DO_ACTION_IN_NULL_IME_DATA) {
1621 return StartInputService(ime);
1622 }
1623 if (action == ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED) {
1624 return false;
1625 }
1626 if (action == ImeAction::DO_NOTHING) {
1627 IMSA_HILOGW("ready when timeout");
1628 return true;
1629 }
1630 ForceStopCurrentIme(false);
1631 return false;
1632 }
1633
StartNewIme(const std::shared_ptr<ImeNativeCfg> & ime)1634 bool PerUserSession::StartNewIme(const std::shared_ptr<ImeNativeCfg> &ime)
1635 {
1636 if (!StopCurrentIme()) {
1637 return false;
1638 }
1639 return StartInputService(ime);
1640 }
1641
StopCurrentIme()1642 bool PerUserSession::StopCurrentIme()
1643 {
1644 auto action = GetImeAction(ImeEvent::STOP_IME);
1645 if (action == ImeAction::DO_ACTION_IN_NULL_IME_DATA) {
1646 return true;
1647 }
1648 if (action == ImeAction::DO_ACTION_IN_IME_EVENT_CONVERT_FAILED) {
1649 return false;
1650 }
1651 if (action == ImeAction::STOP_READY_IME) {
1652 return StopReadyCurrentIme();
1653 }
1654 if (action == ImeAction::STOP_STARTING_IME) {
1655 return ForceStopCurrentIme();
1656 }
1657 return StopExitingCurrentIme();
1658 }
1659
StopReadyCurrentIme()1660 bool PerUserSession::StopReadyCurrentIme()
1661 {
1662 auto client = GetCurrentClient();
1663 auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
1664 if (clientInfo != nullptr && clientInfo->bindImeType == ImeType::IME) {
1665 StopClientInput(clientInfo);
1666 }
1667 auto imeData = GetImeData(ImeType::IME);
1668 if (imeData == nullptr) {
1669 return true;
1670 }
1671 if (imeData->core == nullptr) {
1672 IMSA_HILOGE("core is nullptr.");
1673 return ForceStopCurrentIme();
1674 }
1675 auto ret = RequestIme(imeData, RequestType::NORMAL, [&imeData] {
1676 // failed when register onInputStop after SetCoreAndAgent
1677 return imeData->core->StopInputService(true);
1678 });
1679 if (ret != ErrorCode::NO_ERROR) {
1680 IMSA_HILOGE("StopInputService failed.");
1681 return ForceStopCurrentIme();
1682 }
1683 if (!WaitForCurrentImeStop()) {
1684 IMSA_HILOGI("stop timeout.");
1685 return ForceStopCurrentIme();
1686 }
1687 return true;
1688 }
1689
StopExitingCurrentIme()1690 bool PerUserSession::StopExitingCurrentIme()
1691 {
1692 auto imeData = GetImeData(ImeType::IME);
1693 if (imeData == nullptr) {
1694 return true;
1695 }
1696 if (!ImeInfoInquirer::GetInstance().IsRunningIme(userId_, imeData->ime.first)) {
1697 IMSA_HILOGD("already stop!");
1698 RemoveImeData(ImeType::IME, true);
1699 return true;
1700 }
1701 return ForceStopCurrentIme();
1702 }
1703
ForceStopCurrentIme(bool isNeedWait)1704 bool PerUserSession::ForceStopCurrentIme(bool isNeedWait)
1705 {
1706 auto client = GetCurrentClient();
1707 auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
1708 if (clientInfo != nullptr && clientInfo->bindImeType == ImeType::IME) {
1709 StopClientInput(clientInfo);
1710 }
1711 auto imeData = GetImeData(ImeType::IME);
1712 if (imeData == nullptr) {
1713 return true;
1714 }
1715 AAFwk::Want want;
1716 want.SetElementName(imeData->ime.first, imeData->ime.second);
1717 auto ret = AAFwk::AbilityManagerClient::GetInstance()->StopExtensionAbility(
1718 want, nullptr, userId_, AppExecFwk::ExtensionAbilityType::INPUTMETHOD);
1719 if (ret != ErrorCode::NO_ERROR) {
1720 IMSA_HILOGE("StopExtensionAbility [%{public}s, %{public}s] failed, ret: %{public}d!",
1721 imeData->ime.first.c_str(), imeData->ime.second.c_str(), ret);
1722 return false;
1723 }
1724 if (!isNeedWait) {
1725 return true;
1726 }
1727 WaitForCurrentImeStop();
1728 if (ImeInfoInquirer::GetInstance().IsRunningIme(userId_, imeData->ime.first)) {
1729 IMSA_HILOGW("stop [%{public}s, %{public}s] timeout.", imeData->ime.first.c_str(), imeData->ime.second.c_str());
1730 return false;
1731 }
1732 RemoveImeData(ImeType::IME, true);
1733 return true;
1734 }
1735
HandleFirstStart(const std::shared_ptr<ImeNativeCfg> & ime,bool isStopCurrentIme)1736 bool PerUserSession::HandleFirstStart(const std::shared_ptr<ImeNativeCfg> &ime, bool isStopCurrentIme)
1737 {
1738 if (runningIme_.empty()) {
1739 return StartInputService(ime);
1740 }
1741 IMSA_HILOGW("imsa abnormal restore.");
1742 if (isStopCurrentIme) {
1743 return true;
1744 }
1745 if (BlockRetry(CHECK_IME_RUNNING_RETRY_INTERVAL, CHECK_IME_RUNNING_RETRY_TIMES,
1746 [this]() -> bool { return !ImeInfoInquirer::GetInstance().IsRunningIme(userId_, runningIme_); })) {
1747 IMSA_HILOGI("[%{public}d, %{public}s] stop completely", userId_, runningIme_.c_str());
1748 runningIme_.clear();
1749 return StartInputService(ime);
1750 }
1751 IMSA_HILOGW("[%{public}d, %{public}s] stop timeout", userId_, runningIme_.c_str());
1752 return false;
1753 }
1754
RestoreCurrentIme()1755 int32_t PerUserSession::RestoreCurrentIme()
1756 {
1757 InputTypeManager::GetInstance().Set(false);
1758 auto cfgIme = ImeInfoInquirer::GetInstance().GetImeToStart(userId_);
1759 auto imeData = GetReadyImeData(ImeType::IME);
1760 if (imeData != nullptr && imeData->ime.first == cfgIme->bundleName && imeData->ime.second == cfgIme->extName) {
1761 return ErrorCode::NO_ERROR;
1762 }
1763 IMSA_HILOGD("need restore!");
1764 if (!StartIme(cfgIme)) {
1765 IMSA_HILOGE("start ime failed!");
1766 return ErrorCode::ERROR_IME_START_FAILED;
1767 }
1768 SubProperty subProp = { .name = cfgIme->bundleName, .id = cfgIme->subName };
1769 auto subPropTemp = ImeInfoInquirer::GetInstance().GetCurrentSubtype(userId_);
1770 if (subPropTemp != nullptr) {
1771 subProp = *subPropTemp;
1772 }
1773 SwitchSubtype(subProp);
1774 return ErrorCode::NO_ERROR;
1775 }
1776
CheckPwdInputPatternConv(InputClientInfo & newClientInfo)1777 bool PerUserSession::CheckPwdInputPatternConv(InputClientInfo &newClientInfo)
1778 {
1779 auto exClient = GetCurrentClient();
1780 if (exClient == nullptr) {
1781 exClient = GetInactiveClient();
1782 }
1783 auto exClientInfo = exClient != nullptr ? GetClientInfo(exClient->AsObject()) : nullptr;
1784 if (exClientInfo == nullptr) {
1785 IMSA_HILOGE("exClientInfo is nullptr!");
1786 return false;
1787 }
1788 // if current input pattern differ from previous in pwd and normal, need hide panel first.
1789 if (newClientInfo.config.inputAttribute.GetSecurityFlag()) {
1790 IMSA_HILOGI("new input pattern is pwd.");
1791 return !exClientInfo->config.inputAttribute.GetSecurityFlag();
1792 }
1793 IMSA_HILOGI("new input pattern is normal.");
1794 return exClientInfo->config.inputAttribute.GetSecurityFlag();
1795 }
1796
GetImeNativeCfg(int32_t userId,const std::string & bundleName,const std::string & subName)1797 std::shared_ptr<ImeNativeCfg> PerUserSession::GetImeNativeCfg(int32_t userId, const std::string &bundleName,
1798 const std::string &subName)
1799 {
1800 auto targetImeProperty = ImeInfoInquirer::GetInstance().GetImeProperty(userId, bundleName);
1801 if (targetImeProperty == nullptr) {
1802 IMSA_HILOGE("GetImeProperty [%{public}d, %{public}s] failed!", userId, bundleName.c_str());
1803 return nullptr;
1804 }
1805 std::string targetName = bundleName + "/" + targetImeProperty->id;
1806 ImeNativeCfg targetIme = { targetName, bundleName, subName, targetImeProperty->id };
1807 return std::make_shared<ImeNativeCfg>(targetIme);
1808 }
1809
GetInputTypeToStart(std::shared_ptr<ImeNativeCfg> & imeToStart)1810 bool PerUserSession::GetInputTypeToStart(std::shared_ptr<ImeNativeCfg> &imeToStart)
1811 {
1812 if (!InputTypeManager::GetInstance().IsStarted()) {
1813 return false;
1814 }
1815 auto currentInputTypeIme = InputTypeManager::GetInstance().GetCurrentIme();
1816 if (currentInputTypeIme.bundleName.empty()) {
1817 auto currentInputType = InputTypeManager::GetInstance().GetCurrentInputType();
1818 InputTypeManager::GetInstance().GetImeByInputType(currentInputType, currentInputTypeIme);
1819 }
1820 imeToStart = GetImeNativeCfg(userId_, currentInputTypeIme.bundleName, currentInputTypeIme.subName);
1821 return true;
1822 }
1823 } // namespace MiscServices
1824 } // namespace OHOS