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