• 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 <utility>
21 
22 #include "global.h"
23 #include "input_method_agent_stub.h"
24 #include "input_method_core_stub.h"
25 #include "input_method_system_ability_proxy.h"
26 #include "input_method_utils.h"
27 #include "inputmethod_sysevent.h"
28 #include "inputmethod_trace.h"
29 #include "iservice_registry.h"
30 #include "itypes_util.h"
31 #include "message_parcel.h"
32 #include "string_ex.h"
33 #include "sys/prctl.h"
34 #include "system_ability_definition.h"
35 
36 namespace OHOS {
37 namespace MiscServices {
38 class MessageHandler;
39 using namespace MessageID;
40 sptr<InputMethodAbility> InputMethodAbility::instance_;
41 std::mutex InputMethodAbility::instanceLock_;
42 constexpr double INVALID_CURSOR_VALUE = -1.0;
43 constexpr int32_t INVALID_SELECTION_VALUE = -1;
44 constexpr uint32_t FIND_PANEL_RETRY_INTERVAL = 10;
45 constexpr uint32_t MAX_RETRY_TIMES = 100;
46 constexpr int32_t INVALID_SECURITY_MODE = -1;
InputMethodAbility()47 InputMethodAbility::InputMethodAbility() : msgHandler_(nullptr), stop_(false)
48 {
49 }
50 
~InputMethodAbility()51 InputMethodAbility::~InputMethodAbility()
52 {
53     IMSA_HILOGI("InputMethodAbility::~InputMethodAbility.");
54     QuitWorkThread();
55     if (msgHandler_ != nullptr) {
56         delete msgHandler_;
57         msgHandler_ = nullptr;
58     }
59 }
60 
GetInstance()61 sptr<InputMethodAbility> InputMethodAbility::GetInstance()
62 {
63     if (instance_ == nullptr) {
64         std::lock_guard<std::mutex> autoLock(instanceLock_);
65         if (instance_ == nullptr) {
66             IMSA_HILOGI("InputMethodAbility need new IMA.");
67             instance_ = new (std::nothrow) InputMethodAbility();
68             if (instance_ == nullptr) {
69                 IMSA_HILOGE("instance is nullptr!");
70                 return instance_;
71             }
72             instance_->Initialize();
73         }
74     }
75     return instance_;
76 }
77 
GetImsaProxy()78 sptr<IInputMethodSystemAbility> InputMethodAbility::GetImsaProxy()
79 {
80     std::lock_guard<std::mutex> lock(abilityLock_);
81     if (abilityManager_ != nullptr) {
82         return abilityManager_;
83     }
84     IMSA_HILOGI("InputMethodAbility get imsa proxy.");
85     sptr<ISystemAbilityManager> systemAbilityManager =
86         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
87     if (systemAbilityManager == nullptr) {
88         IMSA_HILOGE("systemAbilityManager is nullptr!");
89         return nullptr;
90     }
91     auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, "");
92     if (systemAbility == nullptr) {
93         IMSA_HILOGE("systemAbility is nullptr!");
94         return nullptr;
95     }
96     if (deathRecipient_ == nullptr) {
97         deathRecipient_ = new (std::nothrow) InputDeathRecipient();
98         if (deathRecipient_ == nullptr) {
99             IMSA_HILOGE("failed to new death recipient!");
100             return nullptr;
101         }
102     }
103     deathRecipient_->SetDeathRecipient([this](const wptr<IRemoteObject> &remote) { OnRemoteSaDied(remote); });
104     if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) {
105         IMSA_HILOGE("failed to add death recipient!");
106         return nullptr;
107     }
108     abilityManager_ = iface_cast<IInputMethodSystemAbility>(systemAbility);
109     return abilityManager_;
110 }
111 
SetCoreAndAgentAsync()112 void InputMethodAbility::SetCoreAndAgentAsync()
113 {
114     if (msgHandler_ == nullptr) {
115         IMSA_HILOGE("msgHandler_ is nullptr");
116         SetCoreAndAgent();
117         return;
118     }
119     Message *msg = new Message(MessageID::MSG_ID_SET_COREANDANGENT, nullptr);
120     msgHandler_->SendMessage(msg);
121 }
122 
SetCoreAndAgent()123 int32_t InputMethodAbility::SetCoreAndAgent()
124 {
125     IMSA_HILOGD("InputMethodAbility, start.");
126     if (isBound_.load()) {
127         IMSA_HILOGD("already bound.");
128         return ErrorCode::NO_ERROR;
129     }
130     auto proxy = GetImsaProxy();
131     if (proxy == nullptr) {
132         IMSA_HILOGE("imsa proxy is nullptr!");
133         return ErrorCode::ERROR_NULL_POINTER;
134     }
135     int32_t ret = proxy->SetCoreAndAgent(coreStub_, agentStub_->AsObject());
136     if (ret != ErrorCode::NO_ERROR) {
137         IMSA_HILOGE("set failed, ret: %{public}d!", ret);
138         return ret;
139     }
140     isBound_.store(true);
141     IMSA_HILOGD("set successfully.");
142     return ErrorCode::NO_ERROR;
143 }
144 
InitConnect()145 int32_t InputMethodAbility::InitConnect()
146 {
147     IMSA_HILOGD("InputMethodAbility, init connect.");
148     auto proxy = GetImsaProxy();
149     if (proxy == nullptr) {
150         IMSA_HILOGE("imsa proxy is nullptr!");
151         return ErrorCode::ERROR_NULL_POINTER;
152     }
153     int32_t ret = proxy->InitConnect();
154     if (ret != ErrorCode::NO_ERROR) {
155         IMSA_HILOGE("set failed, ret: %{public}d!", ret);
156         return ret;
157     }
158     return ErrorCode::NO_ERROR;
159 }
160 
UnRegisteredProxyIme(UnRegisteredType type)161 int32_t InputMethodAbility::UnRegisteredProxyIme(UnRegisteredType type)
162 {
163     isBound_.store(false);
164     auto proxy = GetImsaProxy();
165     if (proxy == nullptr) {
166         IMSA_HILOGE("imsa proxy is nullptr!");
167         return ErrorCode::ERROR_NULL_POINTER;
168     }
169     return proxy->UnRegisteredProxyIme(type, coreStub_);
170 }
171 
Initialize()172 void InputMethodAbility::Initialize()
173 {
174     IMSA_HILOGD("IMA init.");
175     sptr<InputMethodCoreStub> coreStub = new (std::nothrow) InputMethodCoreStub();
176     if (coreStub == nullptr) {
177         IMSA_HILOGE("failed to create core!");
178         return;
179     }
180     sptr<InputMethodAgentStub> agentStub = new (std::nothrow) InputMethodAgentStub();
181     if (agentStub == nullptr) {
182         IMSA_HILOGE("failed to create agent!");
183         return;
184     }
185     msgHandler_ = new (std::nothrow) MessageHandler();
186     if (msgHandler_ == nullptr) {
187         IMSA_HILOGE("failed to create message handler!");
188         return;
189     }
190     coreStub->SetMessageHandler(msgHandler_);
191     agentStub->SetMessageHandler(msgHandler_);
192     agentStub_ = agentStub;
193     coreStub_ = coreStub;
194     workThreadHandler = std::thread([this] { this->WorkThread(); });
195 }
196 
SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)197 void InputMethodAbility::SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)
198 {
199     IMSA_HILOGD("InputMethodAbility start.");
200     if (imeListener_ == nullptr) {
201         imeListener_ = std::move(imeListener);
202     }
203 }
204 
GetImeListener()205 std::shared_ptr<InputMethodEngineListener> InputMethodAbility::GetImeListener()
206 {
207     return imeListener_;
208 }
209 
SetKdListener(std::shared_ptr<KeyboardListener> kdListener)210 void InputMethodAbility::SetKdListener(std::shared_ptr<KeyboardListener> kdListener)
211 {
212     IMSA_HILOGD("InputMethodAbility start.");
213     if (kdListener_ == nullptr) {
214         kdListener_ = std::move(kdListener);
215     }
216 }
217 
WorkThread()218 void InputMethodAbility::WorkThread()
219 {
220     prctl(PR_SET_NAME, "OS_IMAWorkThread start.");
221     while (!stop_) {
222         Message *msg = msgHandler_->GetMessage();
223         switch (msg->msgId_) {
224             case MSG_ID_INIT_INPUT_CONTROL_CHANNEL: {
225                 OnInitInputControlChannel(msg);
226                 break;
227             }
228             case MSG_ID_ON_CURSOR_UPDATE: {
229                 OnCursorUpdate(msg);
230                 break;
231             }
232             case MSG_ID_ON_SELECTION_CHANGE: {
233                 OnSelectionChange(msg);
234                 break;
235             }
236             case MSG_ID_ON_ATTRIBUTE_CHANGE: {
237                 OnAttributeChange(msg);
238                 break;
239             }
240             case MSG_ID_SET_SUBTYPE: {
241                 OnSetSubtype(msg);
242                 break;
243             }
244             case MSG_ID_SET_COREANDANGENT: {
245                 SetCoreAndAgent();
246                 break;
247             }
248             default: {
249                 IMSA_HILOGD("the message is %{public}d.", msg->msgId_);
250                 break;
251             }
252         }
253         delete msg;
254         msg = nullptr;
255     }
256 }
257 
OnInitInputControlChannel(Message * msg)258 void InputMethodAbility::OnInitInputControlChannel(Message *msg)
259 {
260     IMSA_HILOGD("InputMethodAbility::OnInitInputControlChannel start.");
261     MessageParcel *data = msg->msgContent_;
262     sptr<IRemoteObject> channelObject = data->ReadRemoteObject();
263     if (channelObject == nullptr) {
264         IMSA_HILOGE("channelObject is nullptr!");
265         return;
266     }
267     SetInputControlChannel(channelObject);
268 }
269 
StartInput(const InputClientInfo & clientInfo,bool isBindFromClient)270 int32_t InputMethodAbility::StartInput(const InputClientInfo &clientInfo, bool isBindFromClient)
271 {
272     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
273     int32_t cmdCount = ++cmdId_;
274     if (clientInfo.channel == nullptr) {
275         IMSA_HILOGE("channelObject is nullptr!");
276         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
277     }
278     IMSA_HILOGI("IMA isShowKeyboard: %{public}d, isBindFromClient: %{public}d.", clientInfo.isShowKeyboard,
279         isBindFromClient);
280     SetInputDataChannel(clientInfo.channel);
281     if (clientInfo.needHide) {
282         IMSA_HILOGD("pwd or normal input pattern changed, need hide panel first.");
283         auto panel = GetSoftKeyboardPanel();
284         if (panel != nullptr) {
285             panel->HidePanel();
286         }
287     }
288     {
289         std::lock_guard<std::mutex> lock(inputAttrLock_);
290         inputAttribute_.bundleName = clientInfo.config.inputAttribute.bundleName;
291     }
292     int32_t ret = isBindFromClient ? InvokeStartInputCallback(clientInfo.config, clientInfo.isNotifyInputStart)
293                                    : InvokeStartInputCallback(clientInfo.isNotifyInputStart);
294     if (ret != ErrorCode::NO_ERROR) {
295         IMSA_HILOGE("failed to invoke callback, ret: %{public}d!", ret);
296         return ret;
297     }
298     isPendingShowKeyboard_ = clientInfo.isShowKeyboard;
299     if (clientInfo.isShowKeyboard) {
300         auto task = [this, cmdCount]() {
301             std::thread([this, cmdCount]() { ShowKeyboardImplWithLock(cmdCount); }).detach();
302         };
303         if (imeListener_ == nullptr || !imeListener_->PostTaskToEventHandler(task, "ShowKeyboard")) {
304             IMSA_HILOGE("imeListener_ is nullptr, or post task failed!");
305             ShowKeyboardImplWithoutLock(cmdCount);
306         }
307         isImeTerminating_.store(false);
308     }
309     return ErrorCode::NO_ERROR;
310 }
311 
OnSetSubtype(Message * msg)312 void InputMethodAbility::OnSetSubtype(Message *msg)
313 {
314     auto data = msg->msgContent_;
315     SubProperty subProperty;
316     if (!ITypesUtil::Unmarshal(*data, subProperty)) {
317         IMSA_HILOGE("read message parcel failed!");
318         return;
319     }
320     if (imeListener_ == nullptr) {
321         IMSA_HILOGE("imeListener_ is nullptr!");
322         return;
323     }
324     imeListener_->OnSetSubtype(subProperty);
325 }
326 
ClearDataChannel(const sptr<IRemoteObject> & channel)327 void InputMethodAbility::ClearDataChannel(const sptr<IRemoteObject> &channel)
328 {
329     std::lock_guard<std::mutex> lock(dataChannelLock_);
330     if (dataChannelObject_ == nullptr || channel == nullptr) {
331         IMSA_HILOGD("dataChannelObject_ already nullptr.");
332         return;
333     }
334     if (dataChannelObject_.GetRefPtr() == channel.GetRefPtr()) {
335         dataChannelObject_ = nullptr;
336         dataChannelProxy_ = nullptr;
337         IMSA_HILOGD("end.");
338     }
339 }
340 
StopInput(const sptr<IRemoteObject> & channelObject)341 int32_t InputMethodAbility::StopInput(const sptr<IRemoteObject> &channelObject)
342 {
343     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
344     int32_t cmdCount = ++cmdId_;
345     IMSA_HILOGI("IMA");
346     HideKeyboardImplWithoutLock(cmdCount);
347     ClearDataChannel(channelObject);
348     ClearInputAttribute();
349     if (imeListener_ != nullptr) {
350         imeListener_->OnInputFinish();
351     }
352     return ErrorCode::NO_ERROR;
353 }
354 
DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent,sptr<KeyEventConsumerProxy> & consumer)355 int32_t InputMethodAbility::DispatchKeyEvent(
356     const std::shared_ptr<MMI::KeyEvent> &keyEvent, sptr<KeyEventConsumerProxy> &consumer)
357 {
358     if (keyEvent == nullptr) {
359         IMSA_HILOGE("keyEvent is nullptr!");
360         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
361     }
362     if (kdListener_ == nullptr) {
363         IMSA_HILOGE("kdListener_ is nullptr!");
364         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
365     }
366     IMSA_HILOGD("InputMethodAbility, start.");
367 
368     if (!kdListener_->OnDealKeyEvent(keyEvent, consumer)) {
369         IMSA_HILOGE("keyEvent not deal!");
370         return ErrorCode::ERROR_DISPATCH_KEY_EVENT;
371     }
372     return ErrorCode::NO_ERROR;
373 }
374 
SetCallingWindow(uint32_t windowId)375 void InputMethodAbility::SetCallingWindow(uint32_t windowId)
376 {
377     IMSA_HILOGD("InputMethodAbility windowId: %{public}d.", windowId);
378     panels_.ForEach([windowId](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
379         panel->SetCallingWindow(windowId);
380         return false;
381     });
382     if (imeListener_ == nullptr) {
383         IMSA_HILOGD("imeListener_ is nullptr!");
384         return;
385     }
386     imeListener_->OnSetCallingWindow(windowId);
387 }
388 
OnCursorUpdate(Message * msg)389 void InputMethodAbility::OnCursorUpdate(Message *msg)
390 {
391     MessageParcel *data = msg->msgContent_;
392     int32_t positionX = data->ReadInt32();
393     int32_t positionY = data->ReadInt32();
394     int32_t height = data->ReadInt32();
395     if (kdListener_ == nullptr) {
396         IMSA_HILOGE("kdListener_ is nullptr!");
397         return;
398     }
399     IMSA_HILOGD("x: %{public}d, y: %{public}d, height: %{public}d.", positionX, positionY, height);
400     kdListener_->OnCursorUpdate(positionX, positionY, height);
401 }
402 
OnSelectionChange(Message * msg)403 void InputMethodAbility::OnSelectionChange(Message *msg)
404 {
405     MessageParcel *data = msg->msgContent_;
406     std::string text = Str16ToStr8(data->ReadString16());
407     int32_t oldBegin = data->ReadInt32();
408     int32_t oldEnd = data->ReadInt32();
409     int32_t newBegin = data->ReadInt32();
410     int32_t newEnd = data->ReadInt32();
411 
412     if (kdListener_ == nullptr) {
413         IMSA_HILOGE("kdListener_ is nullptr!");
414         return;
415     }
416     kdListener_->OnTextChange(text);
417     kdListener_->OnSelectionChange(oldBegin, oldEnd, newBegin, newEnd);
418 }
419 
OnAttributeChange(Message * msg)420 void InputMethodAbility::OnAttributeChange(Message *msg)
421 {
422     if (kdListener_ == nullptr || msg == nullptr) {
423         IMSA_HILOGE("kdListener_ or msg is nullptr!");
424         return;
425     }
426     MessageParcel *data = msg->msgContent_;
427     InputAttribute attribute;
428     if (!ITypesUtil::Unmarshal(*data, attribute)) {
429         IMSA_HILOGE("failed to read attribute!");
430         return;
431     }
432     IMSA_HILOGD("enterKeyType: %{public}d, inputPattern: %{public}d.", attribute.enterKeyType,
433         attribute.inputPattern);
434     attribute.bundleName = GetInputAttribute().bundleName;
435     SetInputAttribute(attribute);
436     // add for mod inputPattern when panel show
437     auto panel = GetSoftKeyboardPanel();
438     if (panel != nullptr) {
439         auto keyboardSize = panel->GetKeyboardSize();
440         SysPanelStatus sysPanelStatus = { false, panel->GetPanelFlag(), keyboardSize.width, keyboardSize.height };
441         NotifyPanelStatus(panel, sysPanelStatus);
442     }
443     kdListener_->OnEditorAttributeChange(attribute);
444 }
445 
OnStopInputService(bool isTerminateIme)446 int32_t InputMethodAbility::OnStopInputService(bool isTerminateIme)
447 {
448     IMSA_HILOGI("isTerminateIme: %{public}d.", isTerminateIme);
449     isBound_.store(false);
450     auto imeListener = GetImeListener();
451     if (imeListener == nullptr) {
452         return ErrorCode::ERROR_IME_NOT_STARTED;
453     }
454     if (isTerminateIme) {
455         isImeTerminating_.store(true);
456         return imeListener->OnInputStop();
457     }
458     return ErrorCode::NO_ERROR;
459 }
460 
HideKeyboard()461 int32_t InputMethodAbility::HideKeyboard()
462 {
463     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
464     int32_t cmdCount = ++cmdId_;
465     return HideKeyboardImplWithoutLock(cmdCount);
466 }
467 
HideKeyboardImplWithoutLock(int32_t cmdId)468 int32_t InputMethodAbility::HideKeyboardImplWithoutLock(int32_t cmdId)
469 {
470     if (cmdId != cmdId_) {
471         IMSA_HILOGE("current is not last cmd cur: %{public}d, cmdId_: %{public}d!", cmdId, cmdId_);
472         return ErrorCode::NO_ERROR;
473     }
474     return HideKeyboard(Trigger::IMF);
475 }
476 
ShowKeyboard()477 int32_t InputMethodAbility::ShowKeyboard()
478 {
479     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
480     int32_t cmdCount = ++cmdId_;
481     return ShowKeyboardImplWithoutLock(cmdCount);
482 }
483 
ShowKeyboardImplWithLock(int32_t cmdId)484 int32_t InputMethodAbility::ShowKeyboardImplWithLock(int32_t cmdId)
485 {
486     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
487     return ShowKeyboardImplWithoutLock(cmdId);
488 }
489 
ShowKeyboardImplWithoutLock(int32_t cmdId)490 int32_t InputMethodAbility::ShowKeyboardImplWithoutLock(int32_t cmdId)
491 {
492     if (cmdId != cmdId_) {
493         IMSA_HILOGE("current is not last cmd cur: %{public}d, cmdId_: %{public}d!", cmdId, cmdId_);
494         return ErrorCode::NO_ERROR;
495     }
496     if (imeListener_ == nullptr) {
497         IMSA_HILOGE("imeListener is nullptr!");
498         return ErrorCode::ERROR_IME;
499     }
500     IMSA_HILOGI("IMA start.");
501     if (panels_.Contains(SOFT_KEYBOARD)) {
502         auto panel = GetSoftKeyboardPanel();
503         if (panel == nullptr) {
504             IMSA_HILOGE("panel is nullptr!");
505             return ErrorCode::ERROR_IME;
506         }
507         auto flag = panel->GetPanelFlag();
508         imeListener_->OnKeyboardStatus(true);
509         if (flag == FLG_CANDIDATE_COLUMN) {
510             IMSA_HILOGI("panel flag is candidate, no need to show.");
511             NotifyKeyboardHeight(0, flag);
512             return ErrorCode::NO_ERROR;
513         }
514         return ShowPanel(panel, flag, Trigger::IMF);
515     }
516     IMSA_HILOGI("panel not create.");
517     auto channel = GetInputDataChannelProxy();
518     if (channel != nullptr) {
519         channel->SendKeyboardStatus(KeyboardStatus::SHOW);
520     }
521     imeListener_->OnKeyboardStatus(true);
522     return ErrorCode::NO_ERROR;
523 }
524 
NotifyPanelStatusInfo(const PanelStatusInfo & info)525 void InputMethodAbility::NotifyPanelStatusInfo(const PanelStatusInfo &info)
526 {
527     // CANDIDATE_COLUMN not notify
528     auto channel = GetInputDataChannelProxy();
529     NotifyPanelStatusInfo(info, channel);
530 }
531 
InvokeStartInputCallback(bool isNotifyInputStart)532 int32_t InputMethodAbility::InvokeStartInputCallback(bool isNotifyInputStart)
533 {
534     TextTotalConfig textConfig = {};
535     int32_t ret = GetTextConfig(textConfig);
536     if (ret == ErrorCode::NO_ERROR) {
537         textConfig.inputAttribute.bundleName = GetInputAttribute().bundleName;
538         return InvokeStartInputCallback(textConfig, isNotifyInputStart);
539     }
540     IMSA_HILOGW("failed to get text config, ret: %{public}d.", ret);
541     if (imeListener_ == nullptr) {
542         IMSA_HILOGE("imeListener_ is nullptr!");
543         return ErrorCode::ERROR_IME;
544     }
545     if (isNotifyInputStart) {
546         imeListener_->OnInputStart();
547     }
548     return ErrorCode::NO_ERROR;
549 }
550 
InvokeStartInputCallback(const TextTotalConfig & textConfig,bool isNotifyInputStart)551 int32_t InputMethodAbility::InvokeStartInputCallback(const TextTotalConfig &textConfig, bool isNotifyInputStart)
552 {
553     if (imeListener_ == nullptr) {
554         IMSA_HILOGE("imeListener_ is nullptr!");
555         return ErrorCode::ERROR_IME;
556     }
557     positionY_ = textConfig.positionY;
558     height_ = textConfig.height;
559     SetInputAttribute(textConfig.inputAttribute);
560     if (kdListener_ != nullptr) {
561         kdListener_->OnEditorAttributeChange(textConfig.inputAttribute);
562     }
563     if (TextConfig::IsPrivateCommandValid(textConfig.privateCommand) && IsDefaultIme()) {
564         IMSA_HILOGI("notify privateCommand.");
565         imeListener_->ReceivePrivateCommand(textConfig.privateCommand);
566     }
567     if (isNotifyInputStart) {
568         imeListener_->OnInputStart();
569     }
570     if (kdListener_ != nullptr) {
571         if (textConfig.cursorInfo.left != INVALID_CURSOR_VALUE) {
572             kdListener_->OnCursorUpdate(
573                 textConfig.cursorInfo.left, textConfig.cursorInfo.top, textConfig.cursorInfo.height);
574         }
575         if (textConfig.textSelection.newBegin == INVALID_SELECTION_VALUE
576             || (textConfig.textSelection.newBegin == textConfig.textSelection.oldBegin
577                 && textConfig.textSelection.newEnd == textConfig.textSelection.oldEnd)) {
578             IMSA_HILOGD("invalid selection or no selection change");
579         } else {
580             kdListener_->OnSelectionChange(textConfig.textSelection.oldBegin, textConfig.textSelection.oldEnd,
581                 textConfig.textSelection.newBegin, textConfig.textSelection.newEnd);
582         }
583     }
584     auto task = [this, textConfig]() {
585         panels_.ForEach([&textConfig](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
586             panel->SetCallingWindow(textConfig.windowId);
587             return false;
588         });
589     };
590     imeListener_->PostTaskToEventHandler(task, "SetCallingWindow");
591     if (textConfig.windowId != INVALID_WINDOW_ID) {
592         imeListener_->OnSetCallingWindow(textConfig.windowId);
593     }
594     return ErrorCode::NO_ERROR;
595 }
596 
InsertText(const std::string text)597 int32_t InputMethodAbility::InsertText(const std::string text)
598 {
599     InputMethodSyncTrace tracer("IMA_InsertText");
600     IMSA_HILOGD("InputMethodAbility start.");
601     auto channel = GetInputDataChannelProxy();
602     if (channel == nullptr) {
603         IMSA_HILOGE("channel is nullptr!");
604         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
605     }
606     return channel->InsertText(Str8ToStr16(text));
607 }
608 
DeleteForward(int32_t length)609 int32_t InputMethodAbility::DeleteForward(int32_t length)
610 {
611     InputMethodSyncTrace tracer("IMA_DeleteForward");
612     IMSA_HILOGD("InputMethodAbility start, length: %{public}d.", length);
613     auto channel = GetInputDataChannelProxy();
614     if (channel == nullptr) {
615         IMSA_HILOGE("channel is nullptr!");
616         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
617     }
618     return channel->DeleteForward(length);
619 }
620 
DeleteBackward(int32_t length)621 int32_t InputMethodAbility::DeleteBackward(int32_t length)
622 {
623     IMSA_HILOGD("InputMethodAbility start, length: %{public}d.", length);
624     auto channel = GetInputDataChannelProxy();
625     if (channel == nullptr) {
626         IMSA_HILOGE("channel is nullptr!");
627         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
628     }
629     return channel->DeleteBackward(length);
630 }
631 
SendFunctionKey(int32_t funcKey)632 int32_t InputMethodAbility::SendFunctionKey(int32_t funcKey)
633 {
634     auto channel = GetInputDataChannelProxy();
635     if (channel == nullptr) {
636         IMSA_HILOGE("channel is nullptr!");
637         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
638     }
639     return channel->SendFunctionKey(funcKey);
640 }
641 
HideKeyboardSelf()642 int32_t InputMethodAbility::HideKeyboardSelf()
643 {
644     // Current Ime is exiting, hide softkeyboard will cause the TextFiled to lose focus.
645     if (isImeTerminating_.load()) {
646         IMSA_HILOGI("Current Ime is terminating, no need to hide keyboard.");
647         return ErrorCode::NO_ERROR;
648     }
649     InputMethodSyncTrace tracer("IMA_HideKeyboardSelf start.");
650     auto ret = HideKeyboard(Trigger::IME_APP);
651     if (ret == ErrorCode::NO_ERROR) {
652         InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_SELF);
653     }
654     return ret == ErrorCode::ERROR_CLIENT_NULL_POINTER ? ret : ErrorCode::NO_ERROR;
655 }
656 
SendExtendAction(int32_t action)657 int32_t InputMethodAbility::SendExtendAction(int32_t action)
658 {
659     IMSA_HILOGD("InputMethodAbility, action: %{public}d.", action);
660     auto channel = GetInputDataChannelProxy();
661     if (channel == nullptr) {
662         IMSA_HILOGE("channel is nullptr!");
663         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
664     }
665     return channel->HandleExtendAction(action);
666 }
667 
GetTextBeforeCursor(int32_t number,std::u16string & text)668 int32_t InputMethodAbility::GetTextBeforeCursor(int32_t number, std::u16string &text)
669 {
670     InputMethodSyncTrace tracer("IMA_GetForward");
671     IMSA_HILOGD("InputMethodAbility, number: %{public}d.", number);
672     auto channel = GetInputDataChannelProxy();
673     if (channel == nullptr) {
674         IMSA_HILOGE("channel is nullptr!");
675         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
676     }
677     return channel->GetTextBeforeCursor(number, text);
678 }
679 
GetTextAfterCursor(int32_t number,std::u16string & text)680 int32_t InputMethodAbility::GetTextAfterCursor(int32_t number, std::u16string &text)
681 {
682     InputMethodSyncTrace tracer("IMA_GetTextAfterCursor");
683     IMSA_HILOGD("InputMethodAbility, number: %{public}d.", number);
684     auto channel = GetInputDataChannelProxy();
685     if (channel == nullptr) {
686         IMSA_HILOGE("channel is nullptr!");
687         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
688     }
689     return channel->GetTextAfterCursor(number, text);
690 }
691 
MoveCursor(int32_t keyCode)692 int32_t InputMethodAbility::MoveCursor(int32_t keyCode)
693 {
694     IMSA_HILOGD("InputMethodAbility, keyCode: %{public}d.", keyCode);
695     auto channel = GetInputDataChannelProxy();
696     if (channel == nullptr) {
697         IMSA_HILOGE("channel is nullptr!");
698         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
699     }
700     return channel->MoveCursor(keyCode);
701 }
702 
SelectByRange(int32_t start,int32_t end)703 int32_t InputMethodAbility::SelectByRange(int32_t start, int32_t end)
704 {
705     IMSA_HILOGD("InputMethodAbility, start: %{public}d, end: %{public}d", start, end);
706     if (start < 0 || end < 0) {
707         IMSA_HILOGE("check parameter failed, start: %{public}d, end: %{public}d!", start, end);
708         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
709     }
710     auto dataChannel = GetInputDataChannelProxy();
711     if (dataChannel == nullptr) {
712         IMSA_HILOGE("datachannel is nullptr!");
713         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
714     }
715     return dataChannel->SelectByRange(start, end);
716 }
717 
SelectByMovement(int32_t direction)718 int32_t InputMethodAbility::SelectByMovement(int32_t direction)
719 {
720     IMSA_HILOGD("InputMethodAbility, direction: %{public}d.", direction);
721     auto dataChannel = GetInputDataChannelProxy();
722     if (dataChannel == nullptr) {
723         IMSA_HILOGE("datachannel is nullptr!");
724         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
725     }
726     return dataChannel->SelectByMovement(direction, 0);
727 }
728 
GetEnterKeyType(int32_t & keyType)729 int32_t InputMethodAbility::GetEnterKeyType(int32_t &keyType)
730 {
731     IMSA_HILOGD("InputMethodAbility start.");
732     auto channel = GetInputDataChannelProxy();
733     if (channel == nullptr) {
734         IMSA_HILOGE("channel is nullptr!");
735         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
736     }
737     return channel->GetEnterKeyType(keyType);
738 }
739 
GetInputPattern(int32_t & inputPattern)740 int32_t InputMethodAbility::GetInputPattern(int32_t &inputPattern)
741 {
742     IMSA_HILOGD("InputMethodAbility start.");
743     auto channel = GetInputDataChannelProxy();
744     if (channel == nullptr) {
745         IMSA_HILOGE("channel is nullptr!");
746         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
747     }
748     return channel->GetInputPattern(inputPattern);
749 }
750 
GetTextIndexAtCursor(int32_t & index)751 int32_t InputMethodAbility::GetTextIndexAtCursor(int32_t &index)
752 {
753     IMSA_HILOGD("InputMethodAbility start.");
754     auto channel = GetInputDataChannelProxy();
755     if (channel == nullptr) {
756         IMSA_HILOGE("channel is nullptr!");
757         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
758     }
759     return channel->GetTextIndexAtCursor(index);
760 }
761 
GetTextConfig(TextTotalConfig & textConfig)762 int32_t InputMethodAbility::GetTextConfig(TextTotalConfig &textConfig)
763 {
764     IMSA_HILOGD("InputMethodAbility start.");
765     auto channel = GetInputDataChannelProxy();
766     if (channel == nullptr) {
767         IMSA_HILOGE("channel is nullptr!");
768         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
769     }
770     auto ret = channel->GetTextConfig(textConfig);
771     if (ret == ErrorCode::NO_ERROR) {
772         textConfig.inputAttribute.bundleName = GetInputAttribute().bundleName;
773     }
774     return ret;
775 }
776 
SetInputDataChannel(const sptr<IRemoteObject> & object)777 void InputMethodAbility::SetInputDataChannel(const sptr<IRemoteObject> &object)
778 {
779     IMSA_HILOGD("SetInputDataChannel start.");
780     std::lock_guard<std::mutex> lock(dataChannelLock_);
781     auto channelProxy = std::make_shared<InputDataChannelProxy>(object);
782     if (channelProxy == nullptr) {
783         IMSA_HILOGE("failed to create channel proxy!");
784         return;
785     }
786     dataChannelObject_ = object;
787     dataChannelProxy_ = channelProxy;
788 }
789 
GetInputDataChannelProxy()790 std::shared_ptr<InputDataChannelProxy> InputMethodAbility::GetInputDataChannelProxy()
791 {
792     std::lock_guard<std::mutex> lock(dataChannelLock_);
793     return dataChannelProxy_;
794 }
795 
SetInputControlChannel(sptr<IRemoteObject> & object)796 void InputMethodAbility::SetInputControlChannel(sptr<IRemoteObject> &object)
797 {
798     IMSA_HILOGD("SetInputControlChannel start.");
799     std::lock_guard<std::mutex> lock(controlChannelLock_);
800     std::shared_ptr<InputControlChannelProxy> channelProxy = std::make_shared<InputControlChannelProxy>(object);
801     if (channelProxy == nullptr) {
802         IMSA_HILOGD("channelProxy is nullptr!");
803         return;
804     }
805     controlChannel_ = channelProxy;
806 }
807 
ClearInputControlChannel()808 void InputMethodAbility::ClearInputControlChannel()
809 {
810     std::lock_guard<std::mutex> lock(controlChannelLock_);
811     controlChannel_ = nullptr;
812 }
813 
GetInputControlChannel()814 std::shared_ptr<InputControlChannelProxy> InputMethodAbility::GetInputControlChannel()
815 {
816     std::lock_guard<std::mutex> lock(controlChannelLock_);
817     return controlChannel_;
818 }
819 
OnRemoteSaDied(const wptr<IRemoteObject> & object)820 void InputMethodAbility::OnRemoteSaDied(const wptr<IRemoteObject> &object)
821 {
822     IMSA_HILOGI("input method service died.");
823     isBound_.store(false);
824     ClearInputControlChannel();
825     ClearSystemCmdChannel();
826     {
827         std::lock_guard<std::mutex> lock(abilityLock_);
828         abilityManager_ = nullptr;
829     }
830     if (imeListener_ != nullptr) {
831         imeListener_->OnInputStop();
832     }
833 }
834 
QuitWorkThread()835 void InputMethodAbility::QuitWorkThread()
836 {
837     stop_ = true;
838     Message *msg = new Message(MessageID::MSG_ID_QUIT_WORKER_THREAD, nullptr);
839     msgHandler_->SendMessage(msg);
840     if (workThreadHandler.joinable()) {
841         workThreadHandler.join();
842     }
843 }
844 
GetSecurityMode(int32_t & security)845 int32_t InputMethodAbility::GetSecurityMode(int32_t &security)
846 {
847     IMSA_HILOGI("InputMethodAbility start.");
848     int32_t securityMode = securityMode_.load();
849     if (securityMode != INVALID_SECURITY_MODE) {
850         IMSA_HILOGD("Get cache security mode: %{public}d.", securityMode);
851         security = securityMode;
852         return ErrorCode::NO_ERROR;
853     }
854     auto proxy = GetImsaProxy();
855     if (proxy == nullptr) {
856         IMSA_HILOGE("Imsa proxy is nullptr!");
857         return ErrorCode::ERROR_NULL_POINTER;
858     }
859     auto ret = proxy->GetSecurityMode(security);
860     if (ret == ErrorCode::NO_ERROR) {
861         securityMode_.store(security);
862     }
863     return ret;
864 }
865 
ClearSystemCmdChannel()866 void InputMethodAbility::ClearSystemCmdChannel()
867 {
868     std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
869     if (systemCmdChannelProxy_ == nullptr) {
870         IMSA_HILOGD("systemCmdChannelProxy_ already nullptr.");
871         return;
872     }
873     systemCmdChannelProxy_ = nullptr;
874     IMSA_HILOGD("end.");
875 }
876 
GetSystemCmdChannelProxy()877 sptr<SystemCmdChannelProxy> InputMethodAbility::GetSystemCmdChannelProxy()
878 {
879     std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
880     return systemCmdChannelProxy_;
881 }
882 
OnConnectSystemCmd(const sptr<IRemoteObject> & channel,sptr<IRemoteObject> & agent)883 int32_t InputMethodAbility::OnConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)
884 {
885     IMSA_HILOGD("InputMethodAbility start.");
886     std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
887     systemCmdChannelProxy_ = new (std::nothrow) SystemCmdChannelProxy(channel);
888     if (systemCmdChannelProxy_ == nullptr) {
889         IMSA_HILOGE("failed to create channel proxy!");
890         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
891     }
892     systemAgentStub_ = new (std::nothrow) InputMethodAgentStub();
893     if (systemAgentStub_ == nullptr) {
894         IMSA_HILOGE("failed to create agent!");
895         systemCmdChannelProxy_ = nullptr;
896         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
897     }
898     agent = systemAgentStub_->AsObject();
899     return ErrorCode::NO_ERROR;
900 }
901 
OnSecurityChange(int32_t security)902 int32_t InputMethodAbility::OnSecurityChange(int32_t security)
903 {
904     IMSA_HILOGI("InputMethodAbility start.");
905     securityMode_.store(security);
906     if (imeListener_ == nullptr) {
907         IMSA_HILOGE("imeListener_ is nullptr!");
908         return ErrorCode::ERROR_BAD_PARAMETERS;
909     }
910     imeListener_->OnSecurityChange(security);
911     return ErrorCode::NO_ERROR;
912 }
913 
CreatePanel(const std::shared_ptr<AbilityRuntime::Context> & context,const PanelInfo & panelInfo,std::shared_ptr<InputMethodPanel> & inputMethodPanel)914 int32_t InputMethodAbility::CreatePanel(const std::shared_ptr<AbilityRuntime::Context> &context,
915     const PanelInfo &panelInfo, std::shared_ptr<InputMethodPanel> &inputMethodPanel)
916 {
917     IMSA_HILOGI("InputMethodAbility start.");
918     auto panelHeightCallback = [this](uint32_t panelHeight, PanelFlag panelFlag) {
919         NotifyKeyboardHeight(panelHeight, panelFlag);
920     };
921     auto flag = panels_.ComputeIfAbsent(
922         panelInfo.panelType, [panelHeightCallback, &panelInfo, &context, &inputMethodPanel](
923                                  const PanelType &panelType, std::shared_ptr<InputMethodPanel> &panel) {
924             inputMethodPanel = std::make_shared<InputMethodPanel>();
925             inputMethodPanel->SetPanelHeightCallback(panelHeightCallback);
926             auto ret = inputMethodPanel->CreatePanel(context, panelInfo);
927             if (ret == ErrorCode::NO_ERROR) {
928                 panel = inputMethodPanel;
929                 return true;
930             }
931             inputMethodPanel = nullptr;
932             return false;
933         });
934     // Called when creating the input method first time, if the CreatePanel is called later than the ShowKeyboard.
935     if (panelInfo.panelType == SOFT_KEYBOARD && isPendingShowKeyboard_) {
936         ShowKeyboard();
937         isPendingShowKeyboard_ = false;
938     }
939     return flag ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL;
940 }
941 
DestroyPanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel)942 int32_t InputMethodAbility::DestroyPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
943 {
944     IMSA_HILOGI("InputMethodAbility start.");
945     if (inputMethodPanel == nullptr) {
946         IMSA_HILOGE("panel is nullptr!");
947         return ErrorCode::ERROR_BAD_PARAMETERS;
948     }
949     auto ret = inputMethodPanel->DestroyPanel();
950     if (ret == ErrorCode::NO_ERROR) {
951         PanelType panelType = inputMethodPanel->GetPanelType();
952         panels_.Erase(panelType);
953     }
954     return ret;
955 }
956 
ShowPanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel)957 int32_t InputMethodAbility::ShowPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
958 {
959     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
960     if (inputMethodPanel == nullptr) {
961         return ErrorCode::ERROR_BAD_PARAMETERS;
962     }
963     return ShowPanel(inputMethodPanel, inputMethodPanel->GetPanelFlag(), Trigger::IME_APP);
964 }
965 
HidePanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel)966 int32_t InputMethodAbility::HidePanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
967 {
968     if (inputMethodPanel == nullptr) {
969         return ErrorCode::ERROR_BAD_PARAMETERS;
970     }
971 
972     // Current Ime is exiting, hide softkeyboard will cause the TextFiled to lose focus.
973     if (isImeTerminating_.load() && inputMethodPanel->GetPanelType() == PanelType::SOFT_KEYBOARD) {
974         IMSA_HILOGI("Current Ime is terminating, no need to hide keyboard.");
975         return ErrorCode::NO_ERROR;
976     }
977 
978     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
979     return HidePanel(inputMethodPanel, inputMethodPanel->GetPanelFlag(), Trigger::IME_APP);
980 }
981 
ShowPanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel,PanelFlag flag,Trigger trigger)982 int32_t InputMethodAbility::ShowPanel(
983     const std::shared_ptr<InputMethodPanel> &inputMethodPanel, PanelFlag flag, Trigger trigger)
984 {
985     if (inputMethodPanel == nullptr) {
986         return ErrorCode::ERROR_BAD_PARAMETERS;
987     }
988     if (trigger == Trigger::IME_APP && GetInputDataChannelProxy() == nullptr) {
989         IMSA_HILOGE("channel is nullptr!");
990         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
991     }
992     if (flag == FLG_FIXED && inputMethodPanel->GetPanelType() == SOFT_KEYBOARD) {
993         auto ret = inputMethodPanel->SetTextFieldAvoidInfo(positionY_, height_);
994         if (ret != ErrorCode::NO_ERROR) {
995             IMSA_HILOGE("failed to set keyBoard, ret: %{public}d!", ret);
996         }
997     }
998     auto keyboardSize = inputMethodPanel->GetKeyboardSize();
999     SysPanelStatus sysPanelStatus = { false, flag, keyboardSize.width, keyboardSize.height };
1000     NotifyPanelStatus(inputMethodPanel, sysPanelStatus);
1001     auto ret = inputMethodPanel->ShowPanel();
1002     if (ret == ErrorCode::NO_ERROR) {
1003         NotifyPanelStatusInfo({ { inputMethodPanel->GetPanelType(), flag }, true, trigger });
1004     }
1005     return ret;
1006 }
1007 
HidePanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel,PanelFlag flag,Trigger trigger)1008 int32_t InputMethodAbility::HidePanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel, PanelFlag flag,
1009                                       Trigger trigger)
1010 {
1011     if (inputMethodPanel == nullptr) {
1012         return ErrorCode::ERROR_BAD_PARAMETERS;
1013     }
1014     auto ret = inputMethodPanel->HidePanel();
1015     if (ret != ErrorCode::NO_ERROR) {
1016         IMSA_HILOGD("failed, ret: %{public}d", ret);
1017         return ret;
1018     }
1019     NotifyPanelStatusInfo({ { inputMethodPanel->GetPanelType(), flag }, false, trigger });
1020     return ErrorCode::NO_ERROR;
1021 }
1022 
NotifyPanelStatus(const std::shared_ptr<InputMethodPanel> & inputMethodPanel,SysPanelStatus & sysPanelStatus)1023 int32_t InputMethodAbility::NotifyPanelStatus(
1024     const std::shared_ptr<InputMethodPanel> &inputMethodPanel, SysPanelStatus &sysPanelStatus)
1025 {
1026     if (inputMethodPanel->GetPanelType() != SOFT_KEYBOARD) {
1027         return ErrorCode::NO_ERROR;
1028     }
1029     // If it is not binding, do not need to notify the panel
1030     auto channel = GetInputDataChannelProxy();
1031     if (channel == nullptr) {
1032         return ErrorCode::NO_ERROR;
1033     }
1034     bool isSecurity = GetInputAttribute().GetSecurityFlag();
1035     sysPanelStatus.isSecurity = isSecurity;
1036     auto systemChannel = GetSystemCmdChannelProxy();
1037     if (systemChannel == nullptr) {
1038         IMSA_HILOGE("channel is nullptr!");
1039         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1040     }
1041     return systemChannel->NotifyPanelStatus(sysPanelStatus);
1042 }
1043 
SetInputAttribute(const InputAttribute & inputAttribute)1044 void InputMethodAbility::SetInputAttribute(const InputAttribute &inputAttribute)
1045 {
1046     std::lock_guard<std::mutex> lock(inputAttrLock_);
1047     inputAttribute_ = inputAttribute;
1048 }
1049 
ClearInputAttribute()1050 void InputMethodAbility::ClearInputAttribute()
1051 {
1052     std::lock_guard<std::mutex> lock(inputAttrLock_);
1053     inputAttribute_ = {};
1054 }
1055 
GetInputAttribute()1056 InputAttribute InputMethodAbility::GetInputAttribute()
1057 {
1058     std::lock_guard<std::mutex> lock(inputAttrLock_);
1059     return inputAttribute_;
1060 }
1061 
HideKeyboard(Trigger trigger)1062 int32_t InputMethodAbility::HideKeyboard(Trigger trigger)
1063 {
1064     InputMethodSyncTrace tracer("IMA_HideKeyboard");
1065     if (imeListener_ == nullptr) {
1066         IMSA_HILOGE("imeListener_ is nullptr!");
1067         return ErrorCode::ERROR_IME;
1068     }
1069     IMSA_HILOGD("IMA, trigger: %{public}d.", static_cast<int32_t>(trigger));
1070     if (panels_.Contains(SOFT_KEYBOARD)) {
1071         auto panel = GetSoftKeyboardPanel();
1072         if (panel == nullptr) {
1073             IMSA_HILOGE("panel is nullptr!");
1074             return ErrorCode::ERROR_IME;
1075         }
1076         auto flag = panel->GetPanelFlag();
1077         imeListener_->OnKeyboardStatus(false);
1078         if (flag == FLG_CANDIDATE_COLUMN) {
1079             IMSA_HILOGI("panel flag is candidate, no need to hide.");
1080             return ErrorCode::NO_ERROR;
1081         }
1082         return HidePanel(panel, flag, trigger);
1083     }
1084     IMSA_HILOGI("panel is not created.");
1085     imeListener_->OnKeyboardStatus(false);
1086     auto channel = GetInputDataChannelProxy();
1087     if (channel != nullptr) {
1088         channel->SendKeyboardStatus(KeyboardStatus::HIDE);
1089     }
1090     auto controlChannel = GetInputControlChannel();
1091     if (controlChannel != nullptr && trigger == Trigger::IME_APP) {
1092         controlChannel->HideKeyboardSelf();
1093     }
1094     return ErrorCode::NO_ERROR;
1095 }
1096 
GetSoftKeyboardPanel()1097 std::shared_ptr<InputMethodPanel> InputMethodAbility::GetSoftKeyboardPanel()
1098 {
1099     auto result = panels_.Find(SOFT_KEYBOARD);
1100     if (!result.first) {
1101         return nullptr;
1102     }
1103     auto panel = result.second;
1104     if (!BlockRetry(FIND_PANEL_RETRY_INTERVAL, MAX_RETRY_TIMES, [panel]() -> bool {
1105             return panel != nullptr && panel->windowId_ != InputMethodPanel::INVALID_WINDOW_ID;
1106         })) {
1107         return nullptr;
1108     }
1109     return panel;
1110 }
1111 
IsCurrentIme()1112 bool InputMethodAbility::IsCurrentIme()
1113 {
1114     IMSA_HILOGD("InputMethodAbility start.");
1115     if (isCurrentIme_) {
1116         return true;
1117     }
1118     std::lock_guard<std::mutex> lock(imeCheckMutex_);
1119     if (isCurrentIme_) {
1120         return true;
1121     }
1122     auto proxy = GetImsaProxy();
1123     if (proxy == nullptr) {
1124         IMSA_HILOGE("failed to get imsa proxy!");
1125         return false;
1126     }
1127     if (proxy->IsCurrentIme()) {
1128         isCurrentIme_ = true;
1129         return true;
1130     }
1131     return false;
1132 }
1133 
IsDefaultIme()1134 bool InputMethodAbility::IsDefaultIme()
1135 {
1136     IMSA_HILOGD("InputMethodAbility start");
1137     if (isDefaultIme_) {
1138         return true;
1139     }
1140     std::lock_guard<std::mutex> lock(defaultImeCheckMutex_);
1141     if (isDefaultIme_) {
1142         return true;
1143     }
1144     auto proxy = GetImsaProxy();
1145     if (proxy == nullptr) {
1146         IMSA_HILOGE("failed to get imsa proxy!");
1147         return false;
1148     }
1149     auto ret = proxy->IsDefaultIme();
1150     if (ret == ErrorCode::NO_ERROR) {
1151         isDefaultIme_ = true;
1152         return true;
1153     }
1154     IMSA_HILOGE("call IsDefaultIme failed, ret: %{public}d!", ret);
1155     return false;
1156 }
1157 
IsEnable()1158 bool InputMethodAbility::IsEnable()
1159 {
1160     if (imeListener_ == nullptr) {
1161         return false;
1162     }
1163     return imeListener_->IsEnable();
1164 }
1165 
IsSystemApp()1166 bool InputMethodAbility::IsSystemApp()
1167 {
1168     IMSA_HILOGD("InputMethodAbility start");
1169     if (isSystemApp_) {
1170         return true;
1171     }
1172     std::lock_guard<std::mutex> lock(systemAppCheckMutex_);
1173     if (isSystemApp_) {
1174         return true;
1175     }
1176     auto proxy = GetImsaProxy();
1177     if (proxy == nullptr) {
1178         IMSA_HILOGE("failed to get imsa proxy!");
1179         return false;
1180     }
1181     if (proxy->IsSystemApp()) {
1182         isSystemApp_ = true;
1183         return true;
1184     }
1185     return false;
1186 }
1187 
ExitCurrentInputType()1188 int32_t InputMethodAbility::ExitCurrentInputType()
1189 {
1190     IMSA_HILOGD("InputMethodAbility start.");
1191     auto proxy = GetImsaProxy();
1192     if (proxy == nullptr) {
1193         IMSA_HILOGE("failed to get imsa proxy!");
1194         return false;
1195     }
1196     return proxy->ExitCurrentInputType();
1197 }
1198 
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)1199 int32_t InputMethodAbility::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
1200 {
1201     isShown = false;
1202     auto result = panels_.Find(panelInfo.panelType);
1203     if (!result.first) {
1204         IMSA_HILOGI("panel type: %{public}d not found.", static_cast<int32_t>(panelInfo.panelType));
1205         return ErrorCode::NO_ERROR;
1206     }
1207     auto panel = result.second;
1208     if (panel->GetPanelType() == PanelType::SOFT_KEYBOARD && panel->GetPanelFlag() != panelInfo.panelFlag) {
1209         IMSA_HILOGI("queried flag: %{public}d, current flag: %{public}d, panel not found.",
1210             static_cast<int32_t>(panelInfo.panelFlag), static_cast<int32_t>(panel->GetPanelFlag()));
1211         return ErrorCode::NO_ERROR;
1212     }
1213     isShown = panel->IsShowing();
1214     IMSA_HILOGI("type: %{public}d, flag: %{public}d, result: %{public}d.", static_cast<int32_t>(panelInfo.panelType),
1215         static_cast<int32_t>(panelInfo.panelFlag), isShown);
1216     return ErrorCode::NO_ERROR;
1217 }
1218 
OnClientInactive(const sptr<IRemoteObject> & channel)1219 void InputMethodAbility::OnClientInactive(const sptr<IRemoteObject> &channel)
1220 {
1221     IMSA_HILOGI("client inactive.");
1222     if (imeListener_ != nullptr) {
1223         imeListener_->OnInputFinish();
1224     }
1225     auto channelProxy = std::make_shared<InputDataChannelProxy>(channel);
1226     if (channelProxy == nullptr) {
1227         IMSA_HILOGE("failed to create channel proxy!");
1228         return;
1229     }
1230     auto panel = GetSoftKeyboardPanel();
1231     if (imeListener_ != nullptr && panel != nullptr && panel->GetPanelFlag() != PanelFlag::FLG_FIXED) {
1232         imeListener_->OnKeyboardStatus(false);
1233     }
1234     panels_.ForEach([this, &channelProxy](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
1235         if (panelType != PanelType::SOFT_KEYBOARD || panel->GetPanelFlag() != PanelFlag::FLG_FIXED) {
1236             auto ret = panel->HidePanel();
1237             if (ret != ErrorCode::NO_ERROR) {
1238                 IMSA_HILOGE("failed, ret: %{public}d", ret);
1239                 return false;
1240             }
1241             NotifyPanelStatusInfo({ { panel->GetPanelType(), panel->GetPanelFlag() }, false, Trigger::IME_APP },
1242                 channelProxy);
1243             // finish previewing text when soft keyboard hides
1244             if (panel->GetPanelType() == PanelType::SOFT_KEYBOARD) {
1245                 FinishTextPreview(true);
1246             }
1247         }
1248         return false;
1249     });
1250     ClearDataChannel(channel);
1251 }
1252 
NotifyKeyboardHeight(uint32_t panelHeight,PanelFlag panelFlag)1253 void InputMethodAbility::NotifyKeyboardHeight(uint32_t panelHeight, PanelFlag panelFlag)
1254 {
1255     auto channel = GetInputDataChannelProxy();
1256     if (channel == nullptr) {
1257         IMSA_HILOGE("channel is nullptr!");
1258         return;
1259     }
1260     IMSA_HILOGD("notify panel height: %{public}u, flag: %{public}d.", panelHeight, static_cast<int32_t>(panelFlag));
1261     if (panelFlag != PanelFlag::FLG_FIXED) {
1262         channel->NotifyKeyboardHeight(0);
1263         return;
1264     }
1265     channel->NotifyKeyboardHeight(panelHeight);
1266 }
1267 
SendPrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1268 int32_t InputMethodAbility::SendPrivateCommand(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1269 {
1270     if (!IsDefaultIme()) {
1271         IMSA_HILOGE("current is not default ime.");
1272         return ErrorCode::ERROR_NOT_DEFAULT_IME;
1273     }
1274     if (!TextConfig::IsPrivateCommandValid(privateCommand)) {
1275         IMSA_HILOGE("privateCommand is limit 32KB, count limit 5!");
1276         return ErrorCode::ERROR_INVALID_PRIVATE_COMMAND_SIZE;
1277     }
1278     if (TextConfig::IsSystemPrivateCommand(privateCommand)) {
1279         auto systemChannel = GetSystemCmdChannelProxy();
1280         if (systemChannel == nullptr) {
1281             IMSA_HILOGE("channel is nullptr!");
1282             return ErrorCode::ERROR_SYSTEM_CMD_CHANNEL_ERROR;
1283         }
1284         return systemChannel->SendPrivateCommand(privateCommand);
1285     } else {
1286         auto channel = GetInputDataChannelProxy();
1287         if (channel == nullptr) {
1288             IMSA_HILOGE("channel is nullptr!");
1289             return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1290         }
1291         return channel->SendPrivateCommand(privateCommand);
1292     }
1293 }
1294 
ReceivePrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1295 int32_t InputMethodAbility::ReceivePrivateCommand(
1296     const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1297 {
1298     if (!IsDefaultIme()) {
1299         IMSA_HILOGE("current is not default ime!");
1300         return ErrorCode::ERROR_NOT_DEFAULT_IME;
1301     }
1302     if (imeListener_ == nullptr) {
1303         IMSA_HILOGE("imeListener is nullptr!");
1304         return ErrorCode::ERROR_IME;
1305     }
1306     imeListener_->ReceivePrivateCommand(privateCommand);
1307     return ErrorCode::NO_ERROR;
1308 }
1309 
SetPreviewText(const std::string & text,const Range & range)1310 int32_t InputMethodAbility::SetPreviewText(const std::string &text, const Range &range)
1311 {
1312     InputMethodSyncTrace tracer("IMA_SetPreviewText");
1313     auto dataChannel = GetInputDataChannelProxy();
1314     if (dataChannel == nullptr) {
1315         IMSA_HILOGE("dataChannel is nullptr!");
1316         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1317     }
1318     return dataChannel->SetPreviewText(text, range);
1319 }
1320 
FinishTextPreview(bool isAsync)1321 int32_t InputMethodAbility::FinishTextPreview(bool isAsync)
1322 {
1323     InputMethodSyncTrace tracer("IMA_FinishTextPreview");
1324     auto dataChannel = GetInputDataChannelProxy();
1325     if (dataChannel == nullptr) {
1326         IMSA_HILOGE("dataChannel is nullptr!");
1327         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1328     }
1329     return dataChannel->FinishTextPreview(isAsync);
1330 }
1331 
GetCallingWindowInfo(CallingWindowInfo & windowInfo)1332 int32_t InputMethodAbility::GetCallingWindowInfo(CallingWindowInfo &windowInfo)
1333 {
1334     IMSA_HILOGD("IMA start.");
1335     auto channel = GetInputDataChannelProxy();
1336     if (channel == nullptr) {
1337         IMSA_HILOGE("channel is nullptr!");
1338         return ErrorCode::ERROR_CLIENT_NOT_FOUND;
1339     }
1340     auto panel = GetSoftKeyboardPanel();
1341     if (panel == nullptr) {
1342         IMSA_HILOGE("panel not found!");
1343         return ErrorCode::ERROR_PANEL_NOT_FOUND;
1344     }
1345     TextTotalConfig textConfig;
1346     int32_t ret = GetTextConfig(textConfig);
1347     if (ret != ErrorCode::NO_ERROR) {
1348         IMSA_HILOGE("failed to get window id, ret: %{public}d!", ret);
1349         return ErrorCode::ERROR_GET_TEXT_CONFIG;
1350     }
1351     ret = panel->SetCallingWindow(textConfig.windowId);
1352     if (ret != ErrorCode::NO_ERROR) {
1353         IMSA_HILOGE("failed to set calling window, ret: %{public}d!", ret);
1354         return ret;
1355     }
1356     ret = panel->GetCallingWindowInfo(windowInfo);
1357     if (ret != ErrorCode::NO_ERROR) {
1358         IMSA_HILOGE("failed to get calling window, ret: %{public}d", ret);
1359     }
1360     return ret;
1361 }
1362 
NotifyPanelStatusInfo(const PanelStatusInfo & info,std::shared_ptr<InputDataChannelProxy> & channelProxy)1363 void InputMethodAbility::NotifyPanelStatusInfo(
1364     const PanelStatusInfo &info, std::shared_ptr<InputDataChannelProxy> &channelProxy)
1365 {
1366     // CANDIDATE_COLUMN not notify
1367     if (info.panelInfo.panelFlag == PanelFlag::FLG_CANDIDATE_COLUMN) {
1368         return;
1369     }
1370     if (channelProxy != nullptr) {
1371         channelProxy->NotifyPanelStatusInfo(info);
1372     }
1373 
1374     auto controlChannel = GetInputControlChannel();
1375     if (controlChannel != nullptr && info.trigger == Trigger::IME_APP && !info.visible) {
1376         controlChannel->HideKeyboardSelf();
1377     }
1378 }
1379 
SendMessage(const ArrayBuffer & arrayBuffer)1380 int32_t InputMethodAbility::SendMessage(const ArrayBuffer &arrayBuffer)
1381 {
1382     int32_t securityMode = INVALID_SECURITY_MODE;
1383     auto ret = GetSecurityMode(securityMode);
1384     if (ret != ErrorCode::NO_ERROR) {
1385         IMSA_HILOGE("Get security mode failed!");
1386         return ret;
1387     }
1388     if (!ArrayBuffer::IsSizeValid(arrayBuffer)) {
1389         IMSA_HILOGE("arrayBuffer size is invalid!");
1390         return ErrorCode::ERROR_INVALID_ARRAY_BUFFER_SIZE;
1391     }
1392     if (securityMode != static_cast<int32_t>(SecurityMode::FULL)) {
1393         IMSA_HILOGE("Security mode must be FULL!.");
1394         return ErrorCode::ERROR_SECURITY_MODE_OFF;
1395     }
1396     auto dataChannel = GetInputDataChannelProxy();
1397     if (dataChannel == nullptr) {
1398         IMSA_HILOGE("datachannel is nullptr.");
1399         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1400     }
1401     return dataChannel->SendMessage(arrayBuffer);
1402 }
1403 
RecvMessage(const ArrayBuffer & arrayBuffer)1404 int32_t InputMethodAbility::RecvMessage(const ArrayBuffer &arrayBuffer)
1405 {
1406     int32_t securityMode = -1;
1407     auto ret = GetSecurityMode(securityMode);
1408     if (ret != ErrorCode::NO_ERROR) {
1409         IMSA_HILOGE("Get security mode failed!");
1410         return ret;
1411     }
1412     if (securityMode != static_cast<int32_t>(SecurityMode::FULL)) {
1413         IMSA_HILOGE("Security mode must be FULL!.");
1414         return ErrorCode::ERROR_SECURITY_MODE_OFF;
1415     }
1416     auto msgHandlerCallback = GetMsgHandlerCallback();
1417     if (msgHandlerCallback == nullptr) {
1418         IMSA_HILOGW("Message handler was not regist!");
1419         return ErrorCode::ERROR_MSG_HANDLER_NOT_REGIST;
1420     }
1421     return msgHandlerCallback->OnMessage(arrayBuffer);
1422 }
1423 
RegisterMsgHandler(const std::shared_ptr<MsgHandlerCallbackInterface> & msgHandler)1424 int32_t InputMethodAbility::RegisterMsgHandler(const std::shared_ptr<MsgHandlerCallbackInterface> &msgHandler)
1425 {
1426     IMSA_HILOGI("isRegist: %{public}d", msgHandler != nullptr);
1427     std::shared_ptr<MsgHandlerCallbackInterface> exMsgHandler = nullptr;
1428     {
1429         std::lock_guard<decltype(msgHandlerMutex_)> lock(msgHandlerMutex_);
1430         exMsgHandler = jsMsgHandler_;
1431         jsMsgHandler_ = msgHandler;
1432     }
1433     if (exMsgHandler != nullptr) {
1434         IMSA_HILOGI("Trigger exMessageHandler OnTerminated.");
1435         exMsgHandler->OnTerminated();
1436     }
1437     return ErrorCode::NO_ERROR;
1438 }
1439 
GetMsgHandlerCallback()1440 std::shared_ptr<MsgHandlerCallbackInterface> InputMethodAbility::GetMsgHandlerCallback()
1441 {
1442     std::lock_guard<decltype(msgHandlerMutex_)> lock(msgHandlerMutex_);
1443     return jsMsgHandler_;
1444 }
1445 } // namespace MiscServices
1446 } // namespace OHOS
1447