• 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 "input_method_ability.h"
17 
18 #include "input_method_agent_proxy.h"
19 #include "input_method_agent_stub.h"
20 #include "input_method_core_proxy.h"
21 #include "input_method_core_stub.h"
22 #include "input_method_utils.h"
23 #include "iservice_registry.h"
24 #include "message_parcel.h"
25 #include "para_handle.h"
26 #include "string_ex.h"
27 #include "system_ability_definition.h"
28 #include "utils.h"
29 
30 namespace OHOS {
31 namespace MiscServices {
32     class MessageHandler;
33     using namespace MessageID;
34     sptr<InputMethodAbility> InputMethodAbility::instance_;
35     std::mutex InputMethodAbility::instanceLock_;
36 
InputMethodAbility()37     InputMethodAbility::InputMethodAbility() : stop_(false)
38     {
39         writeInputChannel = nullptr;
40         Initialize();
41     }
42 
~InputMethodAbility()43     InputMethodAbility::~InputMethodAbility()
44     {
45         IMSA_HILOGI("InputMethodAbility::~InputMethodAbility");
46         instance_ = nullptr;
47         if (msgHandler != nullptr) {
48             delete msgHandler;
49             msgHandler = nullptr;
50         }
51         stop_ = true;
52     }
53 
GetInstance()54     sptr<InputMethodAbility> InputMethodAbility::GetInstance()
55     {
56         IMSA_HILOGI("InputMethodAbility::GetInstance");
57         if (instance_ == nullptr) {
58             std::lock_guard<std::mutex> autoLock(instanceLock_);
59             if (instance_ == nullptr) {
60                 IMSA_HILOGI("InputMethodAbility::GetInstance need new IMA");
61                 instance_ = new InputMethodAbility();
62             }
63         }
64         return instance_;
65     }
66 
GetImsaProxy()67     sptr<InputMethodSystemAbilityProxy> InputMethodAbility::GetImsaProxy()
68     {
69         IMSA_HILOGI("InputMethodAbility::GetImsaProxy");
70         sptr<ISystemAbilityManager> systemAbilityManager =
71             SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
72         if (systemAbilityManager == nullptr) {
73             IMSA_HILOGI("systemAbilityManager is nullptr");
74             return nullptr;
75         }
76 
77         auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, "");
78         if (systemAbility == nullptr) {
79             IMSA_HILOGI("systemAbility is nullptr");
80             return nullptr;
81         }
82         if (deathRecipientPtr_ == nullptr) {
83             deathRecipientPtr_ = new (std::nothrow) ServiceDeathRecipient();
84             if (deathRecipientPtr_ == nullptr) {
85                 IMSA_HILOGE("failed to new ServiceDeathRecipient");
86                 return nullptr;
87             }
88         }
89         if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipientPtr_))) {
90             IMSA_HILOGE("failed to add death recipient.");
91         }
92         sptr<InputMethodSystemAbilityProxy> iface = new InputMethodSystemAbilityProxy(systemAbility);
93         return iface;
94     }
95 
OnRemoteDied(const wptr<IRemoteObject> & object)96     void InputMethodAbility::ServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
97     {
98         IMSA_HILOGI("input method service died");
99         if (listener != nullptr) {
100             listener->OnInputStop(ParaHandle::GetDefaultIme(Utils::GetUserId()));
101         }
102     }
103 
SetCoreAndAgent()104     void InputMethodAbility::SetCoreAndAgent()
105     {
106         IMSA_HILOGI("InputMethodAbility::SetCoreAndAgent");
107         mImms = GetImsaProxy();
108         if (mImms == nullptr) {
109             IMSA_HILOGI("InputMethodAbility::SetCoreAndAgent() mImms is nullptr");
110             return;
111         }
112         sptr<InputMethodCoreStub> stub = new InputMethodCoreStub(0);
113         stub->SetMessageHandler(msgHandler);
114         sptr<IInputMethodCore> stub2 = stub;
115 
116         sptr<InputMethodAgentStub> inputMethodAgentStub(new InputMethodAgentStub());
117         inputMethodAgentStub->SetMessageHandler(msgHandler);
118         sptr<IInputMethodAgent> inputMethodAgent = sptr(new InputMethodAgentProxy(inputMethodAgentStub));
119 
120         MessageParcel data;
121         if (!(data.WriteInterfaceToken(mImms->GetDescriptor())
122             && data.WriteRemoteObject(stub2->AsObject())
123             && data.WriteRemoteObject(inputMethodAgent->AsObject()))) {
124             return;
125         }
126         mImms->SetCoreAndAgent(data);
127     }
128 
Initialize()129     void InputMethodAbility::Initialize()
130     {
131         IMSA_HILOGI("InputMethodAbility::Initialize");
132         msgHandler = new MessageHandler();
133         workThreadHandler = std::thread([this] {
134             WorkThread();
135         });
136 
137         SetCoreAndAgent();
138     }
139 
setImeListener(sptr<JsInputMethodEngineListener> & imeListener)140     void InputMethodAbility::setImeListener(sptr<JsInputMethodEngineListener> &imeListener)
141     {
142         IMSA_HILOGI("InputMethodAbility::setImeListener");
143         if (imeListener_ == nullptr) {
144             imeListener_ = imeListener;
145         }
146         if (deathRecipientPtr_ != nullptr && deathRecipientPtr_->listener == nullptr) {
147             deathRecipientPtr_->listener = imeListener;
148         }
149     }
150 
setKdListener(sptr<JsKeyboardDelegateListener> & kdListener)151     void InputMethodAbility::setKdListener(sptr<JsKeyboardDelegateListener> &kdListener)
152     {
153         IMSA_HILOGI("InputMethodAbility::setKdListener");
154         if (kdListener_ == nullptr) {
155             kdListener_ = kdListener;
156         }
157     }
158 
WorkThread()159     void InputMethodAbility::WorkThread()
160     {
161         while (!stop_) {
162             Message *msg = msgHandler->GetMessage();
163             switch (msg->msgId_) {
164                 case MSG_ID_INITIALIZE_INPUT: {
165                     OnInitialInput(msg);
166                     break;
167                 }
168                 case MSG_ID_INIT_INPUT_CONTROL_CHANNEL: {
169                     OnInitInputControlChannel(msg);
170                     break;
171                 }
172                 case MSG_ID_SET_CLIENT_STATE: {
173                     MessageParcel *data = msg->msgContent_;
174                     isBindClient = data->ReadBool();
175                     break;
176                 }
177                 case MSG_ID_START_INPUT: {
178                     OnStartInput(msg);
179                     break;
180                 }
181                 case MSG_ID_STOP_INPUT: {
182                     OnStopInput(msg);
183                     break;
184                 }
185                 case MSG_ID_SHOW_KEYBOARD: {
186                     OnShowKeyboard(msg);
187                     break;
188                 }
189                 case MSG_ID_HIDE_KEYBOARD: {
190                     OnHideKeyboard(msg);
191                     break;
192                 }
193                 case MSG_ID_ON_CURSOR_UPDATE: {
194                     OnCursorUpdate(msg);
195                     break;
196                 }
197                 case MSG_ID_ON_SELECTION_CHANGE: {
198                     OnSelectionChange(msg);
199                     break;
200                 }
201                 case MSG_ID_STOP_INPUT_SERVICE:{
202                     MessageParcel *data = msg->msgContent_;
203                     std::string imeId = Str16ToStr8(data->ReadString16());
204                     if (imeListener_ != nullptr) {
205                         imeListener_->OnInputStop(imeId);
206                     }
207                     break;
208                 }
209                 default: {
210                     break;
211                 }
212             }
213             delete msg;
214             msg = nullptr;
215         }
216     }
217 
OnInitialInput(Message * msg)218     void InputMethodAbility::OnInitialInput(Message *msg)
219     {
220         IMSA_HILOGI("InputMethodAbility::OnInitialInput");
221         MessageParcel *data = msg->msgContent_;
222         displyId = data->ReadInt32();
223         sptr<IRemoteObject> channelObject = data->ReadRemoteObject();
224         if (channelObject == nullptr) {
225             IMSA_HILOGI("InputMethodAbility::OnInitialInput channelObject is nullptr");
226             return;
227         }
228         SetInputControlChannel(channelObject);
229     }
230 
OnInitInputControlChannel(Message * msg)231     void InputMethodAbility::OnInitInputControlChannel(Message *msg)
232     {
233         IMSA_HILOGI("InputMethodAbility::OnInitInputControlChannel");
234         MessageParcel *data = msg->msgContent_;
235         sptr<IRemoteObject> channelObject = data->ReadRemoteObject();
236         if (channelObject == nullptr) {
237             IMSA_HILOGI("InputMethodAbility::OnInitInputControlChannel channelObject is nullptr");
238             return;
239         }
240         SetInputControlChannel(channelObject);
241     }
242 
OnStartInput(Message * msg)243     void InputMethodAbility::OnStartInput(Message *msg)
244     {
245         IMSA_HILOGI("InputMethodAbility::OnStartInput");
246         MessageParcel *data = msg->msgContent_;
247         sptr<IRemoteObject> channelObject = data->ReadRemoteObject();
248         if (channelObject == nullptr) {
249             IMSA_HILOGI("InputMethodAbility::OnStartInput channelObject is nullptr");
250             return;
251         }
252         SetInputDataChannel(channelObject);
253         editorAttribute = data->ReadParcelable<InputAttribute>();
254         if (!editorAttribute) {
255             IMSA_HILOGI("InputMethodAbility::OnStartInput editorAttribute is nullptr");
256         }
257         mSupportPhysicalKbd = data->ReadBool();
258     }
259 
OnShowKeyboard(Message * msg)260     void InputMethodAbility::OnShowKeyboard(Message *msg)
261     {
262         IMSA_HILOGI("InputMethodAbility::OnShowKeyboard");
263         MessageParcel *data = msg->msgContent_;
264         sptr<IRemoteObject> channelObject = data->ReadRemoteObject();
265         if (channelObject == nullptr) {
266             IMSA_HILOGI("InputMethodAbility::OnShowKeyboard channelObject is nullptr");
267             return;
268         }
269         SetInputDataChannel(channelObject);
270         ShowInputWindow();
271     }
272 
OnHideKeyboard(Message * msg)273     void InputMethodAbility::OnHideKeyboard(Message *msg)
274     {
275         IMSA_HILOGI("InputMethodAbility::OnHideKeyboard");
276         DissmissInputWindow();
277     }
278 
OnStopInput(Message * msg)279     void InputMethodAbility::OnStopInput(Message *msg)
280     {
281         IMSA_HILOGI("InputMethodAbility::OnStopInput");
282         if (writeInputChannel != nullptr) {
283             delete writeInputChannel;
284             writeInputChannel = nullptr;
285         }
286     }
287 
DispatchKeyEvent(int32_t keyCode,int32_t keyStatus)288     bool InputMethodAbility::DispatchKeyEvent(int32_t keyCode, int32_t keyStatus)
289     {
290         IMSA_HILOGI("InputMethodAbility::DispatchKeyEvent: key = %{public}d, status = %{public}d", keyCode, keyStatus);
291         if (!isBindClient) {
292             IMSA_HILOGI("InputMethodAbility::DispatchKeyEvent abort. no client");
293             return false;
294         }
295         if (kdListener_ == nullptr) {
296             IMSA_HILOGI("InputMethodAbility::DispatchKeyEvent kdListener_ is nullptr");
297             return false;
298         }
299         return kdListener_->OnKeyEvent(keyCode, keyStatus);
300     }
301 
SetCallingWindow(uint32_t windowId)302     void InputMethodAbility::SetCallingWindow(uint32_t windowId)
303     {
304         IMSA_HILOGI("InputMethodAbility::SetCallingWindow");
305 
306         if (!imeListener_) {
307             IMSA_HILOGI("InputMethodAbility::SetCallingWindow imeListener_ is nullptr");
308             return;
309         }
310         imeListener_->OnSetCallingWindow(windowId);
311         return;
312     }
313 
314 
OnCursorUpdate(Message * msg)315     void InputMethodAbility::OnCursorUpdate(Message *msg)
316     {
317         IMSA_HILOGI("InputMethodAbility::OnCursorUpdate");
318         MessageParcel *data = msg->msgContent_;
319         int32_t positionX = data->ReadInt32();
320         int32_t positionY = data->ReadInt32();
321         int32_t height = data->ReadInt32();
322         if (kdListener_ == nullptr) {
323             IMSA_HILOGI("InputMethodAbility::OnCursorUpdate kdListener_ is nullptr");
324             return;
325         }
326         kdListener_->OnCursorUpdate(positionX, positionY, height);
327     }
328 
OnSelectionChange(Message * msg)329     void InputMethodAbility::OnSelectionChange(Message *msg)
330     {
331         IMSA_HILOGI("InputMethodAbility::OnSelectionChange");
332         MessageParcel *data = msg->msgContent_;
333         std::string text = Str16ToStr8(data->ReadString16());
334         int32_t oldBegin = data->ReadInt32();
335         int32_t oldEnd = data->ReadInt32();
336         int32_t newBegin = data->ReadInt32();
337         int32_t newEnd = data->ReadInt32();
338 
339         if (kdListener_ == nullptr) {
340             IMSA_HILOGI("InputMethodAbility::OnSelectionChange kdListener_ is nullptr");
341             return;
342         }
343         kdListener_->OnTextChange(text);
344 
345         kdListener_->OnSelectionChange(oldBegin, oldEnd, newBegin, newEnd);
346     }
347 
ShowInputWindow()348     void InputMethodAbility::ShowInputWindow()
349     {
350         IMSA_HILOGI("InputMethodAbility::ShowInputWindow");
351         if (imeListener_ == nullptr) {
352             IMSA_HILOGI("InputMethodAbility::ShowInputWindow imeListener_ is nullptr");
353             return;
354         }
355         imeListener_->OnInputStart();
356         imeListener_->OnKeyboardStatus(true);
357         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
358         if (channel == nullptr) {
359             IMSA_HILOGI("InputMethodAbility::ShowInputWindow channel is nullptr");
360             return;
361         }
362         channel->SendKeyboardStatus(KEYBOARD_SHOW);
363     }
364 
DissmissInputWindow()365     void InputMethodAbility::DissmissInputWindow()
366     {
367         IMSA_HILOGI("InputMethodAbility::DissmissInputWindow");
368         if (imeListener_ == nullptr) {
369             IMSA_HILOGI("InputMethodAbility::DissmissInputWindow imeListener_ is nullptr");
370             return;
371         }
372         imeListener_->OnKeyboardStatus(false);
373         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
374         if (channel == nullptr) {
375             IMSA_HILOGI("InputMethodAbility::DismissInputWindow channel is nullptr");
376             return;
377         }
378         channel->SendKeyboardStatus(KEYBOARD_HIDE);
379     }
380 
InsertText(const std::string text)381     bool InputMethodAbility::InsertText(const std::string text)
382     {
383         IMSA_HILOGI("InputMethodAbility::InsertText");
384         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
385         if (channel == nullptr) {
386             IMSA_HILOGI("InputMethodAbility::InsertText channel is nullptr");
387             return false;
388         }
389 
390         return channel->InsertText(Utils::to_utf16(text));
391     }
392 
DeleteForward(int32_t length)393     void InputMethodAbility::DeleteForward(int32_t length)
394     {
395         IMSA_HILOGI("InputMethodAbility::DeleteForward");
396         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
397         if (channel == nullptr) {
398             IMSA_HILOGI("InputMethodAbility::DeleteForward channel is nullptr");
399             return;
400         }
401         channel->DeleteForward(length);
402     }
403 
DeleteBackward(int32_t length)404     void InputMethodAbility::DeleteBackward(int32_t length)
405     {
406         IMSA_HILOGI("InputMethodAbility::DeleteBackward");
407         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
408         if (channel == nullptr) {
409             IMSA_HILOGI("InputMethodAbility::DeleteBackward channel is nullptr");
410             return;
411         }
412         channel->DeleteBackward(length);
413     }
414 
SendFunctionKey(int32_t funcKey)415     void InputMethodAbility::SendFunctionKey(int32_t funcKey)
416     {
417         IMSA_HILOGI("InputMethodAbility::SendFunctionKey");
418         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
419         if (channel == nullptr) {
420             IMSA_HILOGI("InputMethodAbility::SendFunctionKey channel is nullptr");
421             return;
422         }
423         channel->SendFunctionKey(funcKey);
424     }
425 
HideKeyboardSelf()426     void InputMethodAbility::HideKeyboardSelf()
427     {
428         IMSA_HILOGI("InputMethodAbility::HideKeyboardSelf");
429         std::shared_ptr<InputControlChannelProxy> channel = GetInputControlChannel();
430         if (channel == nullptr) {
431             IMSA_HILOGI("InputMethodAbility::HideKeyboardSelf channel is nullptr");
432             return;
433         }
434         channel->hideKeyboardSelf(1);
435     }
436 
GetTextBeforeCursor(int32_t number)437     std::u16string InputMethodAbility::GetTextBeforeCursor(int32_t number)
438     {
439         IMSA_HILOGI("InputMethodAbility::GetTextBeforeCursor");
440         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
441         if (channel == nullptr) {
442             IMSA_HILOGI("InputMethodAbility::GetTextBeforeCursor channel is nullptr");
443             return u"";
444         }
445         return channel->GetTextBeforeCursor(number);
446     }
447 
GetTextAfterCursor(int32_t number)448     std::u16string InputMethodAbility::GetTextAfterCursor(int32_t number)
449     {
450         IMSA_HILOGI("InputMethodAbility::GetTextAfterCursor");
451         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
452         if (channel == nullptr) {
453             IMSA_HILOGI("InputMethodAbility::GetTextAfterCursor channel is nullptr");
454             return u"";
455         }
456         return channel->GetTextAfterCursor(number);
457     }
458 
MoveCursor(int32_t keyCode)459     void InputMethodAbility::MoveCursor(int32_t keyCode)
460     {
461         IMSA_HILOGI("InputMethodAbility::MoveCursor");
462         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
463         if (channel == nullptr) {
464             IMSA_HILOGI("InputMethodAbility::MoveCursor channel is nullptr");
465             return;
466         }
467 
468         channel->MoveCursor(keyCode);
469     }
470 
GetEnterKeyType()471     int32_t InputMethodAbility::GetEnterKeyType()
472     {
473         IMSA_HILOGI("InputMethodAbility::GetEnterKeyType");
474         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
475         if (channel == nullptr) {
476             IMSA_HILOGI("InputMethodAbility::GetEnterKeyType channel is nullptr");
477             return -1;
478         }
479         return channel->GetEnterKeyType();
480     }
481 
GetInputPattern()482     int32_t InputMethodAbility::GetInputPattern()
483     {
484         IMSA_HILOGI("InputMethodAbility::GetInputPattern");
485         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
486         if (channel == nullptr) {
487             IMSA_HILOGI("InputMethodAbility::GetInputPattern channel is nullptr");
488             return -1;
489         }
490         return channel->GetInputPattern();
491     }
492 
StopInput()493     void InputMethodAbility::StopInput()
494     {
495         IMSA_HILOGI("InputMethodAbility::StopInput");
496         std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel();
497         if (channel == nullptr) {
498             IMSA_HILOGI("InputMethodAbility::StopInput channel is nullptr");
499             return;
500         }
501         channel->StopInput();
502     }
503 
SetInputDataChannel(sptr<IRemoteObject> & object)504     void InputMethodAbility::SetInputDataChannel(sptr<IRemoteObject> &object)
505     {
506         IMSA_HILOGI("run in SetInputDataChannel");
507         std::lock_guard<std::mutex> lock(dataChannelLock_);
508         std::shared_ptr<InputDataChannelProxy> channelProxy = std::make_shared<InputDataChannelProxy>(object);
509         if (channelProxy == nullptr) {
510             IMSA_HILOGI("InputMethodAbility::SetInputDataChannel inputDataChannel is nullptr");
511             return;
512         }
513         dataChannel_ = channelProxy;
514     }
515 
GetInputDataChannel()516     std::shared_ptr<InputDataChannelProxy> InputMethodAbility::GetInputDataChannel()
517     {
518         std::lock_guard<std::mutex> lock(dataChannelLock_);
519         return dataChannel_;
520     }
521 
SetInputControlChannel(sptr<IRemoteObject> & object)522     void InputMethodAbility::SetInputControlChannel(sptr<IRemoteObject> &object)
523     {
524         IMSA_HILOGI("run in SetInputControlChannel");
525         std::lock_guard<std::mutex> lock(controlChannelLock_);
526         std::shared_ptr<InputControlChannelProxy> channelProxy = std::make_shared<InputControlChannelProxy>(object);
527         if (channelProxy == nullptr) {
528             IMSA_HILOGI("InputMethodAbility::SetInputControlChannel inputDataChannel is nullptr");
529             return;
530         }
531         controlChannel_ = channelProxy;
532 	}
533 
GetInputControlChannel()534     std::shared_ptr<InputControlChannelProxy> InputMethodAbility::GetInputControlChannel()
535     {
536         std::lock_guard<std::mutex> lock(controlChannelLock_);
537         return controlChannel_;
538     }
539 }
540 }