• 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 <vector>
19 
20 #include "ability_connect_callback_proxy.h"
21 #include "ability_manager_interface.h"
22 #include "element_name.h"
23 #include "input_client_proxy.h"
24 #include "input_control_channel_proxy.h"
25 #include "input_data_channel_proxy.h"
26 #include "input_method_ability_connection_stub.h"
27 #include "input_method_agent_proxy.h"
28 #include "input_method_core_proxy.h"
29 #include "ipc_skeleton.h"
30 #include "message_parcel.h"
31 #include "para_handle.h"
32 #include "parcel.h"
33 #include "platform.h"
34 #include "sa_mgr_client.h"
35 #include "system_ability_definition.h"
36 #include "unistd.h"
37 #include "utils.h"
38 #include "want.h"
39 
40 namespace OHOS {
41 namespace MiscServices {
42     using namespace MessageID;
43     /*! Constructor
44     \param userId the id of the given user
45     \param msgId the msg id can be MessageID::MSG_ID_CLIENT_DIED (to monitor input client)
46     \n or MessageID::MSG_ID_IMS_DIED (to monitor input method service)
47     */
RemoteObjectDeathRecipient(int userId,int msgId)48     RemoteObjectDeathRecipient::RemoteObjectDeathRecipient(int userId, int msgId)
49     {
50         userId_ = userId;
51         msgId_ = msgId;
52     }
53 
~RemoteObjectDeathRecipient()54     RemoteObjectDeathRecipient::~RemoteObjectDeathRecipient()
55     {
56     }
57 
58     /*! Notify that a remote object died.
59     \n It's called when the linked remote object died.
60     \param who the IRemoteObject handler of the remote object died.
61     */
OnRemoteDied(const wptr<IRemoteObject> & who)62     void RemoteObjectDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &who)
63     {
64         auto parcel = new (std::nothrow) MessageParcel();
65         if (parcel == nullptr) {
66             IMSA_HILOGE("parcel is nullptr");
67             return;
68         }
69         parcel->WriteInt32(userId_);
70         parcel->WritePointer(reinterpret_cast<uintptr_t>(who.GetRefPtr()));
71         auto msg = new (std::nothrow) Message(msgId_, parcel);
72         if (msg == nullptr) {
73             IMSA_HILOGE("msg is nullptr");
74             delete parcel;
75             return;
76         }
77         MessageHandler::Instance()->SendMessage(msg);
78     }
79 
80     /*! Constructor
81     \param userId the user id of this user whose session are managed by this instance of PerUserSession.
82     */
PerUserSession(int userId)83     PerUserSession::PerUserSession(int userId)
84     {
85         userState = UserState::USER_STATE_STARTED;
86         userId_ = userId;
87         currentIme[0] = nullptr;
88         currentIme[1] = nullptr;
89 
90         needReshowClient = nullptr;
91 
92         imsDeathRecipient = new RemoteObjectDeathRecipient(userId, MSG_ID_IMS_DIED);
93     }
94 
95     /*! Destructor
96     */
~PerUserSession()97     PerUserSession::~PerUserSession()
98     {
99         if (userState == UserState::USER_STATE_UNLOCKED) {
100             OnUserLocked();
101         }
102         imsDeathRecipient = nullptr;
103         if (workThreadHandler.joinable()) {
104             workThreadHandler.join();
105         }
106     }
107 
108 
109     /*! Create work thread for this user
110     \param handle message handle to receive the message
111     */
CreateWorkThread(MessageHandler & handler)112     void PerUserSession::CreateWorkThread(MessageHandler& handler)
113     {
114         msgHandler = &handler;
115         workThreadHandler = std::thread([this] {WorkThread();});
116     }
117 
118     /*! Wait till work thread exits
119     */
JoinWorkThread()120     void PerUserSession::JoinWorkThread()
121     {
122         if (workThreadHandler.joinable()) {
123             workThreadHandler.join();
124         }
125     }
126 
127     /*! Work thread for this user
128     */
WorkThread()129     void PerUserSession::WorkThread()
130     {
131         if (msgHandler == nullptr) {
132             return;
133         }
134         while (1) {
135             Message *msg = msgHandler->GetMessage();
136             std::unique_lock<std::mutex> lock(mtx);
137             switch (msg->msgId_) {
138                 case MSG_ID_USER_LOCK:
139                 case MSG_ID_EXIT_SERVICE: {
140                     OnUserLocked();
141                     delete msg;
142                     msg = nullptr;
143                     return;
144                 }
145                 case MSG_ID_PREPARE_INPUT: {
146                     OnPrepareInput(msg);
147                     break;
148                 }
149                 case MSG_ID_RELEASE_INPUT: {
150                     OnReleaseInput(msg);
151                     break;
152                 }
153                 case MSG_ID_START_INPUT: {
154                     OnStartInput(msg);
155                     break;
156                 }
157                 case MSG_ID_STOP_INPUT: {
158                     OnStopInput(msg);
159                     break;
160                 }
161                 case MSG_ID_SET_CORE_AND_AGENT: {
162                     SetCoreAndAgent(msg);
163                     break;
164                 }
165                 case MSG_ID_CLIENT_DIED: {
166                     auto *remoteObject = reinterpret_cast<IRemoteObject *>(msg->msgContent_->ReadPointer());
167                     if (remoteObject == nullptr) {
168                         IMSA_HILOGE("MSG_ID_CLIENT_DIED remoteObject is nullptr");
169                         break;
170                     }
171                     OnClientDied(remoteObject);
172                     break;
173                 }
174                 case MSG_ID_IMS_DIED: {
175                     auto *remoteObject = reinterpret_cast<IRemoteObject *>(msg->msgContent_->ReadPointer());
176                     if (remoteObject == nullptr) {
177                         IMSA_HILOGE("MSG_ID_IMS_DIED remoteObject is nullptr");
178                         break;
179                     }
180                     OnImsDied(remoteObject);
181                     break;
182                 }
183                 case MSG_ID_HIDE_KEYBOARD_SELF: {
184                     int flag = msg->msgContent_->ReadInt32();
185                     OnHideKeyboardSelf(flag);
186                     break;
187                 }
188                 case MSG_ID_ADVANCE_TO_NEXT: {
189                     OnAdvanceToNext();
190                     break;
191                 }
192                 case MSG_ID_SET_DISPLAY_MODE: {
193                     int mode = msg->msgContent_->ReadInt32();
194                     OnSetDisplayMode(mode);
195                     break;
196                 }
197                 case MSG_ID_RESTART_IMS: {
198                     int index = msg->msgContent_->ReadInt32();
199                     std::u16string imeId = msg->msgContent_->ReadString16();
200                     OnRestartIms(index, imeId);
201                     break;
202                 }
203                 case MSG_HIDE_CURRENT_INPUT: {
204                     OnHideKeyboardSelf(0);
205                 }
206                 default: {
207                     break;
208                 }
209             }
210             delete msg;
211             msg = nullptr;
212         }
213     }
214 
215     /*! Set display Id
216     \param displayId the Id of display screen on which the input method keyboard show.
217     */
SetDisplayId(int displayId)218     void PerUserSession::SetDisplayId(int displayId)
219     {
220         this->displayId = displayId;
221     }
222 
223     /*! Set the current input method engine
224     \param ime the current (default) IME pointer referred to the instance in PerUserSetting.
225     */
SetCurrentIme(InputMethodProperty * ime)226     void PerUserSession::SetCurrentIme(InputMethodProperty *ime)
227     {
228         currentIme[DEFAULT_IME] = ime;
229         userState = UserState::USER_STATE_UNLOCKED;
230     }
231 
232     /*! Set the system security input method engine
233     \param ime system security IME pointer referred to the instance in PerUserSetting.
234     */
SetSecurityIme(InputMethodProperty * ime)235     void PerUserSession::SetSecurityIme(InputMethodProperty *ime)
236     {
237         currentIme[SECURITY_IME] = ime;
238     }
239 
240     /*! Set the input method setting data
241     \param setting InputMethodSetting pointer referred to the instance in PerUserSetting.
242     */
SetInputMethodSetting(InputMethodSetting * setting)243     void PerUserSession::SetInputMethodSetting(InputMethodSetting *setting)
244     {
245         inputMethodSetting = setting;
246     }
247 
248     /*! Reset input method engine
249     \param defaultIme default ime pointer referred to the instance in PerUserSetting
250     \param  security security ime pointer referred to the instance in PerUserSetting
251     \n Two input method engines can be running at the same time for one user.
252     \n One is the default ime, another is security ime
253     */
ResetIme(InputMethodProperty * defaultIme,InputMethodProperty * securityIme)254     void PerUserSession::ResetIme(InputMethodProperty *defaultIme, InputMethodProperty *securityIme)
255     {
256         IMSA_HILOGI("PerUserSession::ResetIme");
257         std::unique_lock<std::mutex> lock(mtx);
258         InputMethodProperty *ime[] = {defaultIme, securityIme};
259         for (int i = 0; i < MIN_IME; i++) {
260             if (currentIme[i] == ime[i] && ime[i] != nullptr) {
261                 continue;
262             }
263             if (imsCore[i]) {
264                 StopInputMethod(i);
265             }
266             ResetImeError(i);
267             currentIme[i] = ime[i];
268             if (currentIme[i] == nullptr) {
269                 if (needReshowClient && GetImeIndex(needReshowClient) == i) {
270                     needReshowClient = nullptr;
271                 }
272                 continue;
273             }
274 
275             bool flag = false;
276             for (auto mapClient : mapClients) {
277                 if ((i == DEFAULT_IME && !mapClient.second->attribute.GetSecurityFlag())
278                     || (i == SECURITY_IME && mapClient.second->attribute.GetSecurityFlag())) {
279                     flag = true;
280                     break;
281                 }
282             }
283             if (flag) {
284                 int ret = StartInputMethod(i);
285                 if (ret != ErrorCode::NO_ERROR) {
286                     needReshowClient = nullptr;
287                     break;
288                 }
289                 if (needReshowClient && GetImeIndex(needReshowClient) == i) {
290                     ShowKeyboard(needReshowClient);
291                     needReshowClient = nullptr;
292                 }
293             }
294         }
295     }
296 
297     /*! Called when a package is removed
298     \param packageName the name of package removed
299     */
OnPackageRemoved(const std::u16string & packageName)300     void PerUserSession::OnPackageRemoved(const std::u16string& packageName)
301     {
302         IMSA_HILOGI("PerUserSession::OnPackageRemoved");
303         InputMethodSetting tmpSetting;
304         bool flag = false;
305         std::unique_lock<std::mutex> lock(mtx);
306         for (int i = 0; i < MAX_IME; i++) {
307             sptr<IInputClient> client = GetCurrentClient();
308             if (currentIme[i] && currentIme[i]->mPackageName == packageName) {
309                 if (client != nullptr && GetImeIndex(client) == i) {
310                     needReshowClient = client;
311                     HideKeyboard(client);
312                 }
313                 StopInputMethod(i);
314                 currentIme[i] = nullptr;
315                 if (i == DEFAULT_IME) {
316                     tmpSetting.SetCurrentKeyboardType(-1);
317                     inputMethodSetting->SetCurrentKeyboardType(-1);
318                 } else if (i == SECURITY_IME) {
319                     tmpSetting.SetCurrentSysKeyboardType(-1);
320                     inputMethodSetting->SetCurrentSysKeyboardType(-1);
321                 }
322                 currentKbdIndex[i] = 0;
323                 flag = true;
324             }
325         }
326         if (flag) {
327             Platform::Instance()->SetInputMethodSetting(userId_, tmpSetting);
328         }
329     }
330 
331     /*! Add an input client
332     \param pid the process pid of the input client
333     \param uid the uid of the the input client
334     \param displayId the display id of the input client
335     \param inputClient the remote object handler of the input client
336     \param channel the remote InputDataChannel object handler for the input client.
337     \n It will be transferred to input method service
338     \param attribute the input attribute of the input client.
339     \return \li ErrorCode::NO_ERROR no error
340     \return \li ErrorCode::ERROR_CLIENT_DUPLICATED client is duplicated
341     */
AddClient(const ClientInfo & clientInfo)342     int PerUserSession::AddClient(const ClientInfo &clientInfo)
343     {
344         IMSA_HILOGI("PerUserSession::AddClient");
345         ClientInfo *info = GetClientInfo(clientInfo.client);
346         if (info != nullptr) {
347             IMSA_HILOGE("info is exist, not need add.");
348             return ErrorCode::NO_ERROR;
349         }
350         sptr<IRemoteObject> obj = clientInfo.client->AsObject();
351         if (obj == nullptr) {
352             IMSA_HILOGE("inputClient AsObject is nullptr");
353             return ErrorCode::ERROR_REMOTE_CLIENT_DIED;
354         }
355         bool ret = obj->AddDeathRecipient(clientInfo.deathRecipient);
356         IMSA_HILOGI("Add death recipient %{public}s", ret ? "success" : "failed");
357 
358         info = new (std::nothrow) ClientInfo(clientInfo);
359         if (info == nullptr) {
360             IMSA_HILOGE("failed to create ClientInfo");
361             return ErrorCode::ERROR_NULL_POINTER;
362         }
363         mapClients.insert({ obj, info });
364         return ErrorCode::NO_ERROR;
365     }
366 
367     /*! Remove an input client
368     \param inputClient remote object handler of the input client
369     \param[out] remainClientNum remained count of the same kinds of clients for this user
370         \n (i.e. if inputClient is an normal client, remainClientNum is the count of remained normal clients.
371         \n if inputClient is a security client, remainClientNum is the count of remained security clients.)
372     \return ErrorCode::NO_ERROR no error
373     \return ErrorCode::ERROR_CLIENT_NOT_FOUND client is not found
374     */
RemoveClient(IRemoteObject * inputClient)375     void PerUserSession::RemoveClient(IRemoteObject *inputClient)
376     {
377         IMSA_HILOGI("PerUserSession::RemoveClient");
378         auto it = mapClients.find(inputClient);
379         if (it == mapClients.end()) {
380             IMSA_HILOGE("PerUserSession::RemoveClient client not found");
381             return;
382         }
383         ClientInfo *clientInfo = it->second;
384         inputClient->RemoveDeathRecipient(clientInfo->deathRecipient);
385         delete clientInfo;
386         clientInfo = nullptr;
387         mapClients.erase(it);
388     }
389 
390     /*! Start input method service
391     \param index it can be 0 or 1. 0 - default ime, 1 - security ime
392     \return ErrorCode::NO_ERROR no error
393     \return ErrorCode::ERROR_IME_BIND_FAILED failed to bind ime
394     \return ErrorCode::ERROR_IME_NOT_AVAILABLE no ime is available
395     \return ErrorCode::ERROR_SECURITY_IME_NOT_AVAILABLE no security ime is available
396     \return ErrorCode::ERROR_TOKEN_CREATE_FAILED failed to create window token
397     \return other errors returned by binder driver
398     */
StartInputMethod(int index)399     int PerUserSession::StartInputMethod(int index)
400     {
401         IMSA_HILOGI("PerUserSession::StartInputMethod index = %{public}d [%{public}d]\n", index, userId_);
402 
403         if (imsCore[index] == nullptr) {
404             IMSA_HILOGI("PerUserSession::StartInputMethod imscore is null");
405             return ErrorCode::ERROR_IME_BIND_FAILED;
406         }
407 
408         sptr<IRemoteObject> b = imsCore[index]->AsObject();
409         inputMethodToken[index] = IPCSkeleton::GetInstance().GetContextObject();
410         localControlChannel[index] = new InputControlChannelStub(userId_);
411         inputControlChannel[index] = localControlChannel[index];
412         int ret_init = imsCore[index]->initializeInput(inputMethodToken[index], displayId, inputControlChannel[index]);
413         if (ret_init != ErrorCode::NO_ERROR) {
414             IMSA_HILOGE("PerUserSession::StartInputMethod initializeInput fail %{public}s", ErrorCode::ToString(ret_init));
415             localControlChannel[index] = nullptr;
416             inputControlChannel[index] = nullptr;
417             return ret_init;
418         }
419         return ErrorCode::NO_ERROR;
420     }
421 
422     /*! Stop input method service
423     \param index it can be 0 or 1. 0 - default ime, 1 - security ime
424     \return ErrorCode::NO_ERROR no error
425     \return ErrorCode::ERROR_IME_NOT_STARTED ime not started
426     \return ErrorCode::ERROR_IME_UNBIND_FAILED failed to unbind ime
427     \return ErrorCode::ERROR_TOKEN_DESTROY_FAILED failed to destroy window token
428     \return other errors returned by binder driver
429     */
StopInputMethod(int index)430     int PerUserSession::StopInputMethod(int index)
431     {
432         IMSA_HILOGI("Start... index = %{public}d [%{public}d]\n", index, userId_);
433         if (index >= MAX_IME || index < 0) {
434             IMSA_HILOGE("Aborted! %{public}s", ErrorCode::ToString(ErrorCode::ERROR_BAD_PARAMETERS));
435             return ErrorCode::ERROR_BAD_PARAMETERS;
436         }
437         if (imsCore[index] == nullptr || currentIme[index] == nullptr) {
438             IMSA_HILOGE("Aborted! %{public}s", ErrorCode::ToString(ErrorCode::ERROR_IME_NOT_STARTED));
439             return ErrorCode::ERROR_IME_NOT_STARTED;
440         }
441         if (currentIme[index] == currentIme[1 - index] && imsCore[1 - index] != nullptr) {
442             imsCore[index] = nullptr;
443             inputControlChannel[index] = nullptr;
444             localControlChannel[index] = nullptr;
445             IMSA_HILOGI("End...[%{public}d]\n", userId_);
446             return ErrorCode::NO_ERROR;
447         }
448 
449         IMSA_HILOGD("unbindInputMethodService...\n");
450 
451         IMSA_HILOGD("destroyWindowToken...\n");
452         int errorCode = ErrorCode::NO_ERROR;
453         int ret = Platform::Instance()->DestroyWindowToken(userId_, currentIme[index]->mPackageName);
454         inputMethodToken[index] = nullptr;
455         if (ret != ErrorCode::NO_ERROR) {
456             IMSA_HILOGE("destroyWindowToken return : %{public}s [%{public}d]\n", ErrorCode::ToString(ret), userId_);
457             errorCode = ErrorCode::ERROR_TOKEN_DESTROY_FAILED;
458         }
459         sptr<IRemoteObject> b = imsCore[index]->AsObject();
460         ret = b->RemoveDeathRecipient(imsDeathRecipient);
461         if (ret != ErrorCode::NO_ERROR) {
462             IMSA_HILOGE("RemoveDeathRecipient return : %{public}s [%{public}d]\n", ErrorCode::ToString(ret), userId_);
463         }
464         imsCore[index] = nullptr;
465         inputControlChannel[index] = nullptr;
466         localControlChannel[index] = nullptr;
467         IMSA_HILOGI("End...[%{public}d]\n", userId_);
468         return errorCode;
469     }
470 
471     /*! Show keyboard
472     \param inputClient the remote object handler of the input client.
473     \return ErrorCode::NO_ERROR no error
474     \return ErrorCode::ERROR_IME_NOT_STARTED ime not started
475     \return ErrorCode::ERROR_KBD_IS_OCCUPIED keyboard is showing by other client
476     \return ErrorCode::ERROR_CLIENT_NOT_FOUND the input client is not found
477     \return ErrorCode::ERROR_IME_START_FAILED failed to start input method service
478     \return ErrorCode::ERROR_KBD_SHOW_FAILED failed to show keyboard
479     \return other errors returned by binder driver
480     */
ShowKeyboard(const sptr<IInputClient> & inputClient)481     int PerUserSession::ShowKeyboard(const sptr<IInputClient>& inputClient)
482     {
483         IMSA_HILOGI("PerUserSession::ShowKeyboard");
484         ClientInfo *clientInfo = GetClientInfo(inputClient);
485         int index = GetImeIndex(inputClient);
486         if (index == -1 || clientInfo == nullptr) {
487             IMSA_HILOGE("PerUserSession::ShowKeyboard Aborted! index = -1 or clientInfo is nullptr");
488             return ErrorCode::ERROR_CLIENT_NOT_FOUND;
489         }
490 
491         if (imsCore[0] == nullptr) {
492             IMSA_HILOGE("PerUserSession::ShowKeyboard Aborted! imsCore[%{public}d] is nullptr", index);
493             return ErrorCode::ERROR_NULL_POINTER;
494         }
495 
496         imsCore[0]->showKeyboard(clientInfo->channel);
497 
498         SetCurrentClient(inputClient);
499         return ErrorCode::NO_ERROR;
500     }
501 
502     /*! hide keyboard
503     \param inputClient the remote object handler of the input client.
504     \return ErrorCode::NO_ERROR no error
505     \return ErrorCode::ERROR_IME_NOT_STARTED ime not started
506     \return ErrorCode::ERROR_KBD_IS_NOT_SHOWING keyboard has not been showing
507     \return ErrorCode::ERROR_CLIENT_NOT_FOUND the input client is not found
508     \return ErrorCode::ERROR_KBD_HIDE_FAILED failed to hide keyboard
509     \return other errors returned by binder driver
510     */
HideKeyboard(const sptr<IInputClient> & inputClient)511     int PerUserSession::HideKeyboard(const sptr<IInputClient>& inputClient)
512     {
513         IMSA_HILOGI("PerUserSession::HideKeyboard");
514         int index = GetImeIndex(inputClient);
515         if (index == -1) {
516             IMSA_HILOGE("PerUserSession::HideKeyboard Aborted! ErrorCode::ERROR_CLIENT_NOT_FOUND");
517             return ErrorCode::ERROR_CLIENT_NOT_FOUND;
518         }
519         ClientInfo *clientInfo = GetClientInfo(inputClient);
520         if (clientInfo == nullptr) {
521             IMSA_HILOGE("PerUserSession::HideKeyboard GetClientInfo pointer nullptr");
522         }
523         if (imsCore[0] == nullptr) {
524             IMSA_HILOGE("PerUserSession::HideKeyboard imsCore[index] is nullptr");
525             return ErrorCode::ERROR_IME_NOT_STARTED;
526         }
527 
528         bool ret = imsCore[0]->hideKeyboard(1);
529         if (!ret) {
530             IMSA_HILOGE("PerUserSession::HideKeyboard [imsCore->hideKeyboard] failed");
531             ret = ErrorCode::ERROR_KBD_HIDE_FAILED;
532         }
533 
534         return ErrorCode::NO_ERROR;
535     }
536 
537     /*! Get the display mode of the current keyboard showing
538     \return return display mode.
539     \n 0 - part sceen mode, 1 - full sceen mode
540     */
GetDisplayMode()541     int PerUserSession::GetDisplayMode()
542     {
543         return currentDisplayMode;
544     }
545 
546     /*! Get the keyboard window height
547     \param[out] retHeight the height of keyboard window showing or showed returned to caller
548     \return ErrorCode
549     */
GetKeyboardWindowHeight(int retHeight)550     int PerUserSession::GetKeyboardWindowHeight(int retHeight)
551     {
552         if (imsCore[lastImeIndex] != nullptr) {
553             int ret = imsCore[lastImeIndex]->getKeyboardWindowHeight(retHeight);
554             if (ret != ErrorCode::NO_ERROR) {
555                 IMSA_HILOGE("getKeyboardWindowHeight return : %{public}s", ErrorCode::ToString(ret));
556             }
557             return ret;
558         }
559         IMSA_HILOGW("No IME is started [%{public}d]\n", userId_);
560         return ErrorCode::ERROR_IME_NOT_STARTED;
561     }
562 
563     /*! Get the current keyboard type
564     \return return the pointer of the object of current keyboard type.
565     \n null if no keyboard type supported by the current ime.
566     \note The returned pointer should NOT be freed by the caller.
567     */
GetCurrentKeyboardType()568     KeyboardType *PerUserSession::GetCurrentKeyboardType()
569     {
570         if (inputMethodSetting == nullptr || currentIme[DEFAULT_IME] == nullptr) {
571             IMSA_HILOGI("Ime has not started ! [%{public}d]\n", userId_);
572             return nullptr;
573         }
574         if (currentIme[DEFAULT_IME] == currentIme[SECURITY_IME]) {
575             return nullptr;
576         }
577         int hashCode = inputMethodSetting->GetCurrentKeyboardType();  // To be checked.
578         if (hashCode == -1) {
579             std::vector<int> hashCodeList = inputMethodSetting->GetEnabledKeyboardTypes(currentIme[DEFAULT_IME]->mImeId);
580             if (hashCodeList.size() == 0) {
581                 IMSA_HILOGE("Cannot find any keyboard types for the current ime [%{public}d]\n", userId_);
582                 return nullptr;
583             }
584             hashCode = hashCodeList[0];
585         }
586 
587         for (int i = 0; i < (int)currentIme[DEFAULT_IME]->mTypes.size(); i++) {
588             if (currentIme[DEFAULT_IME]->mTypes[i]->getHashCode() == hashCode) {
589                 return currentIme[DEFAULT_IME]->mTypes[i];
590             }
591         }
592         return nullptr;
593     }
594 
595     /*! Handle the situation a remote input client died\n
596     It's called when a remote input client died
597     \param remoteObject the remote object handler of the input client died.
598     */
OnClientDied(IRemoteObject * remoteObject)599     void PerUserSession::OnClientDied(IRemoteObject *remoteObject)
600     {
601         IMSA_HILOGI("PerUserSession::OnClientDied Start...[%{public}d]\n", userId_);
602         auto it = mapClients.find(remoteObject);
603         if (it == mapClients.end()) {
604             IMSA_HILOGE("PerUserSession::RemoveClient client not found");
605             return;
606         }
607         sptr<IInputClient> client = GetCurrentClient();
608         if (client == nullptr) {
609             IMSA_HILOGE("current client is nullptr");
610             RemoveClient(it->first);
611             return;
612         }
613         if (client->AsObject().GetRefPtr() == remoteObject) {
614             int ret = HideKeyboard(client);
615             IMSA_HILOGI("hide keyboard ret: %{public}s", ErrorCode::ToString(ret));
616         }
617         RemoveClient(it->first);
618     }
619 
620     /*! Handle the situation a input method service died\n
621     It's called when an input method service died
622     \param remoteObject the remote object handler of input method service remoteObject died.
623     */
OnImsDied(IRemoteObject * remoteObject)624     void PerUserSession::OnImsDied(IRemoteObject *remoteObject)
625     {
626         (void)remoteObject;
627         IMSA_HILOGI("Start...[%{public}d]\n", userId_);
628         int index = 0;
629         for (int i = 0; i < MAX_IME; i++) {
630             if (imsCore[i] == nullptr) {
631                 continue;
632             }
633             auto b = imsCore[i]->AsObject();
634             if (b.GetRefPtr() == remoteObject) {
635                 index = i;
636                 break;
637             }
638         }
639         ClearImeData(index);
640         if (!IsRestartIme(index)) {
641             IMSA_HILOGI("Restart ime over max num");
642             return;
643         }
644         IMSA_HILOGI("IME died. Restart input method...[%{public}d]\n", userId_);
645         const auto &ime = ParaHandle::GetDefaultIme(userId_);
646         auto *parcel = new (std::nothrow) MessageParcel();
647         if (parcel == nullptr) {
648             IMSA_HILOGE("parcel is nullptr");
649             return;
650         }
651         parcel->WriteString(ime);
652         auto *msg = new (std::nothrow) Message(MSG_ID_START_INPUT_SERVICE, parcel);
653         if (msg == nullptr) {
654             IMSA_HILOGE("msg is nullptr");
655             delete parcel;
656             return;
657         }
658         usleep(MAX_RESET_WAIT_TIME);
659         MessageHandler::Instance()->SendMessage(msg);
660         IMSA_HILOGI("End...[%{public}d]\n", userId_);
661     }
662 
663     /*! It's called when input method setting data in the system is changed
664     \param key the name of setting item changed.
665     \param value the value of setting item changed.
666     \return ErrorCode::NO_ERROR no error
667     \return ErrorCode::ERROR_SETTING_SAME_VALUE the current value is same as the one in the system.
668     */
OnSettingChanged(const std::u16string & key,const std::u16string & value)669     int PerUserSession::OnSettingChanged(const std::u16string& key, const std::u16string& value)
670     {
671         IMSA_HILOGI("Start...[%{public}d]\n", userId_);
672         std::unique_lock<std::mutex> lock(mtx);
673         if (inputMethodSetting == nullptr) {
674             return ErrorCode::ERROR_NULL_POINTER;
675         }
676         std::u16string currentValue = inputMethodSetting->GetValue(key);
677 
678         IMSA_HILOGD("PerUserSession::OnSettingChanged key = %{public}s", Utils::to_utf8(key).c_str());
679         IMSA_HILOGD("PerUserSession::OnSettingChanged value = %{public}s", Utils::to_utf8(value).c_str());
680         IMSA_HILOGD("PerUserSession::OnSettingChanged currentValue = %{public}s", Utils::to_utf8(currentValue).c_str());
681 
682         if (currentValue == value) {
683             IMSA_HILOGI("End...[%{public}d]\n", userId_);
684             return ErrorCode::ERROR_SETTING_SAME_VALUE;
685         }
686         sptr<IInputClient> client = GetCurrentClient();
687         if (key == InputMethodSetting::CURRENT_KEYBOARD_TYPE_TAG) {
688             return OnCurrentKeyboardTypeChanged(DEFAULT_IME, value);
689         } else if (key == InputMethodSetting::CURRENT_SYS_KEYBOARD_TYPE_TAG) {
690             return OnCurrentKeyboardTypeChanged(SECURITY_IME, value);
691         } else if (key == InputMethodSetting::CURRENT_INPUT_METHOD_TAG) {
692             if (currentIme[DEFAULT_IME] == nullptr || value == currentIme[DEFAULT_IME]->mImeId) {
693                 return ErrorCode::NO_ERROR;
694             }
695             if (client != nullptr && GetImeIndex(client) == DEFAULT_IME) {
696                 needReshowClient = client;
697                 HideKeyboard(client);
698             }
699             StopInputMethod(DEFAULT_IME);
700             currentIme[DEFAULT_IME] = nullptr;
701             currentKbdIndex[DEFAULT_IME] = 0;
702             inputMethodSetting->SetCurrentKeyboardType(-1);
703         } else if (key == InputMethodSetting::ENABLED_INPUT_METHODS_TAG) {
704             if (currentIme[DEFAULT_IME] != nullptr && currentIme[DEFAULT_IME] != currentIme[SECURITY_IME]
705                 && value.find(currentIme[DEFAULT_IME]->mImeId) == std::string::npos) {
706                 if (client != nullptr && GetImeIndex(client) == DEFAULT_IME) {
707                     needReshowClient = client;
708                     HideKeyboard(client);
709                 }
710                 StopInputMethod(DEFAULT_IME);
711                 currentIme[DEFAULT_IME] = nullptr;
712                 currentKbdIndex[DEFAULT_IME] = 0;
713                 inputMethodSetting->SetCurrentKeyboardType(-1);
714             }
715         }
716         IMSA_HILOGI("End...[%{public}d]\n", userId_);
717         return ErrorCode::NO_ERROR;
718     }
719 
720     /*! Change current keyboard type.
721     \param index it can be 0 or 1. 0 - default ime, 1 - security ime.
722     \param value the hash code of keyboard type
723     \return ErrorCode::NO_ERROR no error
724     \return ErrorCode::ERROR_SETTING_SAME_VALUE the current value is same as the one in the system.
725     */
OnCurrentKeyboardTypeChanged(int index,const std::u16string & value)726     int PerUserSession::OnCurrentKeyboardTypeChanged(int index, const std::u16string& value)
727     {
728         std::string str = Utils::to_utf8(value);
729         int hashCode = std::atoi(str.c_str());
730         if (hashCode == -1) {
731             return ErrorCode::ERROR_SETTING_SAME_VALUE;;
732         }
733         // switch within the current ime.
734         if (index == SECURITY_IME || currentIme[DEFAULT_IME] == currentIme[SECURITY_IME]) {
735             int num = currentKbdIndex[index];
736             if (currentIme[index]->mTypes[num]->getHashCode() == hashCode) {
737                 return ErrorCode::ERROR_SETTING_SAME_VALUE;
738             }
739             for (int i = 0; i < (int)currentIme[index]->mTypes.size(); i++) {
740                 if (currentIme[index]->mTypes[i]->getHashCode() == hashCode) {
741                     currentKbdIndex[index] = i;
742                     break;
743                 }
744             }
745         } else {
746             std::u16string imeId = currentIme[index]->mImeId;
747             std::vector<int> currentKbdTypes = inputMethodSetting->GetEnabledKeyboardTypes(imeId);
748             int num = currentKbdIndex[index];
749             if (currentKbdTypes[num] == hashCode) {
750                 return ErrorCode::ERROR_SETTING_SAME_VALUE;
751             }
752             for (int i = 0; i < (int)currentKbdTypes.size(); i++) {
753                 if (currentKbdTypes[i] == hashCode) {
754                     currentKbdIndex[index] = i;
755                     break;
756                 }
757             }
758         }
759         KeyboardType *type = GetKeyboardType(index, currentKbdIndex[index]);
760         if (type != nullptr) {
761             if (GetCurrentClient() != nullptr) {
762                 int ret = imsCore[index]->setKeyboardType(*type);
763                 if (ret != ErrorCode::NO_ERROR) {
764                     IMSA_HILOGE("setKeyboardType return : %{public}s [%{public}d]\n", ErrorCode::ToString(ret), userId_);
765                 }
766             }
767             if (imsCore[index] == imsCore[1 - index]) {
768                 inputMethodSetting->SetCurrentKeyboardType(type->getHashCode());
769                 inputMethodSetting->SetCurrentSysKeyboardType(type->getHashCode());
770                 currentKbdIndex[1 - index] = currentKbdIndex[index];
771             } else if (index == DEFAULT_IME) {
772                 inputMethodSetting->SetCurrentKeyboardType(type->getHashCode());
773             } else {
774                 inputMethodSetting->SetCurrentSysKeyboardType(type->getHashCode());
775             }
776         }
777         return ErrorCode::NO_ERROR;
778     }
779 
780     /*! Hide current keyboard
781     \param flag the flag to hide keyboard.
782     */
OnHideKeyboardSelf(int flags)783     void PerUserSession::OnHideKeyboardSelf(int flags)
784     {
785         IMSA_HILOGW("PerUserSession::OnHideKeyboardSelf");
786         (void) flags;
787         sptr<IInputClient> client = GetCurrentClient();
788         if (client == nullptr) {
789             IMSA_HILOGE("current client is nullptr");
790             return;
791         }
792         HideKeyboard(client);
793     }
794 
795     /*! Switch to next keyboard type
796     */
OnAdvanceToNext()797     void PerUserSession::OnAdvanceToNext()
798     {
799         sptr<IInputClient> client = GetCurrentClient();
800         if (client == nullptr) {
801             IMSA_HILOGE("current client is nullptr");
802             return;
803         }
804         int index = GetImeIndex(client);
805         if (index == -1) {
806             IMSA_HILOGW("%{public}s [%{public}d]\n", ErrorCode::ToString(ErrorCode::ERROR_CLIENT_NOT_FOUND), userId_);
807             return;
808         }
809         int size = 0;
810         if (index == SECURITY_IME || currentIme[DEFAULT_IME] == currentIme[SECURITY_IME]) {
811             size = currentIme[index]->mTypes.size();
812         } else {
813             std::u16string imeId = currentIme[index]->mImeId;
814             std::vector<int> currentKbdTypes = inputMethodSetting->GetEnabledKeyboardTypes(imeId);
815             size = currentKbdTypes.size();
816         }
817         if (size < MIN_IME) {
818             IMSA_HILOGW("No next keyboard is available. [%{public}d]\n", userId_);
819             return;
820         }
821 
822         int num = currentKbdIndex[index]+1;
823         if (size != 0) {
824             num %= size;
825         }
826         KeyboardType *type = GetKeyboardType(index, num);
827         if (type == nullptr) {
828             IMSA_HILOGW("No next keyboard is available. [%{public}d]\n", userId_);
829             return;
830         }
831         InputMethodSetting tmpSetting;
832         if (imsCore[index] == imsCore[1 - index]) {
833             tmpSetting.SetCurrentKeyboardType(type->getHashCode());
834             tmpSetting.SetCurrentSysKeyboardType(type->getHashCode());
835         }
836         else if (index == DEFAULT_IME) {
837             tmpSetting.SetCurrentKeyboardType(type->getHashCode());
838         } else {
839             tmpSetting.SetCurrentSysKeyboardType(type->getHashCode());
840         }
841         Platform::Instance()->SetInputMethodSetting(userId_, tmpSetting);
842     }
843 
844     /*! Set display mode
845     \param mode the display mode of soft keyboard UI.
846     \n 0 - part sceen mode, 1 - full sceen mode
847     */
OnSetDisplayMode(int mode)848     void PerUserSession::OnSetDisplayMode(int mode)
849     {
850         currentDisplayMode = mode;
851         sptr<IInputClient> client = GetCurrentClient();
852         if (client == nullptr) {
853             IMSA_HILOGE("current client is nullptr");
854             return;
855         }
856         ClientInfo *clientInfo = GetClientInfo(client);
857         if (clientInfo == nullptr) {
858             IMSA_HILOGE("%{public}s [%{public}d]\n", ErrorCode::ToString(ErrorCode::ERROR_CLIENT_NOT_FOUND), userId_);
859             return;
860         }
861         int ret = clientInfo->client->setDisplayMode(mode);
862         if (ret != ErrorCode::NO_ERROR) {
863             IMSA_HILOGE("setDisplayMode return : %{public}s [%{public}d]\n", ErrorCode::ToString(ret), userId_);
864         }
865     }
866 
867     /*! Restart input method service
868     \param index it can be DEFAULT_IME or SECURITY_IME
869     \param imeId the id of the input method service going to restart
870     */
OnRestartIms(int index,const std::u16string & imeId)871     void PerUserSession::OnRestartIms(int index, const std::u16string& imeId)
872     {
873         if (index < 0 || index >= MAX_IME) {
874             return;
875         }
876         IMSA_HILOGI("Start...[%{public}d]\n", userId_);
877         if (currentIme[index] && currentIme[index]->mImeId == imeId) {
878             int ret = StartInputMethod(index);
879             if (needReshowClient && GetImeIndex(needReshowClient) == index) {
880                 if (ret == ErrorCode::NO_ERROR) {
881                     ShowKeyboard(needReshowClient);
882                 }
883                 needReshowClient = nullptr;
884             }
885         }
886         IMSA_HILOGI("End...[%{public}d]\n", userId_);
887     }
888 
889     /*! It's called when this user is locked
890     */
OnUserLocked()891     void PerUserSession::OnUserLocked()
892     {
893         IMSA_HILOGI("PerUserSession::OnUserLocked");
894         if (userState == UserState::USER_STATE_STARTED) {
895             IMSA_HILOGI("End...[%{public}d]\n", userId_);
896             return;
897         }
898         userState = UserState::USER_STATE_STARTED;
899         // hide current keyboard
900         sptr<IInputClient> client = GetCurrentClient();
901         if (client != nullptr) {
902             HideKeyboard(client);
903         }
904         for (int i = 0; i < MIN_IME; i++) {
905             StopInputMethod(i);
906             currentIme[i] = nullptr;
907         }
908         // disconnect all clients.
909         for (auto it = mapClients.begin(); it != mapClients.end();) {
910             auto object = it->first;
911             ClientInfo *clientInfo = it->second;
912             if (clientInfo != nullptr) {
913                 object->RemoveDeathRecipient(clientInfo->deathRecipient);
914                 int ret = clientInfo->client->onInputReleased(0);
915                 if (ret != ErrorCode::NO_ERROR) {
916                     IMSA_HILOGE("2-onInputReleased return : %{public}s", ErrorCode::ToString(ret));
917                 }
918                 delete clientInfo;
919                 clientInfo = nullptr;
920             }
921             IMSA_HILOGD("erase client..\n");
922             it = mapClients.erase(it);
923         }
924         mapClients.clear();
925 
926         // reset values
927         inputMethodSetting = nullptr;
928         SetCurrentClient(nullptr);
929         needReshowClient = nullptr;
930     }
931 
932     /*! Get keyboard type
933     \param imeIndex it can be 0 or 1.  0 - default ime, 1 - security ime
934     \param typeIndex the index of keyboard type.
935     \return a KeyboardType pointer when it's found.
936     \return null when it's not found.
937     \note The returned pointer should not be freed by caller.
938     */
GetKeyboardType(int imeIndex,int typeIndex)939     KeyboardType *PerUserSession::GetKeyboardType(int imeIndex, int typeIndex)
940     {
941         if (typeIndex < 0) {
942             return nullptr;
943         }
944         if (imeIndex == SECURITY_IME || currentIme[DEFAULT_IME] == currentIme[SECURITY_IME]) {
945             if (typeIndex >= (int)currentIme[imeIndex]->mTypes.size()) {
946                 return nullptr;
947             }
948             return currentIme[imeIndex]->mTypes[typeIndex];
949         } else {
950             std::u16string imeId = currentIme[imeIndex]->mImeId;
951             std::vector<int> currentKbdTypes = inputMethodSetting->GetEnabledKeyboardTypes(imeId);
952             int size = currentKbdTypes.size();
953             if (typeIndex >= size) {
954                 return nullptr;
955             }
956             int hashCode = currentKbdTypes[typeIndex];
957             for (int i = 0; i < (int)currentIme[imeIndex]->mTypes.size(); i++) {
958                 if (currentIme[imeIndex]->mTypes[i]->getHashCode() == hashCode) {
959                     return currentIme[imeIndex]->mTypes[i];
960                 }
961             }
962         }
963         return nullptr;
964     }
965 
966     /*! Reset current keyboard type
967     \param imeIndex it can be 0 or 1. 0 - default ime, 1 - security ime
968     */
ResetCurrentKeyboardType(int imeIndex)969     void PerUserSession::ResetCurrentKeyboardType(int imeIndex)
970     {
971         if (imeIndex < 0 || imeIndex > 1) {
972             return;
973         }
974         currentKbdIndex[imeIndex] = 0;
975         int hashCode = 0;
976         if (imeIndex == DEFAULT_IME) {
977             hashCode = inputMethodSetting->GetCurrentKeyboardType();
978         } else {
979             hashCode = inputMethodSetting->GetCurrentSysKeyboardType();
980         }
981         KeyboardType *type = nullptr;
982         if (hashCode == -1) {
983             type  = GetKeyboardType(imeIndex, currentKbdIndex[imeIndex]);
984         } else {
985             bool flag = false;
986             if (imeIndex == SECURITY_IME || currentIme[DEFAULT_IME] == currentIme[SECURITY_IME]) {
987                 for (int i = 0; i < (int)currentIme[imeIndex]->mTypes.size(); i++) {
988                     if (currentIme[imeIndex]->mTypes[i]->getHashCode() == hashCode) {
989                         currentKbdIndex[imeIndex] = i;
990                         flag = true;
991                         break;
992                     }
993                 }
994             } else {
995                 std::vector<int> hashCodeList = inputMethodSetting->GetEnabledKeyboardTypes(currentIme[imeIndex]->mImeId);
996                 for (int i = 0; i < (int)hashCodeList.size(); i++) {
997                     if (hashCode == hashCodeList[i]) {
998                         currentKbdIndex[imeIndex] = i;
999                         flag = true;
1000                         break;
1001                     }
1002                 }
1003             }
1004             if (flag == false) {
1005                 IMSA_HILOGW("The current keyboard type is not found in the current IME. Reset it!");
1006                 type = GetKeyboardType(imeIndex, currentKbdIndex[imeIndex]);
1007             } else if (imsCore[imeIndex] == imsCore[1 - imeIndex]) {
1008                 currentKbdIndex[1 - imeIndex] = currentKbdIndex[imeIndex];
1009             }
1010         }
1011         if (type != nullptr) {
1012             InputMethodSetting tmpSetting;
1013             if (imsCore[imeIndex] == imsCore[1 - imeIndex]) {
1014                 inputMethodSetting->SetCurrentKeyboardType(type->getHashCode());
1015                 inputMethodSetting->SetCurrentSysKeyboardType(type->getHashCode());
1016                 currentKbdIndex[1 - imeIndex] = currentKbdIndex[imeIndex];
1017                 tmpSetting.SetCurrentKeyboardType(type->getHashCode());
1018                 tmpSetting.SetCurrentSysKeyboardType(type->getHashCode());
1019             } else if (imeIndex == DEFAULT_IME) {
1020                 tmpSetting.SetCurrentKeyboardType(type->getHashCode());
1021                 inputMethodSetting->SetCurrentKeyboardType(type->getHashCode());
1022             } else {
1023                 tmpSetting.SetCurrentSysKeyboardType(type->getHashCode());
1024                 inputMethodSetting->SetCurrentSysKeyboardType(type->getHashCode());
1025             }
1026             Platform::Instance()->SetInputMethodSetting(userId_, tmpSetting);
1027         }
1028     }
1029 
1030     /*! Get ime index for the input client
1031     \param inputClient the remote object handler of an input client.
1032     \return 0 - default ime
1033     \return 1 - security ime
1034     \return -1 - input client is not found
1035     */
GetImeIndex(const sptr<IInputClient> & inputClient)1036     int PerUserSession::GetImeIndex(const sptr<IInputClient>& inputClient)
1037     {
1038         if (inputClient == nullptr) {
1039             IMSA_HILOGW("PerUserSession::GetImeIndex inputClient is nullptr");
1040             return -1;
1041         }
1042 
1043         ClientInfo *clientInfo = GetClientInfo(inputClient);
1044         if (clientInfo == nullptr) {
1045             IMSA_HILOGW("PerUserSession::GetImeIndex clientInfo is nullptr");
1046             return -1;
1047         }
1048 
1049         if (clientInfo->attribute.GetSecurityFlag() == true) {
1050             return SECURITY_IME;
1051         }
1052         return DEFAULT_IME;
1053     }
1054 
1055     /*! Copy session data from one IME to another IME
1056     \param imeIndex it can be 0 or 1.
1057     \n 0 - default ime, 1 - security ime
1058     */
CopyInputMethodService(int imeIndex)1059     void PerUserSession::CopyInputMethodService(int imeIndex)
1060     {
1061         imsCore[imeIndex] = imsCore[1 - imeIndex];
1062         localControlChannel[imeIndex] = localControlChannel[1 - imeIndex];
1063         inputControlChannel[imeIndex] = inputControlChannel[1 - imeIndex];
1064         inputMethodToken[imeIndex] = inputMethodToken[1 - imeIndex];
1065         currentKbdIndex[imeIndex] = currentKbdIndex[1 - imeIndex];
1066         int hashCode[2];
1067         hashCode[0] = inputMethodSetting->GetCurrentKeyboardType();
1068         hashCode[1] = inputMethodSetting->GetCurrentSysKeyboardType();
1069         if (hashCode[imeIndex] != hashCode[1 - imeIndex]) {
1070             hashCode[imeIndex] = hashCode[1 - imeIndex];
1071             inputMethodSetting->SetCurrentKeyboardType(hashCode[0]);
1072             inputMethodSetting->SetCurrentSysKeyboardType(hashCode[1]);
1073 
1074             InputMethodSetting tmpSetting;
1075             tmpSetting.ClearData();
1076             tmpSetting.SetCurrentKeyboardType(hashCode[0]);
1077             tmpSetting.SetCurrentSysKeyboardType(hashCode[1]);
1078             Platform::Instance()->SetInputMethodSetting(userId_, tmpSetting);
1079         }
1080     }
1081 
1082     /*! Get ClientInfo
1083     \param inputClient the IInputClient remote handler of given input client
1084     \return a pointer of ClientInfo if client is found
1085     \n      null if client is not found
1086     \note the clientInfo pointer should not be freed by caller
1087     */
GetClientInfo(const sptr<IInputClient> & inputClient)1088     ClientInfo *PerUserSession::GetClientInfo(const sptr<IInputClient> &inputClient)
1089     {
1090         if (inputClient == nullptr) {
1091             IMSA_HILOGE("PerUserSession::GetClientInfo inputClient is nullptr");
1092             return nullptr;
1093         }
1094         sptr<IRemoteObject> object = Platform::RemoteBrokerToObject(inputClient);
1095         auto it = mapClients.find(object);
1096         if (it == mapClients.end()) {
1097             IMSA_HILOGE("client not found");
1098             return nullptr;
1099         }
1100         return it->second;
1101     }
1102 
StartInputService()1103     bool PerUserSession::StartInputService()
1104     {
1105         IMSA_HILOGE("PerUserSession::StartInputService");
1106         sptr<AAFwk::IAbilityManager> ams = GetAbilityManagerService();
1107         if (ams == nullptr) {
1108             return false;
1109         }
1110         AAFwk::Want want;
1111         want.SetAction("action.system.inputmethod");
1112         want.SetElementName("com.example.kikakeyboard", "com.example.kikakeyboard.ServiceExtAbility");
1113         int32_t result = ams->StartAbility(want);
1114         if (result != 0) {
1115             IMSA_HILOGE("PerUserSession::StartInputService fail. result = %{public}d", result);
1116             return false;
1117         }
1118         return true;
1119     }
1120 
GetAbilityManagerService()1121     sptr<AAFwk::IAbilityManager> PerUserSession::GetAbilityManagerService()
1122     {
1123         IMSA_HILOGE("GetAbilityManagerService start");
1124         sptr<IRemoteObject> abilityMsObj =
1125         OHOS::DelayedSingleton<AAFwk::SaMgrClient>::GetInstance()->GetSystemAbility(ABILITY_MGR_SERVICE_ID);
1126         if (abilityMsObj == nullptr) {
1127             IMSA_HILOGE("failed to get ability manager service");
1128             return nullptr;
1129         }
1130         return iface_cast<AAFwk::IAbilityManager>(abilityMsObj);
1131     }
1132 
1133     /*! Prepare input. Called by an input client.
1134     \n Run in work thread of this user
1135     \param msg the parameters from remote client are saved in msg->msgContent_
1136     \return ErrorCode
1137     */
OnPrepareInput(Message * msg)1138     void PerUserSession::OnPrepareInput(Message *msg)
1139     {
1140         IMSA_HILOGI("PerUserSession::OnPrepareInput Start...[%{public}d]\n", userId_);
1141         MessageParcel *data = msg->msgContent_;
1142         int pid = data->ReadInt32();
1143         int uid = data->ReadInt32();
1144         int displayId = data->ReadInt32();
1145 
1146         sptr<IRemoteObject> clientObject = data->ReadRemoteObject();
1147         if (clientObject == nullptr) {
1148             IMSA_HILOGI("PerUserSession::OnPrepareInput clientObject is null");
1149             return;
1150         }
1151 
1152         sptr<InputClientProxy> client = new InputClientProxy(clientObject);
1153         sptr<IRemoteObject> channelObject = data->ReadRemoteObject();
1154         if (channelObject == nullptr) {
1155             IMSA_HILOGI("PerUserSession::OnPrepareInput channelObject is null");
1156             return;
1157         }
1158 
1159         sptr<InputDataChannelProxy> channel = new InputDataChannelProxy(channelObject);
1160         InputAttribute *attribute = data->ReadParcelable<InputAttribute>();
1161         if (attribute == nullptr) {
1162             IMSA_HILOGI("PerUserSession::OnPrepareInput attribute is nullptr");
1163             return;
1164         }
1165 
1166         sptr<RemoteObjectDeathRecipient> clientDeathRecipient = new (std::nothrow)
1167             RemoteObjectDeathRecipient(Utils::GetUserId(), MSG_ID_CLIENT_DIED);
1168         if (clientDeathRecipient == nullptr) {
1169             IMSA_HILOGE("failed to create clientDeathRecipient");
1170         }
1171 
1172         int ret = AddClient({ pid, uid, userId_, displayId, client, channel, *attribute, clientDeathRecipient });
1173         delete attribute;
1174         if (ret != ErrorCode::NO_ERROR) {
1175             IMSA_HILOGE("PerUserSession::OnPrepareInput Aborted! %{public}s", ErrorCode::ToString(ret));
1176             return;
1177         }
1178         SendAgentToSingleClient(client);
1179     }
1180 
SendAgentToSingleClient(const sptr<IInputClient> & inputClient)1181     void PerUserSession::SendAgentToSingleClient(const sptr<IInputClient>& inputClient)
1182     {
1183         IMSA_HILOGI("PerUserSession::SendAgentToSingleClient");
1184         if (imsAgent == nullptr) {
1185             IMSA_HILOGI("PerUserSession::SendAgentToSingleClient imsAgent is nullptr");
1186             return;
1187         }
1188         ClientInfo *clientInfo = GetClientInfo(inputClient);
1189         if (clientInfo == nullptr) {
1190             IMSA_HILOGE("PerUserSession::SendAgentToSingleClient clientInfo is nullptr");
1191             return;
1192         }
1193         clientInfo->client->onInputReady(imsAgent);
1194     }
1195 
1196     /*! Release input. Called by an input client.
1197     \n Run in work thread of this user
1198     \param msg the parameters from remote client are saved in msg->msgContent_
1199     \return ErrorCode
1200     */
OnReleaseInput(Message * msg)1201     void PerUserSession::OnReleaseInput(Message *msg)
1202     {
1203         IMSA_HILOGI("PerUserSession::OnReleaseInput Start...[%{public}d]\n", userId_);
1204         MessageParcel *data = msg->msgContent_;
1205 
1206         sptr<IRemoteObject> clientObject = data->ReadRemoteObject();
1207         sptr<InputClientProxy> client = new InputClientProxy(clientObject);
1208         sptr<IInputClient> interface = client;
1209         if (imsCore[0] != nullptr) {
1210             imsCore[0]->SetClientState(false);
1211         }
1212         HideKeyboard(client);
1213         RemoveClient(clientObject.GetRefPtr());
1214         IMSA_HILOGI("PerUserSession::OnReleaseInput End...[%{public}d]\n", userId_);
1215     }
1216 
1217     /*! Start input. Called by an input client.
1218     \n Run in work thread of this user
1219     \param msg the parameters from remote client are saved in msg->msgContent_
1220     \return ErrorCode
1221     */
OnStartInput(Message * msg)1222     void PerUserSession::OnStartInput(Message *msg)
1223     {
1224         IMSA_HILOGI("PerUserSession::OnStartInput");
1225         MessageParcel *data = msg->msgContent_;
1226         sptr<IRemoteObject> clientObject = data->ReadRemoteObject();
1227         sptr<InputClientProxy> client = new InputClientProxy(clientObject);
1228         if (imsCore[0] != nullptr) {
1229             imsCore[0]->SetClientState(true);
1230         }
1231         ShowKeyboard(client);
1232     }
1233 
SetCoreAndAgent(Message * msg)1234     void PerUserSession::SetCoreAndAgent(Message *msg)
1235     {
1236         IMSA_HILOGI("PerUserSession::SetCoreAndAgent Start...[%{public}d]\n", userId_);
1237         auto data = msg->msgContent_;
1238 
1239         auto coreObject = data->ReadRemoteObject();
1240         if (coreObject == nullptr) {
1241             IMSA_HILOGE("coreObject is nullptr");
1242             return;
1243         }
1244         auto core = new (std::nothrow) InputMethodCoreProxy(coreObject);
1245         if (core == nullptr) {
1246             IMSA_HILOGE("core is nullptr");
1247             return;
1248         }
1249         if (imsCore[0] != nullptr) {
1250             IMSA_HILOGI("PerUserSession::SetCoreAndAgent Input Method Service has already been started ! ");
1251         }
1252         imsCore[0] = core;
1253 
1254         bool ret = coreObject->AddDeathRecipient(imsDeathRecipient);
1255         IMSA_HILOGI("Add death recipient %{public}s", ret ? "success" : "failed");
1256 
1257         auto agentObject = data->ReadRemoteObject();
1258         auto proxy = new (std::nothrow) InputMethodAgentProxy(agentObject);
1259         if (proxy == nullptr) {
1260             IMSA_HILOGE("proxy is nullptr");
1261             return;
1262         }
1263         imsAgent = proxy;
1264 
1265         InitInputControlChannel();
1266 
1267         SendAgentToAllClients();
1268     }
1269 
SendAgentToAllClients()1270     void PerUserSession::SendAgentToAllClients()
1271     {
1272         IMSA_HILOGI("PerUserSession::SendAgentToAllClients");
1273         if (imsAgent == nullptr) {
1274             IMSA_HILOGI("PerUserSession::SendAgentToAllClients imsAgent is nullptr");
1275             return;
1276         }
1277 
1278         for (auto & mapClient : mapClients) {
1279             auto clientInfo = mapClient.second;
1280             if (clientInfo != nullptr) {
1281                 clientInfo->client->onInputReady(imsAgent);
1282             }
1283         }
1284     }
1285 
InitInputControlChannel()1286     void PerUserSession::InitInputControlChannel()
1287     {
1288         IMSA_HILOGI("PerUserSession::InitInputControlChannel");
1289         sptr<IInputControlChannel> inputControlChannel = new InputControlChannelStub(userId_);
1290         int ret = imsCore[0]->InitInputControlChannel(inputControlChannel);
1291         if (ret != ErrorCode::NO_ERROR) {
1292             IMSA_HILOGI("PerUserSession::InitInputControlChannel fail %{public}s", ErrorCode::ToString(ret));
1293         }
1294     }
1295 
1296     /*! Stop input. Called by an input client.
1297     \n Run in work thread of this user
1298     \param msg the parameters from remote client are saved in msg->msgContent_
1299     \return ErrorCode
1300     */
OnStopInput(Message * msg)1301     void PerUserSession::OnStopInput(Message *msg)
1302     {
1303         IMSA_HILOGI("PerUserSession::OnStopInput");
1304         MessageParcel *data = msg->msgContent_;
1305 
1306         sptr<IRemoteObject> clientObject = data->ReadRemoteObject();
1307         sptr<InputClientProxy> client = new InputClientProxy(clientObject);
1308         HideKeyboard(client);
1309     }
1310 
StopInputService(std::string imeId)1311     void PerUserSession::StopInputService(std::string imeId)
1312     {
1313         IMSA_HILOGI("PerUserSession::StopInputService");
1314         if (imsCore[0] == nullptr) {
1315             IMSA_HILOGE("imsCore[0] is nullptr");
1316             return;
1317         }
1318         IMSA_HILOGI("Remove death recipient");
1319         imsCore[0]->AsObject()->RemoveDeathRecipient(imsDeathRecipient);
1320         imsCore[0]->StopInputService(imeId);
1321     }
1322 
IsRestartIme(uint32_t index)1323     bool PerUserSession::IsRestartIme(uint32_t index)
1324     {
1325         IMSA_HILOGI("PerUserSession::IsRestartIme");
1326         std::lock_guard<std::mutex> lock(resetLock);
1327         auto now = time(nullptr);
1328         if (difftime(now, manager[index].last) > IME_RESET_TIME_OUT) {
1329             manager[index] = { 0, now };
1330         }
1331         ++manager[index].num;
1332         return manager[index].num <= MAX_RESTART_NUM;
1333     }
1334 
ResetImeError(uint32_t index)1335     void PerUserSession::ResetImeError(uint32_t index)
1336     {
1337         IMSA_HILOGI("PerUserSession::ResetImeError index = %{public}d", index);
1338         std::lock_guard<std::mutex> lock(resetLock);
1339         manager[index] = { 0, 0 };
1340     }
1341 
ClearImeData(uint32_t index)1342     void PerUserSession::ClearImeData(uint32_t index)
1343     {
1344         IMSA_HILOGI("Clear ime...index = %{public}d", index);
1345         if (imsCore[index] != nullptr) {
1346             imsCore[index]->AsObject()->RemoveDeathRecipient(imsDeathRecipient);
1347             imsCore[index] = nullptr;
1348         }
1349         inputControlChannel[index] = nullptr;
1350         localControlChannel[index] = nullptr;
1351         inputMethodToken[index] = nullptr;
1352     }
1353 
SetCurrentClient(sptr<IInputClient> client)1354     void PerUserSession::SetCurrentClient(sptr<IInputClient> client)
1355     {
1356         IMSA_HILOGI("set current client");
1357         std::lock_guard<std::mutex> lock(clientLock_);
1358         currentClient = client;
1359     }
1360 
GetCurrentClient()1361     sptr<IInputClient> PerUserSession::GetCurrentClient()
1362     {
1363         std::lock_guard<std::mutex> lock(clientLock_);
1364         return currentClient;
1365     }
1366 } // namespace MiscServices
1367 } // namespace OHOS
1368