• 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 #include <utility>
20 
21 #include "global.h"
22 #include "ima_hisysevent_reporter.h"
23 #include "input_method_agent_service_impl.h"
24 #include "input_method_core_service_impl.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 "on_demand_start_stop_sa.h"
33 #include "string_ex.h"
34 #include "sys/prctl.h"
35 #include "system_ability_definition.h"
36 #include "task_manager.h"
37 #include "tasks/task.h"
38 #include "tasks/task_imsa.h"
39 #include "input_method_tools.h"
40 #include "variant_util.h"
41 
42 namespace OHOS {
43 namespace MiscServices {
44 using namespace MessageID;
45 using namespace std::chrono;
46 constexpr double INVALID_CURSOR_VALUE = -1.0;
47 constexpr int32_t INVALID_SELECTION_VALUE = -1;
48 constexpr uint32_t FIND_PANEL_RETRY_INTERVAL = 10;
49 constexpr uint32_t MAX_RETRY_TIMES = 100;
50 constexpr uint32_t START_INPUT_CALLBACK_TIMEOUT_MS = 1000;
51 constexpr uint32_t INVALID_SECURITY_MODE = -1;
52 constexpr uint32_t BASE_TEXT_OPERATION_TIMEOUT = 200;
53 
InputMethodAbility()54 InputMethodAbility::InputMethodAbility()
55 {
56     Initialize();
57 }
58 
~InputMethodAbility()59 InputMethodAbility::~InputMethodAbility()
60 {
61     IMSA_HILOGI("InputMethodAbility::~InputMethodAbility.");
62 }
63 
GetInstance()64 InputMethodAbility &InputMethodAbility::GetInstance()
65 {
66     static InputMethodAbility instance;
67     return instance;
68 }
69 
GetImsaProxy()70 sptr<IInputMethodSystemAbility> InputMethodAbility::GetImsaProxy()
71 {
72     std::lock_guard<std::mutex> lock(abilityLock_);
73     if (abilityManager_ != nullptr) {
74         return abilityManager_;
75     }
76     IMSA_HILOGI("InputMethodAbility get imsa proxy.");
77     auto systemAbility = OnDemandStartStopSa::GetInputMethodSystemAbility();
78     if (systemAbility == nullptr) {
79         IMSA_HILOGE("systemAbility is nullptr!");
80         return nullptr;
81     }
82     if (deathRecipient_ == nullptr) {
83         deathRecipient_ = new (std::nothrow) InputDeathRecipient();
84         if (deathRecipient_ == nullptr) {
85             IMSA_HILOGE("failed to new death recipient!");
86             return nullptr;
87         }
88     }
89     deathRecipient_->SetDeathRecipient([this](const wptr<IRemoteObject> &remote) {
90         OnRemoteSaDied(remote);
91     });
92     if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) {
93         IMSA_HILOGE("failed to add death recipient!");
94         return nullptr;
95     }
96     abilityManager_ = iface_cast<IInputMethodSystemAbility>(systemAbility);
97     return abilityManager_;
98 }
99 
SetCoreAndAgent()100 int32_t InputMethodAbility::SetCoreAndAgent()
101 {
102     IMSA_HILOGD("InputMethodAbility, start.");
103     TaskManager::GetInstance().SetInited(true);
104 
105     if (isBound_.load()) {
106         IMSA_HILOGD("already bound.");
107         return ErrorCode::NO_ERROR;
108     }
109     auto proxy = GetImsaProxy();
110     if (proxy == nullptr) {
111         IMSA_HILOGE("imsa proxy is nullptr!");
112         return ErrorCode::ERROR_NULL_POINTER;
113     }
114     int32_t ret = proxy->SetCoreAndAgent(coreStub_, agentStub_->AsObject());
115     if (ret != ErrorCode::NO_ERROR) {
116         IMSA_HILOGE("set failed, ret: %{public}d!", ret);
117         return ret;
118     }
119     isBound_.store(true);
120     IMSA_HILOGD("set successfully.");
121     return ErrorCode::NO_ERROR;
122 }
123 
InitConnect()124 int32_t InputMethodAbility::InitConnect()
125 {
126     IMSA_HILOGD("InputMethodAbility, init connect.");
127     auto proxy = GetImsaProxy();
128     if (proxy == nullptr) {
129         IMSA_HILOGE("imsa proxy is nullptr!");
130         return ErrorCode::ERROR_NULL_POINTER;
131     }
132     int32_t ret = proxy->InitConnect();
133     if (ret != ErrorCode::NO_ERROR) {
134         IMSA_HILOGE("set failed, ret: %{public}d!", ret);
135         return ret;
136     }
137     return ErrorCode::NO_ERROR;
138 }
139 
UnRegisteredProxyIme(UnRegisteredType type)140 int32_t InputMethodAbility::UnRegisteredProxyIme(UnRegisteredType type)
141 {
142     IMSA_HILOGD("type %{public}d", type);
143     isBound_.store(false);
144     auto proxy = GetImsaProxy();
145     if (proxy == nullptr) {
146         IMSA_HILOGE("imsa proxy is nullptr!");
147         return ErrorCode::ERROR_NULL_POINTER;
148     }
149     return proxy->UnRegisteredProxyIme(static_cast<int32_t>(type), coreStub_);
150 }
151 
RegisterProxyIme(uint64_t displayId)152 int32_t InputMethodAbility::RegisterProxyIme(uint64_t displayId)
153 {
154     IMSA_HILOGD("IMA, displayId: %{public}" PRIu64 "", displayId);
155     TaskManager::GetInstance().SetInited(true);
156 
157     if (isBound_.load()) {
158         IMSA_HILOGD("already bound.");
159         return ErrorCode::NO_ERROR;
160     }
161     auto proxy = GetImsaProxy();
162     if (proxy == nullptr) {
163         IMSA_HILOGE("imsa proxy is nullptr!");
164         return ErrorCode::ERROR_SERVICE_START_FAILED;
165     }
166     if (agentStub_ == nullptr) {
167         IMSA_HILOGE("agent nullptr");
168         return ErrorCode::ERROR_NULL_POINTER;
169     }
170     int32_t ret = displayId == DEFAULT_DISPLAY_ID
171                       ? proxy->SetCoreAndAgent(coreStub_, agentStub_->AsObject())
172                       : proxy->RegisterProxyIme(displayId, coreStub_, agentStub_->AsObject());
173     if (ret != ErrorCode::NO_ERROR) {
174         IMSA_HILOGE("failed, displayId: %{public}" PRIu64 ", ret: %{public}d!", displayId, ret);
175         return ret;
176     }
177     isBound_.store(true);
178     isProxyIme_.store(displayId != DEFAULT_DISPLAY_ID);
179     IMSA_HILOGD("set successfully, displayId: %{public}" PRIu64 "", displayId);
180     return ErrorCode::NO_ERROR;
181 }
182 
UnregisterProxyIme(uint64_t displayId)183 int32_t InputMethodAbility::UnregisterProxyIme(uint64_t displayId)
184 {
185     isBound_.store(false);
186     isProxyIme_.store(false);
187     auto proxy = GetImsaProxy();
188     if (proxy == nullptr) {
189         IMSA_HILOGE("imsa proxy is nullptr!");
190         return ErrorCode::ERROR_SERVICE_START_FAILED;
191     }
192     return proxy->UnregisterProxyIme(displayId);
193 }
194 
BindImeMirror()195 int32_t InputMethodAbility::BindImeMirror()
196 {
197     TaskManager::GetInstance().SetInited(true);
198 
199     if (isBound_.load()) {
200         IMSA_HILOGD("[ImeMirrorTag]already bound.");
201         return ErrorCode::NO_ERROR;
202     }
203     auto proxy = GetImsaProxy();
204     if (proxy == nullptr) {
205         IMSA_HILOGE("[ImeMirrorTag]imsa proxy is nullptr!");
206         return ErrorCode::ERROR_SERVICE_START_FAILED;
207     }
208     if (agentStub_ == nullptr) {
209         IMSA_HILOGE("[ImeMirrorTag]agent nullptr");
210         return ErrorCode::ERROR_NULL_POINTER;
211     }
212 
213     auto ret = proxy->BindImeMirror(coreStub_, agentStub_->AsObject());
214     if (ret != ErrorCode::NO_ERROR) {
215         IMSA_HILOGE("[ImeMirrorTag]failed, ret: %{public}d!", ret);
216         return ret;
217     }
218     IMSA_HILOGD("[ImeMirrorTag]register imsa start event");
219     imeMirrorMgr_.SubscribeSaStart(
220         [this]() {
221             if (!imeMirrorMgr_.IsImeMirrorEnable()) {
222                 IMSA_HILOGI("[ImeMirrorTag]imsa started, no need resume ime mirror");
223                 return;
224             }
225             IMSA_HILOGI("[ImeMirrorTag]imsa started, resume ime mirror");
226             BindImeMirror();
227         },
228         INPUT_METHOD_SYSTEM_ABILITY_ID);
229     isBound_.store(true);
230     imeMirrorMgr_.SetImeMirrorEnable(true);
231     IMSA_HILOGI("[ImeMirrorTag]set successfully");
232     return ErrorCode::NO_ERROR;
233 }
234 
UnbindImeMirror()235 int32_t InputMethodAbility::UnbindImeMirror()
236 {
237     isBound_.store(false);
238     imeMirrorMgr_.SetImeMirrorEnable(false);
239     imeMirrorMgr_.UnSubscribeSaStart(INPUT_METHOD_SYSTEM_ABILITY_ID);
240     auto proxy = GetImsaProxy();
241     if (proxy == nullptr) {
242         IMSA_HILOGE("[ImeMirrorTag]imsa proxy is nullptr!");
243         return ErrorCode::ERROR_SERVICE_START_FAILED;
244     }
245     return proxy->UnbindImeMirror();
246 }
247 
Initialize()248 void InputMethodAbility::Initialize()
249 {
250     IMSA_HILOGD("IMA init.");
251     sptr<InputMethodCoreStub> coreStub = new (std::nothrow) InputMethodCoreServiceImpl();
252     if (coreStub == nullptr) {
253         IMSA_HILOGE("failed to create core!");
254         return;
255     }
256     sptr<InputMethodAgentStub> agentStub = new (std::nothrow) InputMethodAgentServiceImpl();
257     if (agentStub == nullptr) {
258         IMSA_HILOGE("failed to create agent!");
259         return;
260     }
261     agentStub_ = agentStub;
262     coreStub_ = coreStub;
263 }
264 
SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)265 void InputMethodAbility::SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)
266 {
267     IMSA_HILOGD("InputMethodAbility start.");
268     if (imeListener_ == nullptr) {
269         imeListener_ = std::move(imeListener);
270     }
271 }
272 
GetImeListener()273 std::shared_ptr<InputMethodEngineListener> InputMethodAbility::GetImeListener()
274 {
275     return imeListener_;
276 }
277 
SetKdListener(std::shared_ptr<KeyboardListener> kdListener)278 void InputMethodAbility::SetKdListener(std::shared_ptr<KeyboardListener> kdListener)
279 {
280     IMSA_HILOGD("InputMethodAbility start.");
281     if (kdListener_ == nullptr) {
282         kdListener_ = std::move(kdListener);
283     }
284 }
285 
SetTextInputClientListener(std::shared_ptr<TextInputClientListener> textInputClientListener)286 void InputMethodAbility::SetTextInputClientListener(std::shared_ptr<TextInputClientListener> textInputClientListener)
287 {
288     IMSA_HILOGD("InputMethodAbility start.");
289     if (textInputClientListener_ == nullptr) {
290         textInputClientListener_ = std::move(textInputClientListener);
291     }
292 }
293 
OnInitInputControlChannel(sptr<IRemoteObject> channelObj)294 void InputMethodAbility::OnInitInputControlChannel(sptr<IRemoteObject> channelObj)
295 {
296     IMSA_HILOGD("InputMethodAbility::OnInitInputControlChannel start.");
297     SetInputControlChannel(channelObj);
298 }
299 
StartInputInner(const InputClientInfo & clientInfo,bool isBindFromClient)300 int32_t InputMethodAbility::StartInputInner(const InputClientInfo &clientInfo, bool isBindFromClient)
301 {
302     SetBindClientInfo(clientInfo);
303     if (clientInfo.channel == nullptr) {
304         IMSA_HILOGE("channelObject is nullptr!");
305         return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
306     }
307     IMSA_HILOGI("IMA showKeyboard:%{public}d,bindFromClient:%{public}d.", clientInfo.isShowKeyboard, isBindFromClient);
308     SetInputDataChannel(clientInfo.channel);
309     auto attribute = GetInputAttribute();
310     if ((clientInfo.needHide && !isProxyIme_.load()) ||
311         IsDisplayChanged(attribute.callingDisplayId, clientInfo.config.inputAttribute.callingDisplayId)) {
312         IMSA_HILOGD("pwd or normal input pattern changed, need hide panel first.");
313         auto panel = GetSoftKeyboardPanel();
314         if (panel != nullptr) {
315             panel->HidePanel();
316         }
317     }
318     int32_t ret = isBindFromClient
319                       ? InvokeStartInputCallback(clientInfo.config, clientInfo.isNotifyInputStart)
320                       : InvokeStartInputCallbackWithInfoRestruct(clientInfo.config, clientInfo.isNotifyInputStart);
321     if (ret != ErrorCode::NO_ERROR) {
322         IMSA_HILOGE("failed to invoke callback, ret: %{public}d!", ret);
323         return ret;
324     }
325     auto time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
326     auto showPanel = [&, needShow = clientInfo.isShowKeyboard, startTime = time] {
327         auto endTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
328         int32_t ret = ErrorCode::NO_ERROR;
329         if (needShow) {
330             ret = ShowKeyboardImplWithoutLock(cmdId_);
331         }
332         ReportImeStartInput(
333             static_cast<int32_t>(IInputMethodCoreIpcCode::COMMAND_START_INPUT), ret, needShow, endTime - startTime);
334         isImeTerminating_.store(false);
335     };
336     uint64_t seqId = Task::GetNextSeqId();
337     if (imeListener_ == nullptr ||
338         !imeListener_->PostTaskToEventHandler([seqId] { TaskManager::GetInstance().Complete(seqId); },
339             "task_manager_complete")) {
340         showPanel();
341         return ErrorCode::NO_ERROR;
342     }
343     TaskManager::GetInstance().WaitExec(seqId, START_INPUT_CALLBACK_TIMEOUT_MS, showPanel);
344     return ErrorCode::NO_ERROR;
345 }
346 
IsDisplayChanged(uint64_t oldDisplayId,uint64_t newDisplayId)347 bool InputMethodAbility::IsDisplayChanged(uint64_t oldDisplayId, uint64_t newDisplayId)
348 {
349     if (oldDisplayId == newDisplayId) {
350         IMSA_HILOGD("screen not changed!");
351         return false;
352     }
353     auto proxy = GetImsaProxy();
354     if (proxy == nullptr) {
355         IMSA_HILOGE("imsa proxy is nullptr!");
356         return false;
357     }
358     bool ret = false;
359     int32_t result = proxy->IsRestrictedDefaultImeByDisplay(oldDisplayId, ret);
360     if (result != ErrorCode::NO_ERROR) {
361         IMSA_HILOGE("failed to get oldDisplay info , result : %{public}d !", result);
362         return false;
363     }
364     if (!ret) {
365         result = proxy->IsRestrictedDefaultImeByDisplay(newDisplayId, ret);
366         if (result != ErrorCode::NO_ERROR) {
367             IMSA_HILOGE("failed to get newDisplay info , result : %{public}d !", result);
368             return false;
369         }
370     }
371     return ret;
372 }
373 
OnSetSubtype(SubProperty subProperty)374 void InputMethodAbility::OnSetSubtype(SubProperty subProperty)
375 {
376     if (imeListener_ != nullptr) {
377         imeListener_->OnSetSubtype(subProperty);
378     }
379 }
380 
OnSetInputType(InputType inputType)381 void InputMethodAbility::OnSetInputType(InputType inputType)
382 {
383     inputType_ = inputType;
384     IMSA_HILOGD("OnSetInputType, inputType = %{public}d", static_cast<int32_t>(inputType));
385     NotifyPanelStatus(false);
386 }
387 
GetInputType()388 InputType InputMethodAbility::GetInputType()
389 {
390     return inputType_;
391 }
392 
ClearDataChannel(const sptr<IRemoteObject> & channel)393 void InputMethodAbility::ClearDataChannel(const sptr<IRemoteObject> &channel)
394 {
395     std::lock_guard<std::mutex> lock(dataChannelLock_);
396     if (dataChannelObject_ == nullptr || channel == nullptr) {
397         IMSA_HILOGD("dataChannelObject_ already nullptr.");
398         return;
399     }
400     if (dataChannelObject_.GetRefPtr() == channel.GetRefPtr()) {
401         dataChannelObject_ = nullptr;
402         if (dataChannelProxyWrap_ != nullptr) {
403             dataChannelProxyWrap_->ClearRspHandlers();
404         }
405         dataChannelProxyWrap_ = nullptr;
406         IMSA_HILOGD("end.");
407     }
408 }
409 
StopInput(sptr<IRemoteObject> channelObject,uint32_t sessionId)410 int32_t InputMethodAbility::StopInput(sptr<IRemoteObject> channelObject, uint32_t sessionId)
411 {
412     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
413     int32_t cmdCount = ++cmdId_;
414     IMSA_HILOGI("IMA");
415     HideKeyboardImplWithoutLock(cmdCount, sessionId);
416     ClearBindInfo(channelObject);
417     ClearInputType();
418     if (imeListener_ != nullptr) {
419         imeListener_->OnInputFinish();
420     }
421     return ErrorCode::NO_ERROR;
422 }
423 
ClearBindInfo(const sptr<IRemoteObject> & channel)424 void InputMethodAbility::ClearBindInfo(const sptr<IRemoteObject> &channel)
425 {
426     ClearDataChannel(channel);
427     ClearInputAttribute();
428     ClearAttachOptions();
429     ClearBindClientInfo();
430 }
431 
DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent,uint64_t cbId,const sptr<IRemoteObject> & channelObject)432 int32_t InputMethodAbility::DispatchKeyEvent(
433     const std::shared_ptr<MMI::KeyEvent> &keyEvent, uint64_t cbId, const sptr<IRemoteObject> &channelObject)
434 {
435     if (keyEvent == nullptr) {
436         IMSA_HILOGE("keyEvent is nullptr!");
437         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
438     }
439     if (kdListener_ == nullptr) {
440         IMSA_HILOGE("kdListener_ is nullptr!");
441         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
442     }
443     IMSA_HILOGD("InputMethodAbility, start.");
444 
445     if (!kdListener_->OnDealKeyEvent(keyEvent, cbId, channelObject)) {
446         IMSA_HILOGE("keyEvent not deal!");
447         return ErrorCode::ERROR_DISPATCH_KEY_EVENT;
448     }
449     return ErrorCode::NO_ERROR;
450 }
451 
SetCallingWindow(uint32_t windowId)452 void InputMethodAbility::SetCallingWindow(uint32_t windowId)
453 {
454     IMSA_HILOGD("InputMethodAbility windowId: %{public}d.", windowId);
455     {
456         std::lock_guard<std::mutex> lock(inputAttrLock_);
457         inputAttribute_.windowId = windowId;
458     }
459     panels_.ForEach([windowId](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
460         panel->SetCallingWindow(windowId);
461         return false;
462     });
463     if (imeListener_ == nullptr) {
464         IMSA_HILOGD("imeListener_ is nullptr!");
465         return;
466     }
467     imeListener_->OnSetCallingWindow(windowId);
468 }
469 
OnCursorUpdate(int32_t positionX,int32_t positionY,int32_t height)470 void InputMethodAbility::OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height)
471 {
472     if (kdListener_ == nullptr) {
473         IMSA_HILOGE("kdListener_ is nullptr!");
474         return;
475     }
476     IMSA_HILOGD("x: %{public}d, y: %{public}d, height: %{public}d.", positionX, positionY, height);
477     kdListener_->OnCursorUpdate(positionX, positionY, height);
478 }
479 
OnSelectionChange(std::u16string text,int32_t oldBegin,int32_t oldEnd,int32_t newBegin,int32_t newEnd)480 void InputMethodAbility::OnSelectionChange(
481     std::u16string text, int32_t oldBegin, int32_t oldEnd, int32_t newBegin, int32_t newEnd)
482 {
483     if (kdListener_ == nullptr) {
484         IMSA_HILOGE("kdListener_ is nullptr!");
485         return;
486     }
487     kdListener_->OnTextChange(Str16ToStr8(text));
488     kdListener_->OnSelectionChange(oldBegin, oldEnd, newBegin, newEnd);
489 }
490 
OnAttributeChange(InputAttribute attribute)491 void InputMethodAbility::OnAttributeChange(InputAttribute attribute)
492 {
493     if (kdListener_ == nullptr) {
494         IMSA_HILOGE("kdListener_ is nullptr!");
495         return;
496     }
497     IMSA_HILOGD("enterKeyType: %{public}d, inputPattern: %{public}d.", attribute.enterKeyType, attribute.inputPattern);
498     attribute.bundleName = GetInputAttribute().bundleName;
499     attribute.windowId = GetInputAttribute().windowId;
500     attribute.callingDisplayId = GetInputAttribute().callingDisplayId;
501     SetInputAttribute(attribute);
502     // add for mod inputPattern when panel show
503     NotifyPanelStatus(false);
504     kdListener_->OnEditorAttributeChange(attribute);
505 }
506 
OnFunctionKey(int32_t funcKey)507 void InputMethodAbility::OnFunctionKey(int32_t funcKey)
508 {
509     if (kdListener_ == nullptr) {
510         IMSA_HILOGE("kdListener_ is nullptr!");
511         return;
512     }
513     kdListener_->OnFunctionKey(funcKey);
514 }
515 
OnStopInputService(bool isTerminateIme)516 int32_t InputMethodAbility::OnStopInputService(bool isTerminateIme)
517 {
518     IMSA_HILOGI("isTerminateIme: %{public}d.", isTerminateIme);
519     isBound_.store(false);
520     auto imeListener = GetImeListener();
521     if (imeListener == nullptr) {
522         return ErrorCode::ERROR_IME_NOT_STARTED;
523     }
524     if (isTerminateIme) {
525         isImeTerminating_.store(true);
526         return imeListener->OnInputStop();
527     }
528     return ErrorCode::NO_ERROR;
529 }
530 
OnDiscardTypingText()531 int32_t InputMethodAbility::OnDiscardTypingText()
532 {
533     auto imeListener = GetImeListener();
534     if (imeListener == nullptr) {
535         IMSA_HILOGE("imeListener is nullptr!");
536         return ErrorCode::ERROR_IME_NOT_STARTED;
537     }
538     return imeListener_->OnDiscardTypingText();
539 }
540 
HideKeyboard()541 int32_t InputMethodAbility::HideKeyboard()
542 {
543     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
544     int32_t cmdCount = ++cmdId_;
545     return HideKeyboardImplWithoutLock(cmdCount, 0);
546 }
547 
HideKeyboardImplWithoutLock(int32_t cmdId,uint32_t sessionId)548 int32_t InputMethodAbility::HideKeyboardImplWithoutLock(int32_t cmdId, uint32_t sessionId)
549 {
550     if (cmdId != cmdId_) {
551         IMSA_HILOGE("current is not last cmd cur: %{public}d, cmdId_: %{public}d!", cmdId, cmdId_);
552         return ErrorCode::NO_ERROR;
553     }
554     return HideKeyboard(Trigger::IMF, sessionId);
555 }
556 
ShowKeyboard(int32_t requestKeyboardReason)557 int32_t InputMethodAbility::ShowKeyboard(int32_t requestKeyboardReason)
558 {
559     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
560     int32_t cmdCount = ++cmdId_;
561     HandleRequestKeyboardReasonChanged(static_cast<RequestKeyboardReason>(requestKeyboardReason));
562     return ShowKeyboardImplWithoutLock(cmdCount);
563 }
564 
ShowKeyboardImplWithLock(int32_t cmdId)565 int32_t InputMethodAbility::ShowKeyboardImplWithLock(int32_t cmdId)
566 {
567     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
568     return ShowKeyboardImplWithoutLock(cmdId);
569 }
570 
ShowKeyboardImplWithoutLock(int32_t cmdId)571 int32_t InputMethodAbility::ShowKeyboardImplWithoutLock(int32_t cmdId)
572 {
573     if (cmdId != cmdId_) {
574         IMSA_HILOGE("current is not last cmd cur: %{public}d, cmdId_: %{public}d!", cmdId, cmdId_);
575         return ErrorCode::NO_ERROR;
576     }
577     if (imeListener_ == nullptr) {
578         IMSA_HILOGE("imeListener is nullptr!");
579         return ErrorCode::ERROR_IME;
580     }
581     IMSA_HILOGI("IMA start.");
582     if (panels_.Contains(SOFT_KEYBOARD)) {
583         auto panel = GetSoftKeyboardPanel();
584         if (panel == nullptr) {
585             IMSA_HILOGE("panel is nullptr!");
586             return ErrorCode::ERROR_IME;
587         }
588         auto flag = panel->GetPanelFlag();
589         imeListener_->OnKeyboardStatus(true);
590         if (flag == FLG_CANDIDATE_COLUMN) {
591             IMSA_HILOGI("panel flag is candidate, no need to show.");
592             NotifyKeyboardHeight(0, flag);
593             return ErrorCode::NO_ERROR;
594         }
595         return ShowPanel(panel, flag, Trigger::IMF);
596     }
597     isShowAfterCreate_.store(true);
598     IMSA_HILOGI("panel not create.");
599     auto channel = GetInputDataChannelProxy();
600     if (channel != nullptr) {
601         channel->SendKeyboardStatus(static_cast<int32_t>(KeyboardStatus::SHOW));
602     }
603     imeListener_->OnKeyboardStatus(true);
604     return ErrorCode::NO_ERROR;
605 }
606 
NotifyPanelStatusInfo(const PanelStatusInfo & info)607 void InputMethodAbility::NotifyPanelStatusInfo(const PanelStatusInfo &info)
608 {
609     // CANDIDATE_COLUMN not notify
610     auto channel = GetInputDataChannelProxy();
611     NotifyPanelStatusInfo(info, channel);
612 }
613 
InvokeStartInputCallbackWithInfoRestruct(const TextTotalConfig & textConfig,bool isNotifyInputStart)614 int32_t InputMethodAbility::InvokeStartInputCallbackWithInfoRestruct(
615     const TextTotalConfig &textConfig, bool isNotifyInputStart)
616 {
617     TextTotalConfig newTextConfig = {};
618     int32_t ret = GetTextConfig(newTextConfig);
619     if (ret == ErrorCode::NO_ERROR) {
620         newTextConfig.inputAttribute.bundleName = textConfig.inputAttribute.bundleName;
621         newTextConfig.inputAttribute.callingDisplayId = textConfig.inputAttribute.callingDisplayId;
622         newTextConfig.inputAttribute.windowId = textConfig.inputAttribute.windowId;
623         newTextConfig.isSimpleKeyboardEnabled = textConfig.isSimpleKeyboardEnabled;
624         return InvokeStartInputCallback(newTextConfig, isNotifyInputStart);
625     }
626     IMSA_HILOGW("failed to get text config, ret: %{public}d.", ret);
627     if (imeListener_ == nullptr) {
628         IMSA_HILOGE("imeListener_ is nullptr!");
629         return ErrorCode::ERROR_IME;
630     }
631     if (isNotifyInputStart) {
632         imeListener_->OnInputStart();
633     }
634     return ErrorCode::NO_ERROR;
635 }
636 
InvokeStartInputCallback(const TextTotalConfig & textConfig,bool isNotifyInputStart)637 int32_t InputMethodAbility::InvokeStartInputCallback(const TextTotalConfig &textConfig, bool isNotifyInputStart)
638 {
639     if (imeListener_ == nullptr) {
640         IMSA_HILOGE("imeListener_ is nullptr!");
641         return ErrorCode::ERROR_IME;
642     }
643     positionY_ = textConfig.positionY;
644     height_ = textConfig.height;
645     NotifyInfoToWmsInStartInput(textConfig);
646     SetInputAttribute(textConfig.inputAttribute);
647     if (kdListener_ != nullptr) {
648         kdListener_->OnEditorAttributeChange(textConfig.inputAttribute);
649     }
650     AttachOptions options;
651     options.requestKeyboardReason = textConfig.requestKeyboardReason;
652     options.isSimpleKeyboardEnabled = textConfig.isSimpleKeyboardEnabled;
653     InvokeAttachOptionsCallback(options, isNotifyInputStart || !isInputStartNotified_);
654     if (isNotifyInputStart || !isInputStartNotified_) {
655         isInputStartNotified_ = true;
656         IMSA_HILOGD("OnInputStart begin");
657         imeListener_->OnInputStart();
658     }
659     if (TextConfig::IsPrivateCommandValid(textConfig.privateCommand) && IsDefaultIme()) {
660         IMSA_HILOGD("notify privateCommand.");
661         imeListener_->ReceivePrivateCommand(textConfig.privateCommand);
662     }
663     if (kdListener_ != nullptr) {
664         if (textConfig.cursorInfo.left != INVALID_CURSOR_VALUE) {
665             kdListener_->OnCursorUpdate(
666                 textConfig.cursorInfo.left, textConfig.cursorInfo.top, textConfig.cursorInfo.height);
667         }
668         if (textConfig.textSelection.newBegin == INVALID_SELECTION_VALUE ||
669             (textConfig.textSelection.newBegin == textConfig.textSelection.oldBegin &&
670                 textConfig.textSelection.newEnd == textConfig.textSelection.oldEnd)) {
671             IMSA_HILOGD("invalid selection or no selection change");
672         } else {
673             kdListener_->OnSelectionChange(textConfig.textSelection.oldBegin, textConfig.textSelection.oldEnd,
674                 textConfig.textSelection.newBegin, textConfig.textSelection.newEnd);
675         }
676     }
677     if (textConfig.windowId != INVALID_WINDOW_ID) {
678         imeListener_->OnSetCallingWindow(textConfig.windowId);
679     }
680     return ErrorCode::NO_ERROR;
681 }
682 
HandleRequestKeyboardReasonChanged(const RequestKeyboardReason & requestKeyboardReason)683 void InputMethodAbility::HandleRequestKeyboardReasonChanged(const RequestKeyboardReason &requestKeyboardReason)
684 {
685     AttachOptions options;
686     options.requestKeyboardReason = requestKeyboardReason;
687     options.isSimpleKeyboardEnabled = GetAttachOptions().isSimpleKeyboardEnabled;
688     InvokeAttachOptionsCallback(options);
689 }
690 
InvokeAttachOptionsCallback(const AttachOptions & options,bool isFirstNotify)691 void InputMethodAbility::InvokeAttachOptionsCallback(const AttachOptions &options, bool isFirstNotify)
692 {
693     auto oldOptions = GetAttachOptions();
694     if (!isFirstNotify && oldOptions.isSimpleKeyboardEnabled == options.isSimpleKeyboardEnabled
695         && options.requestKeyboardReason == oldOptions.requestKeyboardReason) {
696         return;
697     }
698     SetAttachOptions(options);
699     if (textInputClientListener_ != nullptr) {
700         textInputClientListener_->OnAttachOptionsChanged(options);
701     }
702 }
703 
SetAttachOptions(const AttachOptions & options)704 void InputMethodAbility::SetAttachOptions(const AttachOptions &options)
705 {
706     std::lock_guard<std::mutex> lock(attachOptionsLock_);
707     attachOptions_ = options;
708 }
709 
ClearAttachOptions()710 void InputMethodAbility::ClearAttachOptions()
711 {
712     std::lock_guard<std::mutex> lock(attachOptionsLock_);
713     attachOptions_ = {};
714 }
715 
GetAttachOptions()716 AttachOptions InputMethodAbility::GetAttachOptions()
717 {
718     std::lock_guard<std::mutex> lock(attachOptionsLock_);
719     return attachOptions_;
720 }
721 
InsertTextInner(const std::string & text,const AsyncIpcCallBack & callback)722 int32_t InputMethodAbility::InsertTextInner(const std::string &text, const AsyncIpcCallBack &callback)
723 {
724     InputMethodSyncTrace tracer("IMA_InsertText");
725     IMSA_HILOGD("InputMethodAbility start.");
726     auto channel = GetInputDataChannelProxyWrap();
727     if (channel == nullptr) {
728         IMSA_HILOGE("channel is nullptr!");
729         return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
730     }
731 
732     return channel->InsertText(text, callback);
733 }
734 
DeleteForwardInner(int32_t length,const AsyncIpcCallBack & callback)735 int32_t InputMethodAbility::DeleteForwardInner(int32_t length, const AsyncIpcCallBack &callback)
736 {
737     InputMethodSyncTrace tracer("IMA_DeleteForward");
738     IMSA_HILOGD("InputMethodAbility start, length: %{public}d.", length);
739     auto channel = GetInputDataChannelProxyWrap();
740     if (channel == nullptr) {
741         IMSA_HILOGE("channel is nullptr!");
742         return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
743     }
744     return channel->DeleteForward(length, callback);
745 }
746 
DeleteBackwardInner(int32_t length,const AsyncIpcCallBack & callback)747 int32_t InputMethodAbility::DeleteBackwardInner(int32_t length, const AsyncIpcCallBack &callback)
748 {
749     IMSA_HILOGD("InputMethodAbility start, length: %{public}d.", length);
750     auto channel = GetInputDataChannelProxyWrap();
751     if (channel == nullptr) {
752         IMSA_HILOGE("channel is nullptr!");
753         return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
754     }
755     return channel->DeleteBackward(length, callback);
756 }
757 
SendFunctionKey(int32_t funcKey,const AsyncIpcCallBack & callback)758 int32_t InputMethodAbility::SendFunctionKey(int32_t funcKey, const AsyncIpcCallBack &callback)
759 {
760     auto channel = GetInputDataChannelProxyWrap();
761     if (channel == nullptr) {
762         IMSA_HILOGE("channel is nullptr!");
763         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
764     }
765     return channel->SendFunctionKey(funcKey, callback);
766 }
767 
HideKeyboardSelf()768 int32_t InputMethodAbility::HideKeyboardSelf()
769 {
770     // Current Ime is exiting, hide softkeyboard will cause the TextFiled to lose focus.
771     if (isImeTerminating_.load()) {
772         IMSA_HILOGI("Current Ime is terminating, no need to hide keyboard.");
773         return ErrorCode::NO_ERROR;
774     }
775     InputMethodSyncTrace tracer("IMA_HideKeyboardSelf start.");
776     auto ret = HideKeyboard(Trigger::IME_APP, 0);
777     if (ret == ErrorCode::NO_ERROR) {
778         InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_SELF);
779     }
780     return ret == ErrorCode::ERROR_CLIENT_NULL_POINTER ? ret : ErrorCode::NO_ERROR;
781 }
782 
SendExtendAction(int32_t action,const AsyncIpcCallBack & callback)783 int32_t InputMethodAbility::SendExtendAction(int32_t action, const AsyncIpcCallBack &callback)
784 {
785     IMSA_HILOGD("InputMethodAbility, action: %{public}d.", action);
786     auto channel = GetInputDataChannelProxyWrap();
787     if (channel == nullptr) {
788         IMSA_HILOGE("channel is nullptr!");
789         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
790     }
791     return channel->HandleExtendAction(action, callback);
792 }
793 
GetTextBeforeCursorInner(int32_t number,std::u16string & text,const AsyncIpcCallBack & callback)794 int32_t InputMethodAbility::GetTextBeforeCursorInner(
795     int32_t number, std::u16string &text, const AsyncIpcCallBack &callback)
796 {
797     InputMethodSyncTrace tracer("IMA_GetForward");
798     IMSA_HILOGD("InputMethodAbility, number: %{public}d.", number);
799     auto channel = GetInputDataChannelProxyWrap();
800     if (channel == nullptr) {
801         IMSA_HILOGE("channel is nullptr!");
802         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
803     }
804     std::string textu8 = "";
805     auto ret = channel->GetTextBeforeCursor(number, textu8, callback);
806     text = Str8ToStr16(textu8);
807     return ret;
808 }
809 
GetTextAfterCursorInner(int32_t number,std::u16string & text,const AsyncIpcCallBack & callback)810 int32_t InputMethodAbility::GetTextAfterCursorInner(
811     int32_t number, std::u16string &text, const AsyncIpcCallBack &callback)
812 {
813     InputMethodSyncTrace tracer("IMA_GetTextAfterCursor");
814     IMSA_HILOGD("InputMethodAbility, number: %{public}d.", number);
815     auto channel = GetInputDataChannelProxyWrap();
816     if (channel == nullptr) {
817         IMSA_HILOGE("channel is nullptr!");
818         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
819     }
820     std::string textu8 = "";
821     auto ret = channel->GetTextAfterCursor(number, textu8, callback);
822     text = Str8ToStr16(textu8);
823     return ret;
824 }
825 
MoveCursor(int32_t keyCode,const AsyncIpcCallBack & callback)826 int32_t InputMethodAbility::MoveCursor(int32_t keyCode, const AsyncIpcCallBack &callback)
827 {
828     IMSA_HILOGD("InputMethodAbility, keyCode: %{public}d.", keyCode);
829     auto channel = GetInputDataChannelProxyWrap();
830     if (channel == nullptr) {
831         IMSA_HILOGE("channel is nullptr!");
832         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
833     }
834     return channel->MoveCursor(keyCode, callback);
835 }
836 
SelectByRange(int32_t start,int32_t end,const AsyncIpcCallBack & callback)837 int32_t InputMethodAbility::SelectByRange(int32_t start, int32_t end, const AsyncIpcCallBack &callback)
838 {
839     IMSA_HILOGD("InputMethodAbility, start: %{public}d, end: %{public}d", start, end);
840     if (start < 0 || end < 0) {
841         IMSA_HILOGE("check parameter failed, start: %{public}d, end: %{public}d!", start, end);
842         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
843     }
844     auto dataChannel = GetInputDataChannelProxyWrap();
845     if (dataChannel == nullptr) {
846         IMSA_HILOGE("datachannel is nullptr!");
847         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
848     }
849     return dataChannel->SelectByRange(start, end, callback);
850 }
851 
SelectByMovement(int32_t direction,const AsyncIpcCallBack & callback)852 int32_t InputMethodAbility::SelectByMovement(int32_t direction, const AsyncIpcCallBack &callback)
853 {
854     IMSA_HILOGD("InputMethodAbility, direction: %{public}d.", direction);
855     auto dataChannel = GetInputDataChannelProxyWrap();
856     if (dataChannel == nullptr) {
857         IMSA_HILOGE("datachannel is nullptr!");
858         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
859     }
860     return dataChannel->SelectByMovement(direction, 0, callback);
861 }
862 
GetEnterKeyType(int32_t & keyType)863 int32_t InputMethodAbility::GetEnterKeyType(int32_t &keyType)
864 {
865     IMSA_HILOGD("InputMethodAbility start.");
866     auto channel = GetInputDataChannelProxy();
867     if (channel == nullptr) {
868         IMSA_HILOGE("channel is nullptr!");
869         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
870     }
871     return channel->GetEnterKeyType(keyType);
872 }
873 
GetInputPattern(int32_t & inputPattern)874 int32_t InputMethodAbility::GetInputPattern(int32_t &inputPattern)
875 {
876     IMSA_HILOGD("InputMethodAbility start.");
877     auto channel = GetInputDataChannelProxy();
878     if (channel == nullptr) {
879         IMSA_HILOGE("channel is nullptr!");
880         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
881     }
882     return channel->GetInputPattern(inputPattern);
883 }
884 
GetTextIndexAtCursorInner(int32_t & index,const AsyncIpcCallBack & callback)885 int32_t InputMethodAbility::GetTextIndexAtCursorInner(int32_t &index, const AsyncIpcCallBack &callback)
886 {
887     IMSA_HILOGD("InputMethodAbility start.");
888     auto channel = GetInputDataChannelProxyWrap();
889     if (channel == nullptr) {
890         IMSA_HILOGE("channel is nullptr!");
891         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
892     }
893     return channel->GetTextIndexAtCursor(index, callback);
894 }
895 
GetTextConfig(TextTotalConfig & textConfig)896 int32_t InputMethodAbility::GetTextConfig(TextTotalConfig &textConfig)
897 {
898     IMSA_HILOGD("InputMethodAbility start.");
899     auto channel = GetInputDataChannelProxy();
900     if (channel == nullptr) {
901         IMSA_HILOGE("channel is nullptr!");
902         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
903     }
904     TextTotalConfigInner textConfigInner = InputMethodTools::GetInstance().TextTotalConfigToInner(textConfig);
905     auto ret = channel->GetTextConfig(textConfigInner);
906     if (ret == ErrorCode::NO_ERROR) {
907         textConfig = InputMethodTools::GetInstance().InnerToTextTotalConfig(textConfigInner);
908         textConfig.inputAttribute.bundleName = GetInputAttribute().bundleName;
909         textConfig.inputAttribute.callingDisplayId = GetInputAttribute().callingDisplayId;
910         textConfig.inputAttribute.windowId = GetInputAttribute().windowId;
911     }
912     return ret;
913 }
914 
SetInputDataChannel(const sptr<IRemoteObject> & object)915 void InputMethodAbility::SetInputDataChannel(const sptr<IRemoteObject> &object)
916 {
917     IMSA_HILOGD("SetInputDataChannel start.");
918     std::lock_guard<std::mutex> lock(dataChannelLock_);
919     if (dataChannelObject_ != nullptr && object != nullptr && object.GetRefPtr() == dataChannelObject_.GetRefPtr()) {
920         IMSA_HILOGD("datachannel has already been set.");
921         return;
922     }
923     auto channelProxy = std::make_shared<InputDataChannelProxy>(object);
924     if (channelProxy == nullptr) {
925         IMSA_HILOGE("failed to create channel proxy!");
926         return;
927     }
928     sptr<IRemoteObject> agentObject = nullptr;
929     if (agentStub_ != nullptr) {
930         agentObject = agentStub_->AsObject();
931     }
932     auto channelWrap = std::make_shared<InputDataChannelProxyWrap>(channelProxy, agentObject);
933     if (channelWrap == nullptr) {
934         IMSA_HILOGE("failed to create channel wrap!");
935         return;
936     }
937     if (dataChannelProxyWrap_ != nullptr) {
938         dataChannelProxyWrap_->ClearRspHandlers();
939     }
940     dataChannelProxyWrap_ = channelWrap;
941     dataChannelObject_ = object;
942 }
943 
NotifyInfoToWmsInStartInput(const TextTotalConfig & textConfig)944 bool InputMethodAbility::NotifyInfoToWmsInStartInput(const TextTotalConfig &textConfig)
945 {
946     auto imeListener = GetImeListener();
947     if (imeListener == nullptr) {
948         IMSA_HILOGE("imeListener is nullptr!");
949         return false;
950     }
951     auto task = [this, textConfig]() {
952         panels_.ForEach([&textConfig](const PanelType &type, const std::shared_ptr<InputMethodPanel> &panel) {
953             if (panel == nullptr) {
954                 return false;
955             }
956             if (type == SOFT_KEYBOARD && panel->GetPanelFlag() == FLG_FIXED && panel->IsShowing()) {
957                 panel->SetTextFieldAvoidInfo(textConfig.positionY, textConfig.height);
958             }
959             panel->SetCallingWindow(textConfig.windowId);
960             return false;
961         });
962     };
963     return imeListener->PostTaskToEventHandler(task, "NotifyInfoToWms");
964 }
965 
GetInputDataChannelProxyWrap()966 std::shared_ptr<InputDataChannelProxyWrap> InputMethodAbility::GetInputDataChannelProxyWrap()
967 {
968     if (imeMirrorMgr_.IsImeMirrorEnable()) {
969         IMSA_HILOGW("[ImeMirrorTag] not allow send to data channel");
970         return nullptr;
971     }
972     std::lock_guard<std::mutex> lock(dataChannelLock_);
973     return dataChannelProxyWrap_;
974 }
975 
GetInputDataChannelProxy()976 std::shared_ptr<InputDataChannelProxy> InputMethodAbility::GetInputDataChannelProxy()
977 {
978     auto channel = GetInputDataChannelProxyWrap();
979     if (channel == nullptr) {
980         return nullptr;
981     }
982     return channel->GetDataChannel();
983 }
984 
SetInputControlChannel(sptr<IRemoteObject> & object)985 void InputMethodAbility::SetInputControlChannel(sptr<IRemoteObject> &object)
986 {
987     IMSA_HILOGD("SetInputControlChannel start.");
988     std::lock_guard<std::mutex> lock(controlChannelLock_);
989     std::shared_ptr<InputControlChannelProxy> channelProxy = std::make_shared<InputControlChannelProxy>(object);
990     if (channelProxy == nullptr) {
991         IMSA_HILOGD("channelProxy is nullptr!");
992         return;
993     }
994     controlChannel_ = channelProxy;
995 }
996 
ClearInputControlChannel()997 void InputMethodAbility::ClearInputControlChannel()
998 {
999     std::lock_guard<std::mutex> lock(controlChannelLock_);
1000     controlChannel_ = nullptr;
1001 }
1002 
GetInputControlChannel()1003 std::shared_ptr<InputControlChannelProxy> InputMethodAbility::GetInputControlChannel()
1004 {
1005     std::lock_guard<std::mutex> lock(controlChannelLock_);
1006     return controlChannel_;
1007 }
1008 
OnRemoteSaDied(const wptr<IRemoteObject> & object)1009 void InputMethodAbility::OnRemoteSaDied(const wptr<IRemoteObject> &object)
1010 {
1011     IMSA_HILOGI("input method service died.");
1012     isBound_.store(false);
1013     ClearDataChannel(dataChannelObject_);
1014     ClearInputControlChannel();
1015     ClearSystemCmdChannel();
1016     {
1017         std::lock_guard<std::mutex> lock(abilityLock_);
1018         abilityManager_ = nullptr;
1019     }
1020     if (imeListener_ != nullptr) {
1021         imeListener_->OnInputStop();
1022     }
1023 }
1024 
GetSecurityMode(int32_t & security)1025 int32_t InputMethodAbility::GetSecurityMode(int32_t &security)
1026 {
1027     IMSA_HILOGI("InputMethodAbility start.");
1028     int32_t securityMode = securityMode_.load();
1029     if (securityMode != static_cast<int32_t>(INVALID_SECURITY_MODE)) {
1030         IMSA_HILOGD("Get cache security mode: %{public}d.", securityMode);
1031         security = securityMode;
1032         return ErrorCode::NO_ERROR;
1033     }
1034     auto proxy = GetImsaProxy();
1035     if (proxy == nullptr) {
1036         IMSA_HILOGE("Imsa proxy is nullptr!");
1037         return ErrorCode::ERROR_NULL_POINTER;
1038     }
1039     auto ret = proxy->GetSecurityMode(security);
1040     if (ret == ErrorCode::NO_ERROR) {
1041         securityMode_.store(security);
1042     }
1043     return ret;
1044 }
1045 
ClearSystemCmdChannel()1046 void InputMethodAbility::ClearSystemCmdChannel()
1047 {
1048     std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
1049     if (systemCmdChannelProxy_ == nullptr) {
1050         IMSA_HILOGD("systemCmdChannelProxy_ already nullptr.");
1051         return;
1052     }
1053     systemCmdChannelProxy_ = nullptr;
1054     IMSA_HILOGD("end.");
1055 }
1056 
GetSystemCmdChannelProxy()1057 sptr<SystemCmdChannelProxy> InputMethodAbility::GetSystemCmdChannelProxy()
1058 {
1059     std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
1060     return systemCmdChannelProxy_;
1061 }
1062 
OnConnectSystemCmd(const sptr<IRemoteObject> & channel,sptr<IRemoteObject> & agent)1063 int32_t InputMethodAbility::OnConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)
1064 {
1065     IMSA_HILOGD("InputMethodAbility start.");
1066     sptr<InputMethodAgentServiceImpl> agentImpl = new (std::nothrow) InputMethodAgentServiceImpl();
1067     if (agentImpl == nullptr) {
1068         IMSA_HILOGE("failed to create agent!");
1069         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1070     }
1071     sptr<SystemCmdChannelProxy> cmdChannel = new (std::nothrow) SystemCmdChannelProxy(channel);
1072     if (cmdChannel == nullptr) {
1073         IMSA_HILOGE("failed to create channel proxy!");
1074         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1075     }
1076     {
1077         std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
1078         systemCmdChannelProxy_ = cmdChannel;
1079         systemAgentStub_ = agentImpl;
1080     }
1081     agent = agentImpl->AsObject();
1082     auto panel = GetSoftKeyboardPanel();
1083     if (panel != nullptr) {
1084         auto flag = panel->GetPanelFlag();
1085         if (flag != FLG_CANDIDATE_COLUMN) {
1086             NotifyPanelStatus(false);
1087         }
1088     }
1089     return ErrorCode::NO_ERROR;
1090 }
1091 
OnSecurityChange(int32_t security)1092 int32_t InputMethodAbility::OnSecurityChange(int32_t security)
1093 {
1094     IMSA_HILOGI("InputMethodAbility start.");
1095     securityMode_.store(security);
1096     if (imeListener_ == nullptr) {
1097         IMSA_HILOGE("imeListener_ is nullptr!");
1098         return ErrorCode::ERROR_BAD_PARAMETERS;
1099     }
1100     imeListener_->OnSecurityChange(security);
1101     return ErrorCode::NO_ERROR;
1102 }
1103 
AdjustKeyboard()1104 int32_t InputMethodAbility::AdjustKeyboard()
1105 {
1106     if (panels_.Contains(SOFT_KEYBOARD)) {
1107         auto panel = GetSoftKeyboardPanel();
1108         if (panel == nullptr) {
1109             IMSA_HILOGE("panel is nullptr!");
1110             return ErrorCode::ERROR_IME;
1111         }
1112         auto flag = panel->GetPanelFlag();
1113         if (flag != FLG_FIXED) {
1114             IMSA_HILOGI("panel flag is not fix, no need to adjust.");
1115             return ErrorCode::NO_ERROR;
1116         }
1117         return panel->AdjustKeyboard();
1118     }
1119     return ErrorCode::NO_ERROR;
1120 }
1121 
CreatePanel(const std::shared_ptr<AbilityRuntime::Context> & context,const PanelInfo & panelInfo,std::shared_ptr<InputMethodPanel> & inputMethodPanel)1122 int32_t InputMethodAbility::CreatePanel(const std::shared_ptr<AbilityRuntime::Context> &context,
1123     const PanelInfo &panelInfo, std::shared_ptr<InputMethodPanel> &inputMethodPanel)
1124 {
1125     IMSA_HILOGI("InputMethodAbility start.");
1126     auto panelHeightCallback = [this](uint32_t panelHeight, PanelFlag panelFlag) {
1127         NotifyKeyboardHeight(panelHeight, panelFlag);
1128     };
1129     auto flag = panels_.ComputeIfAbsent(panelInfo.panelType,
1130         [panelHeightCallback, &panelInfo, &context, &inputMethodPanel](
1131             const PanelType &panelType, std::shared_ptr<InputMethodPanel> &panel) {
1132             inputMethodPanel = std::make_shared<InputMethodPanel>();
1133             inputMethodPanel->SetPanelHeightCallback(panelHeightCallback);
1134             auto ret = inputMethodPanel->CreatePanel(context, panelInfo);
1135             if (ret == ErrorCode::NO_ERROR) {
1136                 panel = inputMethodPanel;
1137                 return true;
1138             }
1139             inputMethodPanel = nullptr;
1140             return false;
1141         });
1142     if (flag && isShowAfterCreate_.load() && panelInfo.panelType == SOFT_KEYBOARD
1143         && panelInfo.panelFlag != FLG_CANDIDATE_COLUMN) {
1144         isShowAfterCreate_.store(false);
1145         auto task = std::make_shared<TaskImsaShowKeyboard>();
1146         TaskManager::GetInstance().PostTask(task);
1147     }
1148     return flag ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL;
1149 }
1150 
DestroyPanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel)1151 int32_t InputMethodAbility::DestroyPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
1152 {
1153     IMSA_HILOGI("InputMethodAbility start.");
1154     if (inputMethodPanel == nullptr) {
1155         IMSA_HILOGE("panel is nullptr!");
1156         return ErrorCode::ERROR_BAD_PARAMETERS;
1157     }
1158     auto ret = inputMethodPanel->DestroyPanel();
1159     if (ret == ErrorCode::NO_ERROR) {
1160         PanelType panelType = inputMethodPanel->GetPanelType();
1161         panels_.Erase(panelType);
1162     }
1163     return ret;
1164 }
1165 
ShowPanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel)1166 int32_t InputMethodAbility::ShowPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
1167 {
1168     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
1169     if (inputMethodPanel == nullptr) {
1170         return ErrorCode::ERROR_BAD_PARAMETERS;
1171     }
1172     return ShowPanel(inputMethodPanel, inputMethodPanel->GetPanelFlag(), Trigger::IME_APP);
1173 }
1174 
HidePanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel)1175 int32_t InputMethodAbility::HidePanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
1176 {
1177     if (inputMethodPanel == nullptr) {
1178         return ErrorCode::ERROR_BAD_PARAMETERS;
1179     }
1180     // Current Ime is exiting, hide softkeyboard will cause the TextFiled to lose focus.
1181     if (isImeTerminating_.load() && inputMethodPanel->GetPanelType() == PanelType::SOFT_KEYBOARD) {
1182         IMSA_HILOGI("Current Ime is terminating, no need to hide keyboard.");
1183         return ErrorCode::NO_ERROR;
1184     }
1185     if (isShowAfterCreate_.load() && inputMethodPanel->GetPanelType() == PanelType::SOFT_KEYBOARD
1186         && inputMethodPanel->GetPanelFlag() != PanelFlag::FLG_CANDIDATE_COLUMN) {
1187         isShowAfterCreate_.store(false);
1188     }
1189     std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
1190     return HidePanel(inputMethodPanel, inputMethodPanel->GetPanelFlag(), Trigger::IME_APP, 0);
1191 }
1192 
ShowPanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel,PanelFlag flag,Trigger trigger)1193 int32_t InputMethodAbility::ShowPanel(
1194     const std::shared_ptr<InputMethodPanel> &inputMethodPanel, PanelFlag flag, Trigger trigger)
1195 {
1196     if (inputMethodPanel == nullptr) {
1197         return ErrorCode::ERROR_IMA_NULLPTR;
1198     }
1199     if (trigger == Trigger::IME_APP && GetInputDataChannelProxyWrap() == nullptr) {
1200         IMSA_HILOGE("channel is nullptr!");
1201         return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
1202     }
1203     if (flag == FLG_FIXED && inputMethodPanel->GetPanelType() == SOFT_KEYBOARD) {
1204         auto ret = inputMethodPanel->SetTextFieldAvoidInfo(positionY_, height_);
1205         if (ret != ErrorCode::NO_ERROR) {
1206             IMSA_HILOGE("failed to set keyBoard, ret: %{public}d!", ret);
1207         }
1208     }
1209     auto ret = inputMethodPanel->ShowPanel();
1210     if (ret == ErrorCode::NO_ERROR) {
1211         NotifyPanelStatus(false);
1212         PanelStatusInfo info;
1213         info.panelInfo.panelType = inputMethodPanel->GetPanelType();
1214         info.panelInfo.panelFlag = flag;
1215         info.visible = true;
1216         info.trigger = trigger;
1217         NotifyPanelStatusInfo(info);
1218     }
1219     return ret;
1220 }
1221 
HidePanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel,PanelFlag flag,Trigger trigger,uint32_t sessionId)1222 int32_t InputMethodAbility::HidePanel(
1223     const std::shared_ptr<InputMethodPanel> &inputMethodPanel, PanelFlag flag, Trigger trigger, uint32_t sessionId)
1224 {
1225     if (inputMethodPanel == nullptr) {
1226         return ErrorCode::ERROR_BAD_PARAMETERS;
1227     }
1228     auto ret = inputMethodPanel->HidePanel();
1229     if (ret != ErrorCode::NO_ERROR) {
1230         IMSA_HILOGD("failed, ret: %{public}d", ret);
1231         return ret;
1232     }
1233     PanelStatusInfo info;
1234     info.panelInfo.panelType = inputMethodPanel->GetPanelType();
1235     info.panelInfo.panelFlag = flag;
1236     info.visible = false;
1237     info.trigger = trigger;
1238     info.sessionId = sessionId;
1239     NotifyPanelStatusInfo(info);
1240     if (trigger == Trigger::IMF && inputMethodPanel->GetPanelType() == PanelType::SOFT_KEYBOARD) {
1241         AsyncIpcCallBack callback = [](int32_t code, const ResponseData &data) {};
1242         FinishTextPreview(callback);
1243     }
1244     return ErrorCode::NO_ERROR;
1245 }
1246 
NotifyPanelStatus(bool isUseParameterFlag,PanelFlag panelFlag)1247 int32_t InputMethodAbility::NotifyPanelStatus(bool isUseParameterFlag, PanelFlag panelFlag)
1248 {
1249     auto panel = GetSoftKeyboardPanel();
1250     if (panel == nullptr) {
1251         IMSA_HILOGE("panel is null");
1252         return ErrorCode::ERROR_NULL_POINTER;
1253     }
1254     auto keyboardSize = panel->GetKeyboardSize();
1255     PanelFlag curPanelFlag = isUseParameterFlag ? panelFlag : panel->GetPanelFlag();
1256     SysPanelStatus sysPanelStatus = { inputType_, curPanelFlag, keyboardSize.width, keyboardSize.height };
1257     if (!panel->IsInMainDisplay()) {
1258         sysPanelStatus.isPanelRaised = false;
1259         sysPanelStatus.needFuncButton = false;
1260     }
1261     if (GetAttachOptions().isSimpleKeyboardEnabled && IsDefaultIme() && !GetInputAttribute().IsOneTimeCodeFlag()) {
1262         sysPanelStatus.needFuncButton = false;
1263     }
1264     auto systemChannel = GetSystemCmdChannelProxy();
1265     if (systemChannel == nullptr) {
1266         IMSA_HILOGE("channel is nullptr!");
1267         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1268     }
1269     return systemChannel->NotifyPanelStatus(sysPanelStatus);
1270 }
1271 
SetInputAttribute(const InputAttribute & inputAttribute)1272 void InputMethodAbility::SetInputAttribute(const InputAttribute &inputAttribute)
1273 {
1274     std::lock_guard<std::mutex> lock(inputAttrLock_);
1275     inputAttribute_ = inputAttribute;
1276 }
1277 
ClearInputAttribute()1278 void InputMethodAbility::ClearInputAttribute()
1279 {
1280     std::lock_guard<std::mutex> lock(inputAttrLock_);
1281     inputAttribute_ = {};
1282 }
1283 
GetInputAttribute()1284 InputAttribute InputMethodAbility::GetInputAttribute()
1285 {
1286     std::lock_guard<std::mutex> lock(inputAttrLock_);
1287     return inputAttribute_;
1288 }
1289 
HideKeyboard(Trigger trigger,uint32_t sessionId)1290 int32_t InputMethodAbility::HideKeyboard(Trigger trigger, uint32_t sessionId)
1291 {
1292     isShowAfterCreate_.store(false);
1293     InputMethodSyncTrace tracer("IMA_HideKeyboard");
1294     if (imeListener_ == nullptr) {
1295         IMSA_HILOGE("imeListener_ is nullptr!");
1296         return ErrorCode::ERROR_IME;
1297     }
1298     IMSA_HILOGD("IMA, trigger: %{public}d.", static_cast<int32_t>(trigger));
1299     if (panels_.Contains(SOFT_KEYBOARD)) {
1300         auto panel = GetSoftKeyboardPanel();
1301         if (panel == nullptr) {
1302             IMSA_HILOGE("panel is nullptr!");
1303             return ErrorCode::ERROR_IME;
1304         }
1305         auto flag = panel->GetPanelFlag();
1306         imeListener_->OnKeyboardStatus(false);
1307         if (flag == FLG_CANDIDATE_COLUMN) {
1308             IMSA_HILOGI("panel flag is candidate, no need to hide.");
1309             return ErrorCode::NO_ERROR;
1310         }
1311         return HidePanel(panel, flag, trigger, sessionId);
1312     }
1313     IMSA_HILOGI("panel is not created.");
1314     imeListener_->OnKeyboardStatus(false);
1315     auto channel = GetInputDataChannelProxy();
1316     if (channel != nullptr) {
1317         channel->SendKeyboardStatus(static_cast<int32_t>(KeyboardStatus::HIDE));
1318     }
1319     auto controlChannel = GetInputControlChannel();
1320     if (controlChannel != nullptr && trigger == Trigger::IME_APP) {
1321         controlChannel->HideKeyboardSelf();
1322     }
1323     return ErrorCode::NO_ERROR;
1324 }
1325 
GetSoftKeyboardPanel()1326 std::shared_ptr<InputMethodPanel> InputMethodAbility::GetSoftKeyboardPanel()
1327 {
1328     auto result = panels_.Find(SOFT_KEYBOARD);
1329     if (!result.first) {
1330         return nullptr;
1331     }
1332     auto panel = result.second;
1333     if (!BlockRetry(FIND_PANEL_RETRY_INTERVAL, MAX_RETRY_TIMES, [panel]() -> bool {
1334             return panel != nullptr && panel->windowId_ != InputMethodPanel::INVALID_WINDOW_ID;
1335         })) {
1336         return nullptr;
1337     }
1338     return panel;
1339 }
1340 
IsCurrentIme()1341 bool InputMethodAbility::IsCurrentIme()
1342 {
1343     IMSA_HILOGD("InputMethodAbility start.");
1344     if (isCurrentIme_) {
1345         return true;
1346     }
1347     std::lock_guard<std::mutex> lock(imeCheckMutex_);
1348     if (isCurrentIme_) {
1349         return true;
1350     }
1351     auto proxy = GetImsaProxy();
1352     if (proxy == nullptr) {
1353         IMSA_HILOGE("failed to get imsa proxy!");
1354         return false;
1355     }
1356 
1357     bool ret = false;
1358     proxy->IsCurrentIme(ret);
1359     if (ret) {
1360         isCurrentIme_ = true;
1361     }
1362     return ret;
1363 }
1364 
IsDefaultIme()1365 bool InputMethodAbility::IsDefaultIme()
1366 {
1367     IMSA_HILOGD("InputMethodAbility start");
1368     if (isDefaultIme_) {
1369         return true;
1370     }
1371     std::lock_guard<std::mutex> lock(defaultImeCheckMutex_);
1372     if (isDefaultIme_) {
1373         return true;
1374     }
1375     auto proxy = GetImsaProxy();
1376     if (proxy == nullptr) {
1377         IMSA_HILOGE("failed to get imsa proxy!");
1378         return false;
1379     }
1380     auto ret = proxy->IsDefaultIme();
1381     if (ret == ErrorCode::NO_ERROR) {
1382         isDefaultIme_ = true;
1383         return true;
1384     }
1385     IMSA_HILOGE("call IsDefaultIme failed, ret: %{public}d!", ret);
1386     return false;
1387 }
1388 
IsEnable()1389 bool InputMethodAbility::IsEnable()
1390 {
1391     if (imeListener_ == nullptr) {
1392         return false;
1393     }
1394     return imeListener_->IsEnable();
1395 }
1396 
IsCallbackRegistered(const std::string & type)1397 bool InputMethodAbility::IsCallbackRegistered(const std::string &type)
1398 {
1399     if (imeListener_ == nullptr) {
1400         return false;
1401     }
1402     return imeListener_->IsCallbackRegistered(type);
1403 }
1404 
IsSystemApp()1405 bool InputMethodAbility::IsSystemApp()
1406 {
1407     IMSA_HILOGD("InputMethodAbility start");
1408     if (isSystemApp_) {
1409         return true;
1410     }
1411     std::lock_guard<std::mutex> lock(systemAppCheckMutex_);
1412     if (isSystemApp_) {
1413         return true;
1414     }
1415     auto proxy = GetImsaProxy();
1416     if (proxy == nullptr) {
1417         IMSA_HILOGE("failed to get imsa proxy!");
1418         return false;
1419     }
1420     bool ret = false;
1421     proxy->IsSystemApp(ret);
1422     if (ret) {
1423         isSystemApp_ = true;
1424     }
1425     return ret;
1426 }
1427 
ExitCurrentInputType()1428 int32_t InputMethodAbility::ExitCurrentInputType()
1429 {
1430     IMSA_HILOGD("InputMethodAbility start.");
1431     ClearInputType();
1432     auto proxy = GetImsaProxy();
1433     if (proxy == nullptr) {
1434         IMSA_HILOGE("failed to get imsa proxy!");
1435         return false;
1436     }
1437     auto ret = proxy->ExitCurrentInputType();
1438     if (ret == ErrorCode::NO_ERROR) {
1439         NotifyPanelStatus(false);
1440     }
1441     return ret;
1442 }
1443 
ClearInputType()1444 void InputMethodAbility::ClearInputType()
1445 {
1446     std::lock_guard<std::mutex> lock(inputTypeLock_);
1447     if (inputType_ != InputType::SECURITY_INPUT) {
1448         inputType_ = InputType::NONE;
1449     }
1450 }
1451 
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)1452 int32_t InputMethodAbility::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
1453 {
1454     isShown = false;
1455     auto result = panels_.Find(panelInfo.panelType);
1456     if (!result.first) {
1457         IMSA_HILOGI("panel type: %{public}d not found.", static_cast<int32_t>(panelInfo.panelType));
1458         return ErrorCode::NO_ERROR;
1459     }
1460     auto panel = result.second;
1461     if (panel->GetPanelType() == PanelType::SOFT_KEYBOARD && panel->GetPanelFlag() != panelInfo.panelFlag) {
1462         IMSA_HILOGI("queried flag: %{public}d, current flag: %{public}d, panel not found.",
1463             static_cast<int32_t>(panelInfo.panelFlag), static_cast<int32_t>(panel->GetPanelFlag()));
1464         return ErrorCode::NO_ERROR;
1465     }
1466     isShown = panel->IsShowing();
1467     IMSA_HILOGI("type: %{public}d, flag: %{public}d, result: %{public}d.", static_cast<int32_t>(panelInfo.panelType),
1468         static_cast<int32_t>(panelInfo.panelFlag), isShown);
1469     return ErrorCode::NO_ERROR;
1470 }
1471 
OnClientInactive(const sptr<IRemoteObject> & channel)1472 void InputMethodAbility::OnClientInactive(const sptr<IRemoteObject> &channel)
1473 {
1474     IMSA_HILOGI("client inactive.");
1475     if (imeListener_ != nullptr) {
1476         imeListener_->OnInputFinish();
1477     }
1478     auto channelProxy = std::make_shared<InputDataChannelProxy>(channel);
1479     if (channelProxy == nullptr) {
1480         IMSA_HILOGE("failed to create channel proxy!");
1481         return;
1482     }
1483     auto panel = GetSoftKeyboardPanel();
1484     if (imeListener_ != nullptr && panel != nullptr && panel->GetPanelFlag() != PanelFlag::FLG_FIXED) {
1485         imeListener_->OnKeyboardStatus(false);
1486     }
1487     panels_.ForEach([this, &channelProxy](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
1488         if (panelType == PanelType::SOFT_KEYBOARD && panel->GetPanelFlag() == PanelFlag::FLG_FIXED) {
1489             return false;
1490         }
1491         auto ret = panel->HidePanel();
1492         if (ret != ErrorCode::NO_ERROR) {
1493             IMSA_HILOGE("failed, ret: %{public}d", ret);
1494             return false;
1495         }
1496         PanelStatusInfo info;
1497         info.panelInfo.panelType = panel->GetPanelType();
1498         info.panelInfo.panelFlag = panel->GetPanelFlag();
1499         info.visible = false;
1500         info.trigger = Trigger::IME_APP;
1501         NotifyPanelStatusInfo(info, channelProxy);
1502         // finish previewing text when soft keyboard hides
1503         if (panel->GetPanelType() == PanelType::SOFT_KEYBOARD) {
1504             AsyncIpcCallBack callback = [](int32_t code, const ResponseData &data) {};
1505             FinishTextPreview(callback);
1506         }
1507         return false;
1508     });
1509     // cannot clear inputAttribute, otherwise it will affect hicar
1510     ClearDataChannel(channel);
1511     ClearAttachOptions();
1512     ClearBindClientInfo();
1513 }
1514 
NotifyKeyboardHeight(uint32_t panelHeight,PanelFlag panelFlag)1515 void InputMethodAbility::NotifyKeyboardHeight(uint32_t panelHeight, PanelFlag panelFlag)
1516 {
1517     auto channel = GetInputDataChannelProxy();
1518     if (channel == nullptr) {
1519         IMSA_HILOGE("channel is nullptr!");
1520         return;
1521     }
1522     IMSA_HILOGD("notify panel height: %{public}u, flag: %{public}d.", panelHeight, static_cast<int32_t>(panelFlag));
1523     if (panelFlag != PanelFlag::FLG_FIXED) {
1524         channel->NotifyKeyboardHeight(0);
1525         return;
1526     }
1527     channel->NotifyKeyboardHeight(panelHeight);
1528 }
1529 
SendPrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1530 int32_t InputMethodAbility::SendPrivateCommand(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1531 {
1532     if (!IsDefaultIme()) {
1533         IMSA_HILOGE("current is not default ime!");
1534         return ErrorCode::ERROR_NOT_DEFAULT_IME;
1535     }
1536     if (!TextConfig::IsPrivateCommandValid(privateCommand)) {
1537         IMSA_HILOGE("privateCommand is limit 32KB, count limit 5!");
1538         return ErrorCode::ERROR_INVALID_PRIVATE_COMMAND_SIZE;
1539     }
1540     if (TextConfig::IsSystemPrivateCommand(privateCommand)) {
1541         auto systemChannel = GetSystemCmdChannelProxy();
1542         if (systemChannel == nullptr) {
1543             IMSA_HILOGE("channel is nullptr!");
1544             return ErrorCode::ERROR_SYSTEM_CMD_CHANNEL_ERROR;
1545         }
1546         Value commandValueMap(privateCommand);
1547         return systemChannel->SendPrivateCommand(commandValueMap);
1548     } else {
1549         auto channel = GetInputDataChannelProxy();
1550         if (channel == nullptr) {
1551             IMSA_HILOGE("channel is nullptr!");
1552             return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1553         }
1554         Value commandValueMap(privateCommand);
1555         return channel->SendPrivateCommand(commandValueMap);
1556     }
1557 }
1558 
ReceivePrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1559 int32_t InputMethodAbility::ReceivePrivateCommand(
1560     const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1561 {
1562     if (imeListener_ == nullptr) {
1563         IMSA_HILOGE("imeListener is nullptr!");
1564         return ErrorCode::ERROR_IME;
1565     }
1566     imeListener_->ReceivePrivateCommand(privateCommand);
1567     return ErrorCode::NO_ERROR;
1568 }
1569 
SetPreviewTextInner(const std::string & text,const Range & range,const AsyncIpcCallBack & callback)1570 int32_t InputMethodAbility::SetPreviewTextInner(
1571     const std::string &text, const Range &range, const AsyncIpcCallBack &callback)
1572 {
1573     InputMethodSyncTrace tracer("IMA_SetPreviewText");
1574     auto dataChannel = GetInputDataChannelProxyWrap();
1575     if (dataChannel == nullptr) {
1576         IMSA_HILOGE("dataChannel is nullptr!");
1577         return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
1578     }
1579     RangeInner rangeInner = InputMethodTools::GetInstance().RangeToInner(range);
1580     return dataChannel->SetPreviewText(text, rangeInner, callback);
1581 }
1582 
FinishTextPreviewInner(const AsyncIpcCallBack & callback)1583 int32_t InputMethodAbility::FinishTextPreviewInner(const AsyncIpcCallBack &callback)
1584 {
1585     InputMethodSyncTrace tracer("IMA_FinishTextPreview");
1586     auto dataChannel = GetInputDataChannelProxyWrap();
1587     if (dataChannel == nullptr) {
1588         IMSA_HILOGE("dataChannel is nullptr!");
1589         return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
1590     }
1591     return dataChannel->FinishTextPreview(callback);
1592 }
1593 
GetCallingWindowInfo(CallingWindowInfo & windowInfo)1594 int32_t InputMethodAbility::GetCallingWindowInfo(CallingWindowInfo &windowInfo)
1595 {
1596     IMSA_HILOGD("IMA start.");
1597     auto channel = GetInputDataChannelProxy();
1598     if (channel == nullptr) {
1599         IMSA_HILOGE("channel is nullptr!");
1600         return ErrorCode::ERROR_CLIENT_NOT_FOUND;
1601     }
1602     auto panel = GetSoftKeyboardPanel();
1603     if (panel == nullptr) {
1604         IMSA_HILOGE("panel not found!");
1605         return ErrorCode::ERROR_PANEL_NOT_FOUND;
1606     }
1607     TextTotalConfig textConfig;
1608     int32_t ret = GetTextConfig(textConfig);
1609     if (ret != ErrorCode::NO_ERROR) {
1610         IMSA_HILOGE("failed to get window id, ret: %{public}d!", ret);
1611         return ErrorCode::ERROR_GET_TEXT_CONFIG;
1612     }
1613     ret = panel->SetCallingWindow(textConfig.windowId);
1614     if (ret != ErrorCode::NO_ERROR) {
1615         IMSA_HILOGE("failed to set calling window, ret: %{public}d!", ret);
1616         return ret;
1617     }
1618     ret = panel->GetCallingWindowInfo(windowInfo);
1619     if (ret != ErrorCode::NO_ERROR) {
1620         IMSA_HILOGE("failed to get calling window, ret: %{public}d", ret);
1621     }
1622     return ret;
1623 }
1624 
NotifyPanelStatusInfo(const PanelStatusInfo & info,std::shared_ptr<InputDataChannelProxy> & channelProxy)1625 void InputMethodAbility::NotifyPanelStatusInfo(
1626     const PanelStatusInfo &info, std::shared_ptr<InputDataChannelProxy> &channelProxy)
1627 {
1628     // CANDIDATE_COLUMN not notify
1629     if (info.panelInfo.panelFlag == PanelFlag::FLG_CANDIDATE_COLUMN) {
1630         return;
1631     }
1632     if (channelProxy != nullptr) {
1633         PanelStatusInfoInner inner = InputMethodTools::GetInstance().PanelStatusInfoToInner(info);
1634         channelProxy->NotifyPanelStatusInfo(inner);
1635     }
1636 
1637     auto controlChannel = GetInputControlChannel();
1638     if (controlChannel != nullptr && info.trigger == Trigger::IME_APP && !info.visible && !isImeTerminating_.load()) {
1639         controlChannel->HideKeyboardSelf();
1640     }
1641 }
1642 
SendMessage(const ArrayBuffer & arrayBuffer)1643 int32_t InputMethodAbility::SendMessage(const ArrayBuffer &arrayBuffer)
1644 {
1645     int32_t securityMode = INVALID_SECURITY_MODE;
1646     auto ret = GetSecurityMode(securityMode);
1647     if (ret != ErrorCode::NO_ERROR) {
1648         IMSA_HILOGE("Get security mode failed!");
1649         return ret;
1650     }
1651     if (!ArrayBuffer::IsSizeValid(arrayBuffer)) {
1652         IMSA_HILOGE("arrayBuffer size is invalid!");
1653         return ErrorCode::ERROR_INVALID_ARRAY_BUFFER_SIZE;
1654     }
1655     if (securityMode != static_cast<int32_t>(SecurityMode::FULL)) {
1656         IMSA_HILOGE("Security mode must be FULL!.");
1657         return ErrorCode::ERROR_SECURITY_MODE_OFF;
1658     }
1659     auto dataChannel = GetInputDataChannelProxy();
1660     if (dataChannel == nullptr) {
1661         IMSA_HILOGE("datachannel is nullptr.");
1662         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1663     }
1664     return dataChannel->SendMessage(arrayBuffer);
1665 }
1666 
RecvMessage(const ArrayBuffer & arrayBuffer)1667 int32_t InputMethodAbility::RecvMessage(const ArrayBuffer &arrayBuffer)
1668 {
1669     int32_t securityMode = -1;
1670     auto ret = GetSecurityMode(securityMode);
1671     if (ret != ErrorCode::NO_ERROR) {
1672         IMSA_HILOGE("Get security mode failed!");
1673         return ret;
1674     }
1675     if (securityMode != static_cast<int32_t>(SecurityMode::FULL)) {
1676         IMSA_HILOGE("Security mode must be FULL!.");
1677         return ErrorCode::ERROR_SECURITY_MODE_OFF;
1678     }
1679     auto msgHandlerCallback = GetMsgHandlerCallback();
1680     if (msgHandlerCallback == nullptr) {
1681         IMSA_HILOGW("Message handler was not regist!");
1682         return ErrorCode::ERROR_MSG_HANDLER_NOT_REGIST;
1683     }
1684     return msgHandlerCallback->OnMessage(arrayBuffer);
1685 }
1686 
RegisterMsgHandler(const std::shared_ptr<MsgHandlerCallbackInterface> & msgHandler)1687 int32_t InputMethodAbility::RegisterMsgHandler(const std::shared_ptr<MsgHandlerCallbackInterface> &msgHandler)
1688 {
1689     IMSA_HILOGI("isRegist: %{public}d", msgHandler != nullptr);
1690     std::shared_ptr<MsgHandlerCallbackInterface> exMsgHandler = nullptr;
1691     {
1692         std::lock_guard<decltype(msgHandlerMutex_)> lock(msgHandlerMutex_);
1693         exMsgHandler = msgHandler_;
1694         msgHandler_ = msgHandler;
1695     }
1696     if (exMsgHandler != nullptr) {
1697         IMSA_HILOGI("Trigger exMessageHandler OnTerminated.");
1698         exMsgHandler->OnTerminated();
1699     }
1700     return ErrorCode::NO_ERROR;
1701 }
1702 
GetMsgHandlerCallback()1703 std::shared_ptr<MsgHandlerCallbackInterface> InputMethodAbility::GetMsgHandlerCallback()
1704 {
1705     std::lock_guard<decltype(msgHandlerMutex_)> lock(msgHandlerMutex_);
1706     return msgHandler_;
1707 }
1708 
StartInput(const InputClientInfo & clientInfo,bool isBindFromClient)1709 int32_t InputMethodAbility::StartInput(const InputClientInfo &clientInfo, bool isBindFromClient)
1710 {
1711     auto ret = StartInputInner(clientInfo, isBindFromClient);
1712     if (ret == ErrorCode::NO_ERROR) {
1713         return ret;
1714     }
1715     ReportImeStartInput(static_cast<int32_t>(IInputMethodCoreIpcCode::COMMAND_START_INPUT),
1716         ret, clientInfo.isShowKeyboard);
1717     return ret;
1718 }
1719 
InsertText(const std::string & text,const AsyncIpcCallBack & callback)1720 int32_t InputMethodAbility::InsertText(const std::string &text, const AsyncIpcCallBack &callback)
1721 {
1722     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1723     auto ret = InsertTextInner(text, callback);
1724     int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1725     ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_INSERT_TEXT), ret, end - start);
1726     return ret;
1727 }
1728 
DeleteForward(int32_t length,const AsyncIpcCallBack & callback)1729 int32_t InputMethodAbility::DeleteForward(int32_t length, const AsyncIpcCallBack &callback)
1730 {
1731     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1732     auto ret = DeleteForwardInner(length, callback);
1733     int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1734     ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_DELETE_FORWARD), ret, end - start);
1735     return ret;
1736 }
1737 
DeleteBackward(int32_t length,const AsyncIpcCallBack & callback)1738 int32_t InputMethodAbility::DeleteBackward(int32_t length, const AsyncIpcCallBack &callback)
1739 {
1740     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1741     auto ret = DeleteBackwardInner(length, callback);
1742     int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1743     ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_DELETE_BACKWARD), ret, end - start);
1744     return ret;
1745 }
1746 
SetPreviewText(const std::string & text,const Range & range,const AsyncIpcCallBack & callback)1747 int32_t InputMethodAbility::SetPreviewText(
1748     const std::string &text, const Range &range, const AsyncIpcCallBack &callback)
1749 {
1750     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1751     auto ret = SetPreviewTextInner(text, range, callback);
1752     int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1753     ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_SET_PREVIEW_TEXT), ret, end - start);
1754     return ret;
1755 }
1756 
FinishTextPreview(const AsyncIpcCallBack & callback)1757 int32_t InputMethodAbility::FinishTextPreview(const AsyncIpcCallBack &callback)
1758 {
1759     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1760     auto ret = FinishTextPreviewInner(callback);
1761     int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1762     ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_FINISH_TEXT_PREVIEW),
1763         ret, end - start);
1764     return ret;
1765 }
1766 
GetTextBeforeCursor(int32_t number,std::u16string & text,const AsyncIpcCallBack & callback)1767 int32_t InputMethodAbility::GetTextBeforeCursor(int32_t number, std::u16string &text, const AsyncIpcCallBack &callback)
1768 {
1769     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1770     auto ret = GetTextBeforeCursorInner(number, text, callback);
1771     int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1772     ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_GET_TEXT_BEFORE_CURSOR),
1773         ret, end - start);
1774     return ret;
1775 }
GetTextAfterCursor(int32_t number,std::u16string & text,const AsyncIpcCallBack & callback)1776 int32_t InputMethodAbility::GetTextAfterCursor(int32_t number, std::u16string &text, const AsyncIpcCallBack &callback)
1777 {
1778     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1779     auto ret = GetTextAfterCursorInner(number, text, callback);
1780     int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1781     ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_GET_TEXT_AFTER_CURSOR),
1782         ret, end - start);
1783     return ret;
1784 }
GetTextIndexAtCursor(int32_t & index,const AsyncIpcCallBack & callback)1785 int32_t InputMethodAbility::GetTextIndexAtCursor(int32_t &index, const AsyncIpcCallBack &callback)
1786 {
1787     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1788     auto ret = GetTextIndexAtCursorInner(index, callback);
1789     int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1790     ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_GET_TEXT_INDEX_AT_CURSOR),
1791         ret, end - start);
1792     return ret;
1793 }
1794 
SetBindClientInfo(const InputClientInfo & clientInfo)1795 void InputMethodAbility::SetBindClientInfo(const InputClientInfo &clientInfo)
1796 {
1797     std::lock_guard<std::mutex> lock(bindClientInfoLock_);
1798     bindClientInfo_ = { clientInfo.pid, clientInfo.type, clientInfo.name };
1799 }
1800 
GetBindClientInfo()1801 HiSysEventClientInfo InputMethodAbility::GetBindClientInfo()
1802 {
1803     std::lock_guard<std::mutex> lock(bindClientInfoLock_);
1804     return bindClientInfo_;
1805 }
1806 
ClearBindClientInfo()1807 void InputMethodAbility::ClearBindClientInfo()
1808 {
1809     std::lock_guard<std::mutex> lock(bindClientInfoLock_);
1810     bindClientInfo_ = {};
1811 }
1812 
ReportImeStartInput(int32_t eventCode,int32_t errCode,bool isShowKeyboard,int64_t consumeTime)1813 void InputMethodAbility::ReportImeStartInput(
1814     int32_t eventCode, int32_t errCode, bool isShowKeyboard, int64_t consumeTime)
1815 {
1816     IMSA_HILOGD("HiSysEvent report start:[%{public}d, %{public}d]!", eventCode, errCode);
1817     auto clientInfo = GetBindClientInfo();
1818     auto evenInfo = HiSysOriginalInfo::Builder()
1819                         .SetPeerName(clientInfo.name)
1820                         .SetPeerPid(clientInfo.pid)
1821                         .SetIsShowKeyboard(isShowKeyboard)
1822                         .SetEventCode(eventCode)
1823                         .SetErrCode(errCode)
1824                         .SetImeCbTime(consumeTime)
1825                         .Build();
1826     ImaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::IME_START_INPUT, *evenInfo);
1827     IMSA_HILOGD("HiSysEvent report end:[%{public}d, %{public}d]!", eventCode, errCode);
1828 }
1829 
ReportBaseTextOperation(int32_t eventCode,int32_t errCode,int64_t consumeTime)1830 void InputMethodAbility::ReportBaseTextOperation(int32_t eventCode, int32_t errCode, int64_t consumeTime)
1831 {
1832     IMSA_HILOGD("HiSysEvent report start:[%{public}d, %{public}d]!", eventCode, errCode);
1833     auto clientInfo = GetBindClientInfo();
1834     if (errCode == ErrorCode::NO_ERROR && consumeTime > BASE_TEXT_OPERATION_TIMEOUT) {
1835         errCode = ErrorCode::ERROR_DEAL_TIMEOUT;
1836     }
1837     auto evenInfo = HiSysOriginalInfo::Builder()
1838                         .SetPeerName(clientInfo.name)
1839                         .SetPeerPid(clientInfo.pid)
1840                         .SetClientType(clientInfo.type)
1841                         .SetEventCode(eventCode)
1842                         .SetErrCode(errCode)
1843                         .SetBaseTextOperatorTime(consumeTime)
1844                         .Build();
1845     ImaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::BASE_TEXT_OPERATOR, *evenInfo);
1846     IMSA_HILOGD("HiSysEvent report end:[%{public}d, %{public}d]!", eventCode, errCode);
1847 }
1848 
OnCallingDisplayIdChanged(uint64_t displayId)1849 int32_t InputMethodAbility::OnCallingDisplayIdChanged(uint64_t displayId)
1850 {
1851     IMSA_HILOGD("InputMethodAbility calling display: %{public}" PRIu64 ".", displayId);
1852     if (imeListener_ == nullptr) {
1853         IMSA_HILOGD("imeListener_ is nullptr!");
1854         return ErrorCode::NO_ERROR;
1855     }
1856     auto windowId = GetInputAttribute().windowId;
1857     auto task = [this, windowId]() {
1858         panels_.ForEach([windowId](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
1859             if (panel != nullptr) {
1860                 panel->SetCallingWindow(windowId);
1861             }
1862             return false;
1863         });
1864     };
1865     imeListener_->PostTaskToEventHandler(task, "SetCallingWindow");
1866     {
1867         std::lock_guard<std::mutex> lock(inputAttrLock_);
1868         inputAttribute_.callingDisplayId = displayId;
1869     }
1870     imeListener_->OnCallingDisplayIdChanged(displayId);
1871     return ErrorCode::NO_ERROR;
1872 }
1873 
OnSendPrivateData(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1874 int32_t InputMethodAbility::OnSendPrivateData(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1875 {
1876     auto ret = ReceivePrivateCommand(privateCommand);
1877     if (ret != ErrorCode::NO_ERROR) {
1878         IMSA_HILOGE("OnSendPrivateData failed!");
1879     }
1880     IMSA_HILOGD("InputMethodAbility ReceivePrivateCommand success.");
1881     return ret;
1882 }
1883 
HandleUnconsumedKey(const std::shared_ptr<MMI::KeyEvent> & keyEvent)1884 bool InputMethodAbility::HandleUnconsumedKey(const std::shared_ptr<MMI::KeyEvent> &keyEvent)
1885 {
1886     if (keyEvent == nullptr) {
1887         IMSA_HILOGE("keyEvent nullptr");
1888         return false;
1889     }
1890     auto channel = GetInputDataChannelProxyWrap();
1891     if (channel == nullptr) {
1892         IMSA_HILOGD("channel is nullptr!");
1893         return false;
1894     }
1895     if (!GetInputAttribute().needAutoInputNumkey) {
1896         IMSA_HILOGD("no need");
1897         return false;
1898     }
1899     if (keyEvent->GetKeyAction() != MMI::KeyEvent::KEY_ACTION_DOWN) {
1900         IMSA_HILOGD("not down key");
1901         return false;
1902     }
1903     if (keyEvent->GetPressedKeys().size() > 1) {
1904         IMSA_HILOGD("only handle single key");
1905         return false;
1906     }
1907     int32_t keyCode = keyEvent->GetKeyCode();
1908     std::string inputNumber;
1909     AsyncIpcCallBack callback = [](int32_t code, const ResponseData &data) {};
1910     if (MMI::KeyEvent::KEYCODE_0 <= keyCode && keyCode <= MMI::KeyEvent::KEYCODE_9) {
1911         IMSA_HILOGI("auto input a number");
1912         channel->InsertText(std::to_string(keyCode - MMI::KeyEvent::KEYCODE_0), callback);
1913         return true;
1914     }
1915     if (!keyEvent->GetFunctionKey(MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY)) {
1916         IMSA_HILOGD("num lock off");
1917         return false;
1918     }
1919     if (MMI::KeyEvent::KEYCODE_NUMPAD_0 <= keyCode && keyCode <= MMI::KeyEvent::KEYCODE_NUMPAD_9) {
1920         IMSA_HILOGI("auto input a number");
1921         channel->InsertText(std::to_string(keyCode - MMI::KeyEvent::KEYCODE_NUMPAD_0), callback);
1922         return true;
1923     }
1924     return false;
1925 }
1926 
OnResponse(uint64_t msgId,int32_t code,const ResponseData & data)1927 int32_t InputMethodAbility::OnResponse(uint64_t msgId, int32_t code, const ResponseData &data)
1928 {
1929     auto channel = GetInputDataChannelProxyWrap();
1930     if (channel != nullptr) {
1931         ResponseInfo rspInfo = { code, data };
1932         channel->HandleResponse(msgId, rspInfo);
1933     }
1934     return ErrorCode::NO_ERROR;
1935 }
1936 
IsCapacitySupport(int32_t capacity,bool & isSupport)1937 int32_t InputMethodAbility::IsCapacitySupport(int32_t capacity, bool &isSupport)
1938 {
1939     auto proxy = GetImsaProxy();
1940     if (proxy == nullptr) {
1941         IMSA_HILOGE("failed to get imsa proxy!");
1942         return ErrorCode::ERROR_NULL_POINTER;
1943     }
1944 
1945     return proxy->IsCapacitySupport(capacity, isSupport);
1946 }
1947 
HandleKeyEventResult(uint64_t cbId,bool consumeResult,const sptr<IRemoteObject> & channelObject)1948 int32_t InputMethodAbility::HandleKeyEventResult(
1949     uint64_t cbId, bool consumeResult, const sptr<IRemoteObject> &channelObject)
1950 {
1951     IMSA_HILOGD("run in:%{public}" PRIu64 "/%{public}d.", cbId, consumeResult);
1952     if (channelObject == nullptr) {
1953         IMSA_HILOGE("channelObject is nullptr:%{public}" PRIu64 ".", cbId);
1954         return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
1955     }
1956     auto channel = std::make_shared<InputDataChannelProxy>(channelObject);
1957     return channel->HandleKeyEventResult(cbId, consumeResult);
1958 }
1959 
OnNotifyPreemption()1960 int32_t InputMethodAbility::OnNotifyPreemption()
1961 {
1962     IMSA_HILOGD("start.");
1963     StopInput(dataChannelObject_, 0);
1964     isBound_.store(false);
1965     auto imeListener = GetImeListener();
1966     if (imeListener == nullptr) {
1967         return ErrorCode::ERROR_IME_NOT_STARTED;
1968     }
1969     IMSA_HILOGD("notifyPreemption begin.");
1970     imeListener->NotifyPreemption();
1971     return ErrorCode::NO_ERROR;
1972 }
1973 } // namespace MiscServices
1974 } // namespace OHOS