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