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