• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2023 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 <unistd.h>
19 
20 #include "global.h"
21 #include "input_method_agent_proxy.h"
22 #include "input_method_agent_stub.h"
23 #include "input_method_core_proxy.h"
24 #include "input_method_core_stub.h"
25 #include "input_method_utils.h"
26 #include "inputmethod_sysevent.h"
27 #include "iservice_registry.h"
28 #include "itypes_util.h"
29 #include "message_parcel.h"
30 #include "string_ex.h"
31 #include "sys/prctl.h"
32 #include "system_ability_definition.h"
33 
34 namespace OHOS {
35 namespace MiscServices {
36 class MessageHandler;
37 using namespace MessageID;
38 sptr<InputMethodAbility> InputMethodAbility::instance_;
39 std::mutex InputMethodAbility::instanceLock_;
40 constexpr double INVALID_CURSOR_VALUE = -1.0;
41 constexpr int32_t INVALID_SELECTION_VALUE = -1;
InputMethodAbility()42 InputMethodAbility::InputMethodAbility() : msgHandler(nullptr), stop_(false) {}
43 
~InputMethodAbility()44 InputMethodAbility::~InputMethodAbility()
45 {
46     IMSA_HILOGI("InputMethodAbility::~InputMethodAbility");
47     QuitWorkThread();
48     if (msgHandler != nullptr) {
49         delete msgHandler;
50         msgHandler = nullptr;
51     }
52 }
53 
GetInstance()54 sptr<InputMethodAbility> InputMethodAbility::GetInstance()
55 {
56     if (instance_ == nullptr) {
57         std::lock_guard<std::mutex> autoLock(instanceLock_);
58         if (instance_ == nullptr) {
59             IMSA_HILOGI("InputMethodAbility::GetInstance need new IMA");
60             instance_ = new (std::nothrow) InputMethodAbility();
61             if (instance_ == nullptr) {
62                 IMSA_HILOGI("instance is nullptr.");
63                 return instance_;
64             }
65             instance_->Initialize();
66         }
67     }
68     return instance_;
69 }
70 
GetImsaProxy()71 sptr<InputMethodSystemAbilityProxy> InputMethodAbility::GetImsaProxy()
72 {
73     IMSA_HILOGI("InputMethodAbility::GetImsaProxy");
74     sptr<ISystemAbilityManager> systemAbilityManager =
75         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
76     if (systemAbilityManager == nullptr) {
77         IMSA_HILOGI("InputMethodAbility::GetImsaProxy systemAbilityManager is nullptr");
78         return nullptr;
79     }
80 
81     auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, "");
82     if (systemAbility == nullptr) {
83         IMSA_HILOGI("InputMethodAbility::GetImsaProxy systemAbility is nullptr");
84         return nullptr;
85     }
86     if (deathRecipientPtr_ == nullptr) {
87         deathRecipientPtr_ = new (std::nothrow) ServiceDeathRecipient();
88         if (deathRecipientPtr_ == nullptr) {
89             IMSA_HILOGE("new ServiceDeathRecipient failed");
90             return nullptr;
91         }
92     }
93     if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipientPtr_))) {
94         IMSA_HILOGE("failed to add death recipient.");
95     }
96 
97     sptr<InputMethodSystemAbilityProxy> iface = new InputMethodSystemAbilityProxy(systemAbility);
98     return iface;
99 }
100 
SetCoreAndAgent()101 int32_t InputMethodAbility::SetCoreAndAgent()
102 {
103     IMSA_HILOGD("InputMethodAbility, run in");
104     if (isBound_.load()) {
105         IMSA_HILOGD("already bound");
106         return ErrorCode::NO_ERROR;
107     }
108     mImms = GetImsaProxy();
109     if (mImms == nullptr) {
110         IMSA_HILOGI("InputMethodAbility mImms is nullptr");
111         return ErrorCode::ERROR_NULL_POINTER;
112     }
113     sptr<InputMethodCoreStub> stub = new InputMethodCoreStub(0);
114     stub->SetMessageHandler(msgHandler);
115 
116     sptr<InputMethodAgentStub> inputMethodAgentStub(new InputMethodAgentStub());
117     inputMethodAgentStub->SetMessageHandler(msgHandler);
118     sptr<IInputMethodAgent> inputMethodAgent = sptr(new InputMethodAgentProxy(inputMethodAgentStub));
119     int32_t ret = mImms->SetCoreAndAgent(stub, inputMethodAgent);
120     if (ret != ErrorCode::NO_ERROR) {
121         IMSA_HILOGE("set failed, ret: %{public}d", ret);
122         return ret;
123     }
124     isBound_.store(true);
125     IMSA_HILOGD("set successfully");
126     return ErrorCode::NO_ERROR;
127 }
128 
Initialize()129 void InputMethodAbility::Initialize()
130 {
131     IMSA_HILOGI("InputMethodAbility::Initialize");
132     msgHandler = new MessageHandler();
133     workThreadHandler = std::thread([this] { WorkThread(); });
134 }
135 
SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)136 void InputMethodAbility::SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)
137 {
138     IMSA_HILOGI("InputMethodAbility.");
139     if (imeListener_ == nullptr) {
140         imeListener_ = std::move(imeListener);
141     }
142     if (deathRecipientPtr_ != nullptr && deathRecipientPtr_->listener == nullptr) {
143         deathRecipientPtr_->listener = imeListener_;
144     }
145 }
146 
OnImeReady()147 void InputMethodAbility::OnImeReady()
148 {
149     isImeReady_ = true;
150     if (!notifier_.isNotify) {
151         IMSA_HILOGI("InputMethodAbility::Ime Ready, don't need to notify");
152         return;
153     }
154     IMSA_HILOGI("InputMethodAbility::Ime Ready, notify InputStart");
155     TextTotalConfig textConfig{};
156     int32_t ret = GetTextConfig(textConfig);
157     IMSA_HILOGI("InputMethodAbility, get text config failed, ret is %{public}d", ret);
158     OnTextConfigChange(textConfig);
159     ShowInputWindow(notifier_.isShowKeyboard);
160 }
161 
SetKdListener(std::shared_ptr<KeyboardListener> kdListener)162 void InputMethodAbility::SetKdListener(std::shared_ptr<KeyboardListener> kdListener)
163 {
164     IMSA_HILOGI("InputMethodAbility.");
165     if (kdListener_ == nullptr) {
166         kdListener_ = kdListener;
167     }
168 }
169 
WorkThread()170 void InputMethodAbility::WorkThread()
171 {
172     prctl(PR_SET_NAME, "IMAWorkThread");
173     while (!stop_) {
174         Message *msg = msgHandler->GetMessage();
175         switch (msg->msgId_) {
176             case MSG_ID_INIT_INPUT_CONTROL_CHANNEL: {
177                 OnInitInputControlChannel(msg);
178                 break;
179             }
180             case MSG_ID_ON_CURSOR_UPDATE: {
181                 OnCursorUpdate(msg);
182                 break;
183             }
184             case MSG_ID_ON_SELECTION_CHANGE: {
185                 OnSelectionChange(msg);
186                 break;
187             }
188             case MSG_ID_ON_CONFIGURATION_CHANGE: {
189                 OnConfigurationChange(msg);
190                 break;
191             }
192             case MSG_ID_STOP_INPUT_SERVICE: {
193                 MessageParcel *data = msg->msgContent_;
194                 std::string imeId = Str16ToStr8(data->ReadString16());
195                 if (imeListener_ != nullptr) {
196                     imeListener_->OnInputStop(imeId);
197                 }
198                 isBound_.store(false);
199                 break;
200             }
201             case MSG_ID_SET_SUBTYPE: {
202                 OnSetSubtype(msg);
203                 break;
204             }
205             default: {
206                 IMSA_HILOGD("the message is %{public}d.", msg->msgId_);
207                 break;
208             }
209         }
210         delete msg;
211         msg = nullptr;
212     }
213 }
214 
OnInitInputControlChannel(Message * msg)215 void InputMethodAbility::OnInitInputControlChannel(Message *msg)
216 {
217     IMSA_HILOGI("InputMethodAbility::OnInitInputControlChannel");
218     MessageParcel *data = msg->msgContent_;
219     sptr<IRemoteObject> channelObject = data->ReadRemoteObject();
220     if (channelObject == nullptr) {
221         IMSA_HILOGI("InputMethodAbility::OnInitInputControlChannel channelObject is nullptr");
222         return;
223     }
224     if (deathRecipientPtr_ != nullptr) {
225         deathRecipientPtr_->currentIme_ = data->ReadString();
226     }
227     SetInputControlChannel(channelObject);
228 }
229 
ShowKeyboard(const sptr<IRemoteObject> & channelObject,bool isShowKeyboard,bool attachFlag)230 int32_t InputMethodAbility::ShowKeyboard(const sptr<IRemoteObject> &channelObject, bool isShowKeyboard, bool attachFlag)
231 {
232     IMSA_HILOGI("InputMethodAbility::ShowKeyboard");
233     if (channelObject == nullptr) {
234         IMSA_HILOGE("InputMethodAbility::ShowKeyboard channelObject is nullptr");
235         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
236     }
237     SetInputDataChannel(channelObject);
238     if (attachFlag) {
239         TextTotalConfig textConfig = {};
240         int32_t ret = GetTextConfig(textConfig);
241         if (ret != ErrorCode::NO_ERROR) {
242             IMSA_HILOGE("InputMethodAbility, get text config failed, ret is %{public}d", ret);
243             return ret;
244         }
245         OnTextConfigChange(textConfig);
246     }
247     return ShowInputWindow(isShowKeyboard);
248 }
249 
OnSetSubtype(Message * msg)250 void InputMethodAbility::OnSetSubtype(Message *msg)
251 {
252     IMSA_HILOGI("InputMethodAbility::OnSetSubtype");
253     auto data = msg->msgContent_;
254     SubProperty subProperty;
255     if (!ITypesUtil::Unmarshal(*data, subProperty)) {
256         IMSA_HILOGE("read message parcel failed");
257         return;
258     }
259     if (imeListener_ == nullptr) {
260         IMSA_HILOGI("InputMethodAbility::OnSetSubtype imeListener_ is nullptr");
261         return;
262     }
263     imeListener_->OnSetSubtype(subProperty);
264 }
265 
ClearDataChannel(const sptr<IRemoteObject> & channel)266 void InputMethodAbility::ClearDataChannel(const sptr<IRemoteObject> &channel)
267 {
268     IMSA_HILOGI("run in");
269     std::lock_guard<std::mutex> lock(dataChannelLock_);
270     if (dataChannelObject_ == nullptr || channel == nullptr) {
271         return;
272     }
273     if (dataChannelObject_.GetRefPtr() == channel.GetRefPtr()) {
274         IMSA_HILOGI("clear data channel");
275         dataChannelObject_ = nullptr;
276         dataChannelProxy_ = nullptr;
277     }
278 }
279 
DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)280 bool InputMethodAbility::DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> &keyEvent)
281 {
282     IMSA_HILOGD("InputMethodAbility, run in");
283     if (keyEvent == nullptr) {
284         IMSA_HILOGE("keyEvent is nullptr");
285         return false;
286     }
287     if (kdListener_ == nullptr) {
288         IMSA_HILOGI("kdListener_ is nullptr");
289         return false;
290     }
291     bool isFullKeyEventConsumed = kdListener_->OnKeyEvent(keyEvent);
292     bool isKeyEventConsumed = kdListener_->OnKeyEvent(keyEvent->GetKeyCode(), keyEvent->GetKeyAction());
293     return isFullKeyEventConsumed || isKeyEventConsumed;
294 }
295 
SetCallingWindow(uint32_t windowId)296 void InputMethodAbility::SetCallingWindow(uint32_t windowId)
297 {
298     IMSA_HILOGI("InputMethodAbility::SetCallingWindow");
299 
300     if (imeListener_ == nullptr) {
301         IMSA_HILOGI("InputMethodAbility::SetCallingWindow imeListener_ is nullptr");
302         return;
303     }
304     panels_.ForEach([windowId](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
305         panel->SetCallingWindow(windowId);
306         return false;
307     });
308     imeListener_->OnSetCallingWindow(windowId);
309 }
310 
OnCursorUpdate(Message * msg)311 void InputMethodAbility::OnCursorUpdate(Message *msg)
312 {
313     IMSA_HILOGD("InputMethodAbility::OnCursorUpdate");
314     MessageParcel *data = msg->msgContent_;
315     int32_t positionX = data->ReadInt32();
316     int32_t positionY = data->ReadInt32();
317     int32_t height = data->ReadInt32();
318     if (kdListener_ == nullptr) {
319         IMSA_HILOGE("InputMethodAbility::OnCursorUpdate kdListener_ is nullptr");
320         return;
321     }
322     kdListener_->OnCursorUpdate(positionX, positionY, height);
323 }
324 
OnSelectionChange(Message * msg)325 void InputMethodAbility::OnSelectionChange(Message *msg)
326 {
327     IMSA_HILOGD("InputMethodAbility::OnSelectionChange");
328     MessageParcel *data = msg->msgContent_;
329     std::string text = Str16ToStr8(data->ReadString16());
330     int32_t oldBegin = data->ReadInt32();
331     int32_t oldEnd = data->ReadInt32();
332     int32_t newBegin = data->ReadInt32();
333     int32_t newEnd = data->ReadInt32();
334 
335     if (kdListener_ == nullptr) {
336         IMSA_HILOGE("InputMethodAbility::OnSelectionChange kdListener_ is nullptr");
337         return;
338     }
339     kdListener_->OnTextChange(text);
340 
341     kdListener_->OnSelectionChange(oldBegin, oldEnd, newBegin, newEnd);
342 }
343 
OnConfigurationChange(Message * msg)344 void InputMethodAbility::OnConfigurationChange(Message *msg)
345 {
346     IMSA_HILOGD("InputMethodAbility in.");
347     if (kdListener_ == nullptr) {
348         IMSA_HILOGE("InputMethodAbility in, kdListener_ is nullptr");
349         return;
350     }
351     MessageParcel *data = msg->msgContent_;
352     InputAttribute attribute;
353     attribute.enterKeyType = data->ReadInt32();
354     attribute.inputPattern = data->ReadInt32();
355     kdListener_->OnEditorAttributeChange(attribute);
356 }
357 
ShowInputWindow(bool isShowKeyboard)358 int32_t InputMethodAbility::ShowInputWindow(bool isShowKeyboard)
359 {
360     IMSA_HILOGI("InputMethodAbility::ShowInputWindow");
361     if (!isImeReady_) {
362         IMSA_HILOGE("InputMethodAbility::ime is unready, store notifier_");
363         notifier_.isNotify = true;
364         notifier_.isShowKeyboard = isShowKeyboard;
365         return ErrorCode::ERROR_IME_NOT_READY;
366     }
367     if (imeListener_ == nullptr) {
368         IMSA_HILOGE("InputMethodAbility, imeListener is nullptr");
369         return ErrorCode::ERROR_IME;
370     }
371     imeListener_->OnInputStart();
372     if (!isShowKeyboard) {
373         IMSA_HILOGI("InputMethodAbility::ShowInputWindow will not show keyboard");
374         return ErrorCode::NO_ERROR;
375     }
376     imeListener_->OnKeyboardStatus(true);
377     auto channel = GetInputDataChannelProxy();
378     if (channel == nullptr) {
379         IMSA_HILOGE("InputMethodAbility::ShowInputWindow channel is nullptr");
380         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
381     }
382     channel->SendKeyboardStatus(KEYBOARD_SHOW);
383     auto result = panels_.Find(SOFT_KEYBOARD);
384     if (result.first) {
385         IMSA_HILOGI("find SOFT_KEYBOARD panel.");
386         auto panel = result.second;
387         if (panel->GetPanelFlag() == PanelFlag::FLG_CANDIDATE_COLUMN) {
388             IMSA_HILOGD("panel flag is candidate, not need to show.");
389             return ErrorCode::NO_ERROR;
390         }
391         auto ret = panel->ShowPanel();
392         if (ret != ErrorCode::NO_ERROR) {
393             IMSA_HILOGE("Show panel failed, ret = %{public}d.", ret);
394         }
395         return ret;
396     }
397     return ErrorCode::NO_ERROR;
398 }
399 
OnTextConfigChange(const TextTotalConfig & textConfig)400 void InputMethodAbility::OnTextConfigChange(const TextTotalConfig &textConfig)
401 {
402     IMSA_HILOGI("InputMethodAbility run in.");
403     if (kdListener_ == nullptr) {
404         IMSA_HILOGE("kdListener_ is nullptr.");
405     } else {
406         IMSA_HILOGI("send on('editorAttributeChanged') callback.");
407         kdListener_->OnEditorAttributeChange(textConfig.inputAttribute);
408         if (textConfig.cursorInfo.left != INVALID_CURSOR_VALUE) {
409             IMSA_HILOGI("send on('cursorUpdate') callback.");
410             kdListener_->OnCursorUpdate(
411                 textConfig.cursorInfo.left, textConfig.cursorInfo.top, textConfig.cursorInfo.height);
412         }
413         if (textConfig.textSelection.newBegin != INVALID_SELECTION_VALUE) {
414             IMSA_HILOGI("send on('selectionChange') callback.");
415             kdListener_->OnSelectionChange(textConfig.textSelection.oldBegin, textConfig.textSelection.oldEnd,
416                                            textConfig.textSelection.newBegin, textConfig.textSelection.newEnd);
417         }
418     }
419     if (textConfig.windowId == INVALID_WINDOW_ID) {
420         return;
421     }
422     panels_.ForEach([&textConfig](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
423         panel->SetCallingWindow(textConfig.windowId);
424         return false;
425     });
426     if (imeListener_ == nullptr) {
427         IMSA_HILOGE("imeListener_ is nullptr, do not need to send callback of setCallingWindow.");
428         return;
429     }
430     imeListener_->OnSetCallingWindow(textConfig.windowId);
431     IMSA_HILOGD("setCallingWindow end.");
432 }
433 
HideKeyboard()434 int32_t InputMethodAbility::HideKeyboard()
435 {
436     IMSA_HILOGI("InputMethodAbility::HideKeyboard");
437     if (imeListener_ == nullptr) {
438         IMSA_HILOGE("InputMethodAbility::HideKeyboard imeListener_ is nullptr");
439         return ErrorCode::ERROR_IME;
440     }
441     imeListener_->OnKeyboardStatus(false);
442     auto channel = GetInputDataChannelProxy();
443     if (channel == nullptr) {
444         IMSA_HILOGE("InputMethodAbility::HideKeyboard channel is nullptr");
445         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
446     }
447     channel->SendKeyboardStatus(KEYBOARD_HIDE);
448     auto result = panels_.Find(SOFT_KEYBOARD);
449     if (!result.first) {
450         IMSA_HILOGE("Not find SOFT_KEYBOARD panel.");
451         return ErrorCode::NO_ERROR;
452     }
453     auto panel = result.second;
454     if (panel->GetPanelFlag() == PanelFlag::FLG_CANDIDATE_COLUMN) {
455         IMSA_HILOGD("panel flag is candidate, not need to hide.");
456         return ErrorCode::NO_ERROR;
457     }
458     auto ret = panel->HidePanel();
459     IMSA_HILOGD("Hide panel, ret = %{public}d.", ret);
460     return ret;
461 }
462 
InsertText(const std::string text)463 int32_t InputMethodAbility::InsertText(const std::string text)
464 {
465     IMSA_HILOGD("InputMethodAbility, in");
466     auto channel = GetInputDataChannelProxy();
467     if (channel == nullptr) {
468         IMSA_HILOGI("InputMethodAbility::InsertText channel is nullptr");
469         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
470     }
471     return channel->InsertText(Str8ToStr16(text));
472 }
473 
DeleteForward(int32_t length)474 int32_t InputMethodAbility::DeleteForward(int32_t length)
475 {
476     IMSA_HILOGD("InputMethodAbility, length = %{public}d", length);
477     auto channel = GetInputDataChannelProxy();
478     if (channel == nullptr) {
479         IMSA_HILOGE("InputMethodAbility, channel is nullptr");
480         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
481     }
482     return channel->DeleteForward(length);
483 }
484 
DeleteBackward(int32_t length)485 int32_t InputMethodAbility::DeleteBackward(int32_t length)
486 {
487     IMSA_HILOGD("InputMethodAbility, length = %{public}d", length);
488     auto channel = GetInputDataChannelProxy();
489     if (channel == nullptr) {
490         IMSA_HILOGE("InputMethodAbility, channel is nullptr");
491         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
492     }
493     return channel->DeleteBackward(length);
494 }
495 
SendFunctionKey(int32_t funcKey)496 int32_t InputMethodAbility::SendFunctionKey(int32_t funcKey)
497 {
498     auto channel = GetInputDataChannelProxy();
499     if (channel == nullptr) {
500         IMSA_HILOGE("InputMethodAbility::SendFunctionKey channel is nullptr");
501         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
502     }
503     return channel->SendFunctionKey(funcKey);
504 }
505 
HideKeyboardSelf()506 int32_t InputMethodAbility::HideKeyboardSelf()
507 {
508     auto controlChannel = GetInputControlChannel();
509     if (controlChannel == nullptr) {
510         IMSA_HILOGE("InputMethodAbility::HideKeyboardSelf controlChannel is nullptr");
511         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
512     }
513     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_SELF);
514     return controlChannel->HideKeyboardSelf();
515 }
516 
SendExtendAction(int32_t action)517 int32_t InputMethodAbility::SendExtendAction(int32_t action)
518 {
519     auto channel = GetInputDataChannelProxy();
520     if (channel == nullptr) {
521         IMSA_HILOGI("InputMethodAbility::SendExtendAction channel is nullptr");
522         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
523     }
524     return channel->HandleExtendAction(action);
525 }
526 
GetTextBeforeCursor(int32_t number,std::u16string & text)527 int32_t InputMethodAbility::GetTextBeforeCursor(int32_t number, std::u16string &text)
528 {
529     auto channel = GetInputDataChannelProxy();
530     if (channel == nullptr) {
531         IMSA_HILOGE("InputMethodAbility::GetTextBeforeCursor channel is nullptr");
532         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
533     }
534     return channel->GetTextBeforeCursor(number, text);
535 }
536 
GetTextAfterCursor(int32_t number,std::u16string & text)537 int32_t InputMethodAbility::GetTextAfterCursor(int32_t number, std::u16string &text)
538 {
539     auto channel = GetInputDataChannelProxy();
540     if (channel == nullptr) {
541         IMSA_HILOGE("InputMethodAbility::GetTextAfterCursor channel is nullptr");
542         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
543     }
544     return channel->GetTextAfterCursor(number, text);
545 }
546 
MoveCursor(int32_t keyCode)547 int32_t InputMethodAbility::MoveCursor(int32_t keyCode)
548 {
549     IMSA_HILOGD("InputMethodAbility, keyCode = %{public}d", keyCode);
550     auto channel = GetInputDataChannelProxy();
551     if (channel == nullptr) {
552         IMSA_HILOGE("InputMethodAbility::MoveCursor channel is nullptr");
553         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
554     }
555 
556     return channel->MoveCursor(keyCode);
557 }
558 
SelectByRange(int32_t start,int32_t end)559 int32_t InputMethodAbility::SelectByRange(int32_t start, int32_t end)
560 {
561     IMSA_HILOGD("InputMethodAbility, start = %{public}d, end = %{public}d", start, end);
562     if (start < 0 || end < 0) {
563         IMSA_HILOGE("check parameter failed, start: %{public}d, end: %{public}d", start, end);
564         return ErrorCode::ERROR_BAD_PARAMETERS;
565     }
566     auto dataChannel = GetInputDataChannelProxy();
567     if (dataChannel == nullptr) {
568         IMSA_HILOGE("datachannel is nullptr");
569         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
570     }
571     return dataChannel->SelectByRange(start, end);
572 }
573 
SelectByMovement(int32_t direction)574 int32_t InputMethodAbility::SelectByMovement(int32_t direction)
575 {
576     IMSA_HILOGD("InputMethodAbility, direction = %{public}d", direction);
577     auto dataChannel = GetInputDataChannelProxy();
578     if (dataChannel == nullptr) {
579         IMSA_HILOGE("datachannel is nullptr");
580         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
581     }
582     return dataChannel->SelectByMovement(direction, 0);
583 }
584 
GetEnterKeyType(int32_t & keyType)585 int32_t InputMethodAbility::GetEnterKeyType(int32_t &keyType)
586 {
587     auto channel = GetInputDataChannelProxy();
588     if (channel == nullptr) {
589         IMSA_HILOGE("InputMethodAbility::GetEnterKeyType channel is nullptr");
590         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
591     }
592     return channel->GetEnterKeyType(keyType);
593 }
594 
GetInputPattern(int32_t & inputPattern)595 int32_t InputMethodAbility::GetInputPattern(int32_t &inputPattern)
596 {
597     auto channel = GetInputDataChannelProxy();
598     if (channel == nullptr) {
599         IMSA_HILOGE("InputMethodAbility::GetInputPattern channel is nullptr");
600         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
601     }
602     return channel->GetInputPattern(inputPattern);
603 }
604 
GetTextIndexAtCursor(int32_t & index)605 int32_t InputMethodAbility::GetTextIndexAtCursor(int32_t &index)
606 {
607     auto channel = GetInputDataChannelProxy();
608     if (channel == nullptr) {
609         IMSA_HILOGE("InputMethodAbility::channel is nullptr");
610         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
611     }
612     return channel->GetTextIndexAtCursor(index);
613 }
614 
GetTextConfig(TextTotalConfig & textConfig)615 int32_t InputMethodAbility::GetTextConfig(TextTotalConfig &textConfig)
616 {
617     IMSA_HILOGD("InputMethodAbility, run in.");
618     auto channel = GetInputDataChannelProxy();
619     if (channel == nullptr) {
620         IMSA_HILOGE("InputMethodAbility::channel is nullptr");
621         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
622     }
623     return channel->GetTextConfig(textConfig);
624 }
625 
SetInputDataChannel(const sptr<IRemoteObject> & object)626 void InputMethodAbility::SetInputDataChannel(const sptr<IRemoteObject> &object)
627 {
628     IMSA_HILOGD("run in SetInputDataChannel");
629     std::lock_guard<std::mutex> lock(dataChannelLock_);
630     auto channelProxy = std::make_shared<InputDataChannelProxy>(object);
631     if (channelProxy == nullptr) {
632         IMSA_HILOGE("failed to new data channel proxy");
633         return;
634     }
635     dataChannelObject_ = object;
636     dataChannelProxy_ = channelProxy;
637 }
638 
GetInputDataChannelProxy()639 std::shared_ptr<InputDataChannelProxy> InputMethodAbility::GetInputDataChannelProxy()
640 {
641     std::lock_guard<std::mutex> lock(dataChannelLock_);
642     return dataChannelProxy_;
643 }
644 
SetInputControlChannel(sptr<IRemoteObject> & object)645 void InputMethodAbility::SetInputControlChannel(sptr<IRemoteObject> &object)
646 {
647     IMSA_HILOGI("run in SetInputControlChannel");
648     std::lock_guard<std::mutex> lock(controlChannelLock_);
649     std::shared_ptr<InputControlChannelProxy> channelProxy = std::make_shared<InputControlChannelProxy>(object);
650     if (channelProxy == nullptr) {
651         IMSA_HILOGI("InputMethodAbility::SetInputControlChannel inputDataChannel is nullptr");
652         return;
653     }
654     controlChannel_ = channelProxy;
655 }
656 
GetInputControlChannel()657 std::shared_ptr<InputControlChannelProxy> InputMethodAbility::GetInputControlChannel()
658 {
659     std::lock_guard<std::mutex> lock(controlChannelLock_);
660     return controlChannel_;
661 }
662 
OnRemoteDied(const wptr<IRemoteObject> & object)663 void InputMethodAbility::ServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
664 {
665     IMSA_HILOGI("ServiceDeathRecipient::OnRemoteDied");
666     if (listener != nullptr) {
667         listener->OnInputStop(currentIme_);
668     }
669 }
670 
QuitWorkThread()671 void InputMethodAbility::QuitWorkThread()
672 {
673     stop_ = true;
674     Message *msg = new Message(MessageID::MSG_ID_QUIT_WORKER_THREAD, nullptr);
675     msgHandler->SendMessage(msg);
676     if (workThreadHandler.joinable()) {
677         workThreadHandler.join();
678     }
679 }
680 
CreatePanel(const std::shared_ptr<AbilityRuntime::Context> & context,const PanelInfo & panelInfo,std::shared_ptr<InputMethodPanel> & inputMethodPanel)681 int32_t InputMethodAbility::CreatePanel(const std::shared_ptr<AbilityRuntime::Context> &context,
682     const PanelInfo &panelInfo, std::shared_ptr<InputMethodPanel> &inputMethodPanel)
683 {
684     IMSA_HILOGI("InputMethodAbility::CreatePanel start.");
685     auto result = panels_.Find(panelInfo.panelType);
686     if (result.first) {
687         IMSA_HILOGE(" type of %{public}d panel already created, can not create another", panelInfo.panelType);
688         return ErrorCode::ERROR_OPERATE_PANEL;
689     }
690     inputMethodPanel = std::make_shared<InputMethodPanel>();
691     auto ret = inputMethodPanel->CreatePanel(context, panelInfo);
692     if (ret != ErrorCode::NO_ERROR) {
693         IMSA_HILOGE("CreatePanel failed, ret = %{public}d", ret);
694         return ret;
695     }
696     IMSA_HILOGI("InputMethodAbility::CreatePanel ret = 0, success.");
697     if (!panels_.Insert(panelInfo.panelType, inputMethodPanel)) {
698         IMSA_HILOGE("insert inputMethodPanel fail.");
699         return ErrorCode::ERROR_OPERATE_PANEL;
700     }
701     return ErrorCode::NO_ERROR;
702 }
703 
DestroyPanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel)704 int32_t InputMethodAbility::DestroyPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
705 {
706     IMSA_HILOGI("InputMethodAbility, in.");
707     if (inputMethodPanel == nullptr) {
708         return ErrorCode::ERROR_BAD_PARAMETERS;
709     }
710     PanelType panelType = inputMethodPanel->GetPanelType();
711     auto ret = inputMethodPanel->DestroyPanel();
712     if (ret == ErrorCode::NO_ERROR) {
713         panels_.Erase(panelType);
714     }
715     return ret;
716 }
717 } // namespace MiscServices
718 } // namespace OHOS
719