• 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_controller.h"
17 
18 #include <algorithm>
19 #include <cinttypes>
20 #include "securec.h"
21 
22 #include "block_data.h"
23 #include "global.h"
24 #include "imc_hisysevent_reporter.h"
25 #include "ime_event_monitor_manager_impl.h"
26 #include "input_client_service_impl.h"
27 #include "input_data_channel_service_impl.h"
28 #include "input_method_agent_proxy.h"
29 #include "input_method_property.h"
30 #include "input_method_status.h"
31 #include "input_method_system_ability_proxy.h"
32 #include "inputmethod_sysevent.h"
33 #include "inputmethod_trace.h"
34 #include "iservice_registry.h"
35 #include "keyevent_consumer_service_impl.h"
36 #include "on_demand_start_stop_sa.h"
37 #include "string_ex.h"
38 #include "string_utils.h"
39 #include "sys/prctl.h"
40 #include "system_ability_definition.h"
41 #include "system_cmd_channel_stub.h"
42 #include "input_method_tools.h"
43 #include "notify_service_impl.h"
44 #include "on_input_stop_notify_proxy.h"
45 
46 namespace OHOS {
47 namespace MiscServices {
48 using namespace MessageID;
49 using namespace std::chrono;
50 sptr<InputMethodController> InputMethodController::instance_;
51 std::shared_ptr<AppExecFwk::EventHandler> InputMethodController::handler_ { nullptr };
52 std::mutex InputMethodController::instanceLock_;
53 std::mutex InputMethodController::logLock_;
54 int InputMethodController::keyEventCountInPeriod_ = 0;
55 std::chrono::system_clock::time_point InputMethodController::startLogTime_ = system_clock::now();
56 constexpr int32_t LOOP_COUNT = 5;
57 constexpr int32_t LOG_MAX_TIME = 20;
58 constexpr int64_t DELAY_TIME = 100;
59 constexpr int32_t ACE_DEAL_TIME_OUT = 200;
60 constexpr int32_t MAX_PLACEHOLDER_SIZE = 255; // 256 utf16 char
61 constexpr int32_t MAX_ABILITY_NAME_SIZE = 127; // 127 utf16 char
62 static constexpr int32_t MAX_TIMEOUT = 2500;
63 constexpr size_t MAX_AGENT_NUMBER = 2;
64 const std::string IME_MIRROR_NAME = "proxyIme_IME_MIRROR";
InputMethodController()65 InputMethodController::InputMethodController()
66 {
67     IMSA_HILOGD("IMC structure.");
68 }
69 
~InputMethodController()70 InputMethodController::~InputMethodController() { }
71 #ifdef OHOS_IMF_TEST
SetImsaProxyForTest(sptr<IInputMethodSystemAbility> proxy)72 void InputMethodController::SetImsaProxyForTest(sptr<IInputMethodSystemAbility> proxy)
73 {
74     std::lock_guard<std::mutex> autoLock(abilityLock_);
75     abilityManager_ = proxy;
76 }
77 #endif // OHOS_IMF_TEST
78 
GetInstance()79 sptr<InputMethodController> InputMethodController::GetInstance()
80 {
81     if (instance_ == nullptr) {
82         std::lock_guard<std::mutex> autoLock(instanceLock_);
83         if (instance_ == nullptr) {
84             IMSA_HILOGD("instance_ is nullptr.");
85             instance_ = new (std::nothrow) InputMethodController();
86             if (instance_ == nullptr) {
87                 IMSA_HILOGE("failed to create InputMethodController!");
88                 return instance_;
89             }
90             int32_t ret = instance_->Initialize();
91             if (ret != ErrorCode::NO_ERROR) {
92                 InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, "", "IMC initialize failed!");
93             }
94         }
95     }
96     return instance_;
97 }
98 
RestoreListenEventFlag()99 int32_t InputMethodController::RestoreListenEventFlag()
100 {
101     auto proxy = GetSystemAbilityProxy();
102     if (proxy == nullptr) {
103         IMSA_HILOGE("proxy is nullptr!");
104         return ErrorCode::ERROR_SERVICE_START_FAILED;
105     }
106     // 0 represent no need to check permission
107     InputClientInfoInner infoInner = InputMethodTools::GetInstance().InputClientInfoToInner(clientInfo_);
108     return proxy->UpdateListenEventFlag(infoInner, 0);
109 }
110 
UpdateListenEventFlag(uint32_t finalEventFlag,uint32_t eventFlag,bool isOn)111 int32_t InputMethodController::UpdateListenEventFlag(uint32_t finalEventFlag, uint32_t eventFlag, bool isOn)
112 {
113     auto oldEventFlag = clientInfo_.eventFlag;
114     clientInfo_.eventFlag = finalEventFlag;
115     auto proxy = GetSystemAbilityProxy();
116     if (proxy == nullptr) {
117         IMSA_HILOGE("proxy is nullptr!");
118         if (isOn) {
119             clientInfo_.eventFlag = oldEventFlag;
120         }
121         return ErrorCode::ERROR_SERVICE_START_FAILED;
122     }
123     InputClientInfoInner infoInner = InputMethodTools::GetInstance().InputClientInfoToInner(clientInfo_);
124     auto ret = proxy->UpdateListenEventFlag(infoInner, eventFlag);
125     if (ret != ErrorCode::NO_ERROR && isOn) {
126         clientInfo_.eventFlag = oldEventFlag;
127     }
128     return ret;
129 }
130 
SetControllerListener(std::shared_ptr<ControllerListener> controllerListener)131 void InputMethodController::SetControllerListener(std::shared_ptr<ControllerListener> controllerListener)
132 {
133     IMSA_HILOGD("InputMethodController run in");
134     controllerListener_ = std::move(controllerListener);
135 }
136 
Initialize()137 int32_t InputMethodController::Initialize()
138 {
139     sptr<IInputClient> client = new (std::nothrow) InputClientServiceImpl();
140     if (client == nullptr) {
141         IMSA_HILOGE("failed to create client!");
142         return ErrorCode::ERROR_NULL_POINTER;
143     }
144     sptr<IInputDataChannel> channel = new (std::nothrow) InputDataChannelServiceImpl();
145     if (channel == nullptr) {
146         IMSA_HILOGE("failed to new channel!");
147         return ErrorCode::ERROR_NULL_POINTER;
148     }
149     InputAttribute attribute;
150     attribute.inputPattern = InputAttribute::PATTERN_TEXT;
151     clientInfo_.attribute = attribute;
152     clientInfo_.client = client,
153     clientInfo_.channel = channel->AsObject();
154 
155     // make AppExecFwk::EventHandler handler
156     handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
157     return ErrorCode::NO_ERROR;
158 }
159 
TryGetSystemAbilityProxy()160 sptr<IInputMethodSystemAbility> InputMethodController::TryGetSystemAbilityProxy()
161 {
162     return GetSystemAbilityProxy(false);
163 }
164 
GetSystemAbilityProxy(bool ifRetry)165 sptr<IInputMethodSystemAbility> InputMethodController::GetSystemAbilityProxy(bool ifRetry)
166 {
167     std::lock_guard<std::mutex> lock(abilityLock_);
168     if (abilityManager_ != nullptr) {
169         return abilityManager_;
170     }
171     IMSA_HILOGD("get input method service proxy.");
172     auto systemAbility = OnDemandStartStopSa::GetInputMethodSystemAbility(ifRetry);
173     if (systemAbility == nullptr) {
174         IMSA_HILOGE("systemAbility is nullptr!");
175         return nullptr;
176     }
177 
178     if (deathRecipient_ == nullptr) {
179         deathRecipient_ = new (std::nothrow) InputDeathRecipient();
180         if (deathRecipient_ == nullptr) {
181             IMSA_HILOGE("create death recipient failed!");
182             return nullptr;
183         }
184     }
185     deathRecipient_->SetDeathRecipient([this](const wptr<IRemoteObject> &remote) {
186         OnRemoteSaDied(remote);
187     });
188     if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) {
189         IMSA_HILOGE("failed to add death recipient!");
190         return nullptr;
191     }
192     abilityManager_ = iface_cast<IInputMethodSystemAbility>(systemAbility);
193     return abilityManager_;
194 }
195 
RemoveDeathRecipient()196 void InputMethodController::RemoveDeathRecipient()
197 {
198     std::lock_guard<std::mutex> lock(abilityLock_);
199     if (abilityManager_ != nullptr && abilityManager_->AsObject() != nullptr && deathRecipient_ != nullptr) {
200         abilityManager_->AsObject()->RemoveDeathRecipient(deathRecipient_);
201     }
202     deathRecipient_ = nullptr;
203     abilityManager_ = nullptr;
204 }
205 
DeactivateClient()206 void InputMethodController::DeactivateClient()
207 {
208     {
209         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
210         clientInfo_.state = ClientState::INACTIVE;
211     }
212     SendKeyboardStatus(KeyboardStatus::NONE);
213 }
214 
CalibrateImmersiveParam(InputAttribute & inputAttribute)215 void InputMethodController::CalibrateImmersiveParam(InputAttribute &inputAttribute)
216 {
217     // 1.The gradient mode and the fluid light mode can only be used when the immersive mode is enabled.
218     if (inputAttribute.immersiveMode == 0) {
219         if (inputAttribute.gradientMode != 0 || inputAttribute.fluidLightMode != 0) {
220             IMSA_HILOGW("immersiveMode is NONE, but gradientMode=%{public}d, fluidLightMode=%{public}d",
221                 inputAttribute.gradientMode, inputAttribute.fluidLightMode);
222             inputAttribute.gradientMode = 0;
223             inputAttribute.fluidLightMode = 0;
224         }
225         return;
226     }
227 
228     // 2.The fluid light mode can only be used when the gradient mode is enabled.
229     if (inputAttribute.gradientMode == 0 && inputAttribute.fluidLightMode != 0) {
230         IMSA_HILOGW("gradientMode is NONE, but fluidLightMode=%{public}d", inputAttribute.fluidLightMode);
231         inputAttribute.fluidLightMode = 0;
232         return;
233     }
234 }
235 
SaveTextConfig(const TextConfig & textConfig)236 void InputMethodController::SaveTextConfig(const TextConfig &textConfig)
237 {
238     IMSA_HILOGD("textConfig: %{public}s.", textConfig.ToString().c_str());
239     CursorInfo cursorInfo = textConfig.cursorInfo;
240     uint32_t windowId = textConfig.windowId;
241     GetWindowScaleCoordinate(windowId, cursorInfo);
242     {
243         std::lock_guard<std::mutex> lock(textConfigLock_);
244         textConfig_ = textConfig;
245         CalibrateImmersiveParam(textConfig_.inputAttribute);
246         textConfig_.cursorInfo = cursorInfo;
247         StringUtils::TruncateUtf16String(textConfig_.inputAttribute.placeholder, MAX_PLACEHOLDER_SIZE);
248         StringUtils::TruncateUtf16String(textConfig_.inputAttribute.abilityName, MAX_ABILITY_NAME_SIZE);
249     }
250     if (textConfig.range.start != INVALID_VALUE) {
251         std::lock_guard<std::mutex> lock(editorContentLock_);
252         selectOldBegin_ = selectNewBegin_;
253         selectOldEnd_ = selectNewEnd_;
254         selectNewBegin_ = textConfig.range.start;
255         selectNewEnd_ = textConfig.range.end;
256     }
257 }
258 
Attach(sptr<OnTextChangedListener> listener,ClientType type)259 int32_t InputMethodController::Attach(sptr<OnTextChangedListener> listener, ClientType type)
260 {
261     return Attach(listener, true, type);
262 }
263 
Attach(sptr<OnTextChangedListener> listener,bool isShowKeyboard,ClientType type)264 int32_t InputMethodController::Attach(sptr<OnTextChangedListener> listener, bool isShowKeyboard, ClientType type)
265 {
266     InputAttribute attribute;
267     attribute.inputPattern = InputAttribute::PATTERN_TEXT;
268     return Attach(listener, isShowKeyboard, attribute, type);
269 }
270 
Attach(sptr<OnTextChangedListener> listener,bool isShowKeyboard,const InputAttribute & attribute,ClientType type)271 int32_t InputMethodController::Attach(
272     sptr<OnTextChangedListener> listener, bool isShowKeyboard, const InputAttribute &attribute, ClientType type)
273 {
274     InputMethodSyncTrace tracer("InputMethodController Attach trace.");
275     TextConfig textConfig;
276     textConfig.inputAttribute = attribute;
277     return Attach(listener, isShowKeyboard, textConfig, type);
278 }
279 
Attach(sptr<OnTextChangedListener> listener,bool isShowKeyboard,const TextConfig & textConfig,ClientType type)280 int32_t InputMethodController::Attach(
281     sptr<OnTextChangedListener> listener, bool isShowKeyboard, const TextConfig &textConfig, ClientType type)
282 {
283     AttachOptions attachOptions;
284     attachOptions.isShowKeyboard = isShowKeyboard;
285     attachOptions.requestKeyboardReason = RequestKeyboardReason::NONE;
286     return Attach(listener, attachOptions, textConfig, type);
287 }
288 
IsValidTextConfig(const TextConfig & textConfig)289 int32_t InputMethodController::IsValidTextConfig(const TextConfig &textConfig)
290 {
291     if (textConfig.inputAttribute.immersiveMode < static_cast<int32_t>(ImmersiveMode::NONE_IMMERSIVE) ||
292         textConfig.inputAttribute.immersiveMode >= static_cast<int32_t>(ImmersiveMode::END)) {
293         IMSA_HILOGE("invalid immersiveMode: %{public}d", textConfig.inputAttribute.immersiveMode);
294         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
295     }
296     if (textConfig.inputAttribute.gradientMode < static_cast<int32_t>(GradientMode::NONE) ||
297         textConfig.inputAttribute.gradientMode >= static_cast<int32_t>(GradientMode::END)) {
298         IMSA_HILOGW("invalid gradientMode: %{public}d", textConfig.inputAttribute.gradientMode);
299     }
300     if (textConfig.inputAttribute.fluidLightMode < static_cast<int32_t>(FluidLightMode::NONE) ||
301         textConfig.inputAttribute.fluidLightMode >= static_cast<int32_t>(FluidLightMode::END)) {
302         IMSA_HILOGW("invalid fluidLightMode: %{public}d", textConfig.inputAttribute.fluidLightMode);
303     }
304     return ErrorCode::NO_ERROR;
305 }
306 
Attach(sptr<OnTextChangedListener> listener,const AttachOptions & attachOptions,const TextConfig & textConfig,ClientType type)307 int32_t InputMethodController::Attach(sptr<OnTextChangedListener> listener, const AttachOptions &attachOptions,
308     const TextConfig &textConfig, ClientType type)
309 {
310     IMSA_HILOGI("isShowKeyboard %{public}d.", attachOptions.isShowKeyboard);
311     InputMethodSyncTrace tracer("InputMethodController Attach with textConfig trace.");
312     if (IsValidTextConfig(textConfig) != ErrorCode::NO_ERROR) {
313         IMSA_HILOGE("invalid textConfig.");
314         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
315     }
316     auto lastListener = GetTextListener();
317     clientInfo_.isNotifyInputStart = lastListener != listener;
318     if (clientInfo_.isNotifyInputStart) {
319         sessionId_++;
320     }
321     IMSA_HILOGD("sessionId_ %{public}u", sessionId_.load());
322     if (clientInfo_.isNotifyInputStart && lastListener != nullptr) {
323         lastListener->OnDetachV2();
324     }
325     ClearEditorCache(clientInfo_.isNotifyInputStart, lastListener);
326     SetTextListener(listener);
327     {
328         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
329         clientInfo_.isShowKeyboard = attachOptions.isShowKeyboard;
330     }
331     SaveTextConfig(textConfig);
332     GetTextConfig(clientInfo_.config);
333     clientInfo_.requestKeyboardReason = attachOptions.requestKeyboardReason;
334     clientInfo_.type = type;
335     std::vector<sptr<IRemoteObject>> agents;
336     std::vector<BindImeInfo> imeInfos;
337     int32_t ret = StartInput(clientInfo_, agents, imeInfos);
338     if (ret != ErrorCode::NO_ERROR) {
339         auto evenInfo = HiSysOriginalInfo::Builder()
340                             .SetErrCode(ret)
341                             .SetInputPattern(textConfig.inputAttribute.inputPattern)
342                             .SetIsShowKeyboard(attachOptions.isShowKeyboard)
343                             .SetClientType(type)
344                             .Build();
345         ImcHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_ATTACH, *evenInfo);
346         SetTextListener(nullptr);
347         return ret;
348     }
349     clientInfo_.state = ClientState::ACTIVE;
350     SetInputReady(agents, imeInfos);
351     if (attachOptions.isShowKeyboard) {
352         InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_ATTACH);
353     }
354     IMSA_HILOGI("bind imf successfully.");
355     return ErrorCode::NO_ERROR;
356 }
357 
ShowTextInputInner(const AttachOptions & attachOptions,ClientType type)358 int32_t InputMethodController::ShowTextInputInner(const AttachOptions &attachOptions, ClientType type)
359 {
360     InputMethodSyncTrace tracer("IMC_ShowTextInput");
361     if (!IsBound()) {
362         IMSA_HILOGE("not bound!");
363         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
364     }
365     IMSA_HILOGI("start.");
366     {
367         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
368         clientInfo_.isShowKeyboard = true;
369     }
370     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_ENEDITABLE);
371     int32_t ret = ShowInput(clientInfo_.client, type, static_cast<int32_t>(attachOptions.requestKeyboardReason));
372     if (ret != ErrorCode::NO_ERROR) {
373         IMSA_HILOGE("failed to start input: %{public}d", ret);
374         return ret;
375     }
376     isEditable_.store(true);
377     IMSA_HILOGI("enter editable state.");
378     return ret;
379 }
380 
HideTextInput()381 int32_t InputMethodController::HideTextInput()
382 {
383     InputMethodSyncTrace tracer("IMC_HideTextInput");
384     if (!IsBound()) {
385         IMSA_HILOGE("not bound!");
386         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
387     }
388     IMSA_HILOGI("start.");
389     isEditable_.store(false);
390     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNEDITABLE);
391     return HideInput(clientInfo_.client);
392 }
393 
HideCurrentInput()394 int32_t InputMethodController::HideCurrentInput()
395 {
396     InputMethodSyncTrace tracer("IMC_HideCurrentInput");
397     IMSA_HILOGD("InputMethodController::HideCurrentInput");
398     if (!IsEditable()) {
399         IMSA_HILOGD("not editable.");
400         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
401     }
402     auto proxy = GetSystemAbilityProxy();
403     if (proxy == nullptr) {
404         IMSA_HILOGE("proxy is nullptr!");
405         return ErrorCode::ERROR_EX_NULL_POINTER;
406     }
407     {
408         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
409         clientInfo_.isShowKeyboard = false;
410     }
411     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_NORMAL);
412     return proxy->HideCurrentInputDeprecated();
413 }
414 
ShowCurrentInput()415 int32_t InputMethodController::ShowCurrentInput()
416 {
417     InputMethodSyncTrace tracer("IMC_ShowCurrentInput");
418     if (!IsEditable()) {
419         IMSA_HILOGD("not editable.");
420         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
421     }
422     auto proxy = GetSystemAbilityProxy();
423     if (proxy == nullptr) {
424         IMSA_HILOGE("proxy is nullptr!");
425         return ErrorCode::ERROR_EX_NULL_POINTER;
426     }
427     IMSA_HILOGI("start.");
428     {
429         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
430         clientInfo_.isShowKeyboard = true;
431     }
432     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_NORMAL);
433     return proxy->ShowCurrentInputDeprecated();
434 }
435 
Close()436 int32_t InputMethodController::Close()
437 {
438     if (IsBound()) {
439         IMSA_HILOGI("start.");
440     }
441 
442     auto listener = GetTextListener();
443     if (listener != nullptr) {
444         listener->OnDetachV2();
445     }
446     OperateIMEInfoCode infoCode = OperateIMEInfoCode::IME_UNBIND;
447     {
448         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
449         if (clientInfo_.isShowKeyboard) {
450             infoCode = OperateIMEInfoCode::IME_HIDE_UNBIND;
451         }
452     }
453     InputMethodSyncTrace tracer("InputMethodController Close trace.");
454     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(infoCode);
455     return ReleaseInput(clientInfo_.client);
456 }
457 
Reset()458 void InputMethodController::Reset()
459 {
460     Close();
461     RemoveDeathRecipient();
462 }
463 
RequestShowInput()464 int32_t InputMethodController::RequestShowInput()
465 {
466     auto proxy = GetSystemAbilityProxy();
467     if (proxy == nullptr) {
468         IMSA_HILOGE("proxy is nullptr!");
469         return ErrorCode::ERROR_SERVICE_START_FAILED; // ERROR_EX_NULL_POINTER
470     }
471     IMSA_HILOGD("InputMethodController start.");
472     return proxy->RequestShowInput();
473 }
474 
RequestHideInput(bool isFocusTriggered)475 int32_t InputMethodController::RequestHideInput(bool isFocusTriggered)
476 {
477     auto proxy = TryGetSystemAbilityProxy();
478     if (proxy == nullptr) {
479         IMSA_HILOGE("proxy is nullptr!");
480         return ErrorCode::ERROR_EX_NULL_POINTER;
481     }
482     IMSA_HILOGD("InputMethodController start.");
483     return proxy->RequestHideInput(isFocusTriggered);
484 }
485 
DisplayOptionalInputMethod()486 int32_t InputMethodController::DisplayOptionalInputMethod()
487 {
488     IMSA_HILOGD("InputMethodController::DisplayOptionalInputMethod start.");
489     auto proxy = GetSystemAbilityProxy();
490     if (proxy == nullptr) {
491         IMSA_HILOGE("proxy is nullptr!");
492         return ErrorCode::ERROR_EX_NULL_POINTER;
493     }
494     return proxy->DisplayOptionalInputMethod();
495 }
496 
WasAttached()497 bool InputMethodController::WasAttached()
498 {
499     return isBound_.load();
500 }
501 
GetInputStartInfo(bool & isInputStart,uint32_t & callingWndId,int32_t & requestKeyboardReason)502 int32_t InputMethodController::GetInputStartInfo(bool &isInputStart,
503     uint32_t &callingWndId, int32_t &requestKeyboardReason)
504 {
505     auto proxy = GetSystemAbilityProxy();
506     if (proxy == nullptr) {
507         IMSA_HILOGE("proxy is nullptr!");
508         return false;
509     }
510     return proxy->GetInputStartInfo(isInputStart, callingWndId, requestKeyboardReason);
511 }
512 
ListInputMethodCommon(InputMethodStatus status,std::vector<Property> & props)513 int32_t InputMethodController::ListInputMethodCommon(InputMethodStatus status, std::vector<Property> &props)
514 {
515     IMSA_HILOGD("InputMethodController::ListInputMethodCommon start.");
516     auto proxy = GetSystemAbilityProxy();
517     if (proxy == nullptr) {
518         IMSA_HILOGE("proxy is nullptr!");
519         return ErrorCode::ERROR_EX_NULL_POINTER;
520     }
521     return proxy->ListInputMethod(status, props);
522 }
523 
ListInputMethod(std::vector<Property> & props)524 int32_t InputMethodController::ListInputMethod(std::vector<Property> &props)
525 {
526     IMSA_HILOGD("InputMethodController::listInputMethod start.");
527     return ListInputMethodCommon(ALL, props);
528 }
529 
ListInputMethod(bool enable,std::vector<Property> & props)530 int32_t InputMethodController::ListInputMethod(bool enable, std::vector<Property> &props)
531 {
532     IMSA_HILOGI("enable: %{public}s.", enable ? "ENABLE" : "DISABLE");
533     return ListInputMethodCommon(enable ? ENABLE : DISABLE, props);
534 }
535 
GetDefaultInputMethod(std::shared_ptr<Property> & property)536 int32_t InputMethodController::GetDefaultInputMethod(std::shared_ptr<Property> &property)
537 {
538     InputMethodSyncTrace tracer("IMC_GetDefaultInputMethod");
539     IMSA_HILOGD("InputMethodController::GetDefaultInputMethod start.");
540     auto proxy = GetSystemAbilityProxy();
541     if (proxy == nullptr) {
542         IMSA_HILOGE("proxy is nullptr!");
543         return ErrorCode::ERROR_SERVICE_START_FAILED;
544     }
545     Property prop;
546     auto ret = proxy->GetDefaultInputMethod(prop, false);
547     if (ret != ErrorCode::NO_ERROR) {
548         return ret;
549     }
550     property = std::make_shared<Property>(prop);
551     return ret;
552 }
553 
GetInputMethodConfig(OHOS::AppExecFwk::ElementName & inputMethodConfig)554 int32_t InputMethodController::GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig)
555 {
556     InputMethodSyncTrace tracer("IMC_GetInputMethodConfig");
557     IMSA_HILOGD("InputMethodController::inputMethodConfig start.");
558     auto proxy = GetSystemAbilityProxy();
559     if (proxy == nullptr) {
560         IMSA_HILOGE("proxy is nullptr!");
561         return ErrorCode::ERROR_SERVICE_START_FAILED;
562     }
563     return proxy->GetInputMethodConfig(inputMethodConfig);
564 }
565 
GetCurrentInputMethod()566 std::shared_ptr<Property> InputMethodController::GetCurrentInputMethod()
567 {
568     InputMethodSyncTrace tracer("IMC_GetCurrentInputMethod");
569     IMSA_HILOGD("InputMethodController::GetCurrentInputMethod start.");
570     auto proxy = GetSystemAbilityProxy();
571     if (proxy == nullptr) {
572         IMSA_HILOGE("proxy is nullptr!");
573         return nullptr;
574     }
575     Property propertyData;
576     proxy->GetCurrentInputMethod(propertyData);
577     auto property = std::make_shared<Property>(propertyData);
578     return property;
579 }
580 
GetCurrentInputMethodSubtype()581 std::shared_ptr<SubProperty> InputMethodController::GetCurrentInputMethodSubtype()
582 {
583     InputMethodSyncTrace tracer("IMC_GetCurrentInputMethodSubtype");
584     IMSA_HILOGD("InputMethodController::GetCurrentInputMethodSubtype start.");
585     auto proxy = GetSystemAbilityProxy();
586     if (proxy == nullptr) {
587         IMSA_HILOGE("proxy is nullptr!");
588         return nullptr;
589     }
590     SubProperty subPropertyData;
591     proxy->GetCurrentInputMethodSubtype(subPropertyData);
592     auto subProperty = std::make_shared<SubProperty>(subPropertyData);
593     return subProperty;
594 }
595 
IsDefaultImeSet()596 bool InputMethodController::IsDefaultImeSet()
597 {
598     IMSA_HILOGI("enter.");
599     auto proxy = GetSystemAbilityProxy();
600     if (proxy == nullptr) {
601         IMSA_HILOGE("proxy is nullptr!");
602         return false;
603     }
604     bool ret = false;
605     proxy->IsDefaultImeSet(ret);
606     return ret;
607 }
608 
EnableIme(const std::string & bundleName,const std::string & extensionName,EnabledStatus status)609 int32_t InputMethodController::EnableIme(
610     const std::string &bundleName, const std::string &extensionName, EnabledStatus status)
611 {
612     IMSA_HILOGI("enter.");
613     auto proxy = GetSystemAbilityProxy();
614     if (proxy == nullptr) {
615         IMSA_HILOGE("proxy is nullptr!");
616         return false;
617     }
618     return proxy->EnableIme(bundleName, extensionName, static_cast<int32_t>(status));
619 }
620 
StartInput(InputClientInfo & inputClientInfo,std::vector<sptr<IRemoteObject>> & agents,std::vector<BindImeInfo> & imeInfos)621 int32_t InputMethodController::StartInput(
622     InputClientInfo &inputClientInfo, std::vector<sptr<IRemoteObject>> &agents, std::vector<BindImeInfo> &imeInfos)
623 {
624     IMSA_HILOGD("InputMethodController::StartInput start.");
625     auto proxy = GetSystemAbilityProxy();
626     if (proxy == nullptr) {
627         IMSA_HILOGE("proxy is nullptr!");
628         return ErrorCode::ERROR_SERVICE_START_FAILED;
629     }
630     InputClientInfoInner inner = InputMethodTools::GetInstance().InputClientInfoToInner(inputClientInfo);
631     int32_t ret = proxy->StartInput(inner, agents, imeInfos);
632     return ret;
633 }
634 
ReleaseInput(sptr<IInputClient> & client)635 int32_t InputMethodController::ReleaseInput(sptr<IInputClient> &client)
636 {
637     IMSA_HILOGD("InputMethodController::ReleaseInput start.");
638     auto proxy = TryGetSystemAbilityProxy();
639     if (proxy == nullptr) {
640         IMSA_HILOGE("proxy is nullptr!");
641         return ErrorCode::ERROR_SERVICE_START_FAILED;
642     }
643     int32_t ret = proxy->ReleaseInput(client, sessionId_.load());
644     if (ret == ErrorCode::NO_ERROR) {
645         OnInputStop();
646     }
647     SetTextListener(nullptr);
648     return ret;
649 }
650 
ShowInput(sptr<IInputClient> & client,ClientType type,int32_t requestKeyboardReason)651 int32_t InputMethodController::ShowInput(sptr<IInputClient> &client, ClientType type, int32_t requestKeyboardReason)
652 {
653     IMSA_HILOGD("InputMethodController::ShowInput start.");
654     auto proxy = GetSystemAbilityProxy();
655     if (proxy == nullptr) {
656         IMSA_HILOGE("proxy is nullptr!");
657         return ErrorCode::ERROR_SERVICE_START_FAILED;
658     }
659     return proxy->ShowInput(client, type, requestKeyboardReason);
660 }
661 
HideInput(sptr<IInputClient> & client)662 int32_t InputMethodController::HideInput(sptr<IInputClient> &client)
663 {
664     IMSA_HILOGD("InputMethodController::HideInput start.");
665     auto proxy = GetSystemAbilityProxy();
666     if (proxy == nullptr) {
667         IMSA_HILOGE("proxy is nullptr!");
668         return ErrorCode::ERROR_SERVICE_START_FAILED;
669     }
670     return proxy->HideInput(client);
671 }
672 
OnRemoteSaDied(const wptr<IRemoteObject> & remote)673 void InputMethodController::OnRemoteSaDied(const wptr<IRemoteObject> &remote)
674 {
675     IMSA_HILOGI("input method service death.");
676     // imf sa died, current client callback inputStop
677     ImeEventMonitorManagerImpl::GetInstance().OnInputStop();
678     auto textListener = GetTextListener();
679     if (textListener != nullptr && textConfig_.inputAttribute.isTextPreviewSupported) {
680         IMSA_HILOGD("finish text preview.");
681         textListener->FinishTextPreviewV2();
682     }
683     {
684         std::lock_guard<std::mutex> lock(abilityLock_);
685         abilityManager_ = nullptr;
686     }
687     ClearAgentInfo();
688     if (handler_ == nullptr) {
689         IMSA_HILOGE("handler_ is nullptr!");
690         return;
691     }
692     RestoreClientInfoInSaDied();
693 }
694 
RestoreListenInfoInSaDied()695 void InputMethodController::RestoreListenInfoInSaDied()
696 {
697     {
698         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
699         if (clientInfo_.eventFlag == NO_EVENT_ON) {
700             return;
701         }
702     }
703     isDiedRestoreListen_.store(false);
704     auto restoreListenTask = [=]() {
705         if (isDiedRestoreListen_.load()) {
706             return;
707         }
708         auto ret = RestoreListenEventFlag();
709         if (ret == ErrorCode::NO_ERROR) {
710             isDiedRestoreListen_.store(true);
711             IMSA_HILOGI("try to RestoreListen success.");
712         }
713     };
714     for (int i = 0; i < LOOP_COUNT; i++) {
715         handler_->PostTask(restoreListenTask, "OnRemoteSaDied", DELAY_TIME * (i + 1),
716             AppExecFwk::EventQueue::Priority::VIP);
717     }
718 }
719 
RestoreClientInfoInSaDied()720 void InputMethodController::RestoreClientInfoInSaDied()
721 {
722     if (!IsEditable()) {
723         IMSA_HILOGD("not editable.");
724         RestoreListenInfoInSaDied();
725         return;
726     }
727     auto attach = [=]() -> bool {
728         TextConfig tempConfig {};
729         {
730             std::lock_guard<std::mutex> lock(textConfigLock_);
731             tempConfig = textConfig_;
732             tempConfig.range.start = selectNewBegin_;
733             tempConfig.range.end = selectNewEnd_;
734         }
735         {
736             std::lock_guard<std::mutex> lock(cursorInfoMutex_);
737             tempConfig.cursorInfo = cursorInfo_;
738         }
739         auto listener = GetTextListener();
740         bool isShowKeyboard = false;
741         {
742             std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
743             isShowKeyboard = clientInfo_.isShowKeyboard;
744         }
745         auto errCode = Attach(listener, isShowKeyboard, tempConfig);
746         IMSA_HILOGI("attach end, errCode: %{public}d", errCode);
747         return errCode == ErrorCode::NO_ERROR;
748     };
749     if (attach()) {
750         return;
751     }
752     isDiedAttached_.store(false);
753     auto attachTask = [this, attach]() {
754         if (isDiedAttached_.load()) {
755             return;
756         }
757         attach();
758     };
759     for (int i = 0; i < LOOP_COUNT; i++) {
760         handler_->PostTask(attachTask, "OnRemoteSaDied", DELAY_TIME * (i + 1), AppExecFwk::EventQueue::Priority::VIP);
761     }
762 }
763 
DiscardTypingText()764 int32_t InputMethodController::DiscardTypingText()
765 {
766     if (!IsBound()) {
767         IMSA_HILOGE("not bound.");
768         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
769     }
770 
771     return SendRequestToAllAgents([](std::shared_ptr<IInputMethodAgent> agent) -> int32_t {
772         return agent->DiscardTypingText();
773     });
774 }
775 
OnCursorUpdate(CursorInfo cursorInfo)776 int32_t InputMethodController::OnCursorUpdate(CursorInfo cursorInfo)
777 {
778     if (!IsBound()) {
779         IMSA_HILOGD("not bound.");
780         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
781     }
782     if (!IsEditable()) {
783         IMSA_HILOGD("not editable.");
784         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
785     }
786     uint32_t windowId = 0;
787     {
788         std::lock_guard<std::mutex> lock(textConfigLock_);
789         windowId = textConfig_.windowId;
790     }
791     GetWindowScaleCoordinate(windowId, cursorInfo);
792     {
793         std::lock_guard<std::mutex> lock(textConfigLock_);
794         textConfig_.cursorInfo = cursorInfo;
795     }
796     {
797         std::lock_guard<std::mutex> lk(cursorInfoMutex_);
798         if (cursorInfo_ == cursorInfo) {
799             IMSA_HILOGD("same to last update.");
800             return ErrorCode::NO_ERROR;
801         }
802         cursorInfo_ = cursorInfo;
803     }
804     IMSA_HILOGI("left: %{public}d, top: %{public}d, height: %{public}d.", static_cast<int32_t>(cursorInfo.left),
805         static_cast<int32_t>(cursorInfo.top), static_cast<int32_t>(cursorInfo.height));
806     return SendRequestToAllAgents([cursorInfo](std::shared_ptr<IInputMethodAgent> agent) -> int32_t {
807         agent->OnCursorUpdate(cursorInfo.left, cursorInfo.top, cursorInfo.height);
808         return ErrorCode::NO_ERROR;
809     });
810 }
811 
OnSelectionChange(std::u16string text,int start,int end)812 int32_t InputMethodController::OnSelectionChange(std::u16string text, int start, int end)
813 {
814     if (!IsBound()) {
815         IMSA_HILOGD("not bound.");
816         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
817     }
818     if (!IsEditable()) {
819         IMSA_HILOGD("not editable.");
820         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
821     }
822     {
823         std::lock_guard<std::mutex> lock(textConfigLock_);
824         textConfig_.range.start = start;
825         textConfig_.range.end = end;
826     }
827     {
828         std::lock_guard<std::mutex> lock(editorContentLock_);
829         if (isTextNotified_.exchange(true) && textString_ == text && selectNewBegin_ == start && selectNewEnd_ == end) {
830             IMSA_HILOGD("same to last update.");
831             return ErrorCode::NO_ERROR;
832         }
833         textString_ = text;
834         selectOldBegin_ = selectNewBegin_;
835         selectOldEnd_ = selectNewEnd_;
836         selectNewBegin_ = start;
837         selectNewEnd_ = end;
838     }
839     IMSA_HILOGI("IMC size: %{public}zu, range: %{public}d/%{public}d/%{public}d/%{public}d.", text.size(),
840         selectOldBegin_, selectOldEnd_, start, end);
841     std::string testString = Str16ToStr8(text);
842     return SendRequestToAllAgents(
843         [testString, selectOldBegin = selectOldBegin_, selectOldEnd = selectOldEnd_, selectNewBegin = selectNewBegin_,
844             selectNewEnd = selectNewEnd_](std::shared_ptr<IInputMethodAgent> agent) -> int32_t {
845             agent->OnSelectionChange(testString, selectOldBegin, selectOldEnd, selectNewBegin, selectNewEnd);
846             return ErrorCode::NO_ERROR;
847         });
848 }
849 
OnConfigurationChange(Configuration info)850 int32_t InputMethodController::OnConfigurationChange(Configuration info)
851 {
852     if (!IsBound()) {
853         IMSA_HILOGD("not bound.");
854         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
855     }
856     bool oldSecurityFlag = textConfig_.inputAttribute.GetSecurityFlag();
857     InputAttribute attribute;
858     {
859         std::lock_guard<std::mutex> lock(textConfigLock_);
860         textConfig_.inputAttribute.enterKeyType = static_cast<int32_t>(info.GetEnterKeyType());
861         textConfig_.inputAttribute.inputPattern = static_cast<int32_t>(info.GetTextInputType());
862         attribute = textConfig_.inputAttribute;
863     }
864     if (!IsEditable()) {
865         IMSA_HILOGD("not editable.");
866         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
867     }
868     IMSA_HILOGI(
869         "IMC enterKeyType: %{public}d, textInputType: %{public}d.", attribute.enterKeyType, attribute.inputPattern);
870     if (oldSecurityFlag != attribute.GetSecurityFlag()) {
871         GetTextConfig(clientInfo_.config);
872         std::vector<sptr<IRemoteObject>> agents;
873         std::vector<BindImeInfo> imeInfos;
874         int32_t ret = StartInput(clientInfo_, agents, imeInfos);
875         if (ret != ErrorCode::NO_ERROR) {
876             return ret;
877         }
878         SetInputReady(agents, imeInfos);
879     }
880 
881     auto agent = GetAgent();
882     if (agent == nullptr) {
883         IMSA_HILOGE("agent is nullptr!");
884         return ErrorCode::ERROR_IME_NOT_STARTED;
885     }
886     InputAttributeInner inner = InputMethodTools::GetInstance().AttributeToInner(attribute);
887     agent->OnAttributeChange(inner);
888     return ErrorCode::NO_ERROR;
889 }
890 
GetLeft(int32_t length,std::u16string & text)891 int32_t InputMethodController::GetLeft(int32_t length, std::u16string &text)
892 {
893     InputMethodSyncTrace tracer("IMC_GetForward");
894     IMSA_HILOGD("start, length: %{public}d", length);
895     auto listener = GetTextListener();
896     if (!IsEditable() || listener == nullptr) {
897         IMSA_HILOGE("not editable or listener is nullptr!");
898         ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_GET_TEXT_BEFORE_CURSOR),
899             ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
900         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
901     }
902     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
903     {
904         InputMethodSyncTrace aceTracer("ACE_GetForward");
905         text = listener->GetLeftTextOfCursorV2(length);
906     }
907     PrintLogIfAceTimeout(start);
908     return ErrorCode::NO_ERROR;
909 }
910 
GetRight(int32_t length,std::u16string & text)911 int32_t InputMethodController::GetRight(int32_t length, std::u16string &text)
912 {
913     IMSA_HILOGD("start, length: %{public}d", length);
914     auto listener = GetTextListener();
915     if (!IsEditable() || listener == nullptr) {
916         IMSA_HILOGE("not editable or textListener_ is nullptr!");
917         ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_GET_TEXT_AFTER_CURSOR),
918             ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
919         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
920     }
921     text = listener->GetRightTextOfCursorV2(length);
922     return ErrorCode::NO_ERROR;
923 }
924 
GetTextIndexAtCursor(int32_t & index)925 int32_t InputMethodController::GetTextIndexAtCursor(int32_t &index)
926 {
927     IMSA_HILOGD("start.");
928     auto listener = GetTextListener();
929     if (!IsEditable() || listener == nullptr) {
930         IMSA_HILOGE("not editable or textListener_ is nullptr!");
931         ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_GET_TEXT_INDEX_AT_CURSOR),
932             ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
933         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
934     }
935     index = listener->GetTextIndexAtCursorV2();
936     return ErrorCode::NO_ERROR;
937 }
938 
PrintKeyEventLog()939 void InputMethodController::PrintKeyEventLog()
940 {
941     std::lock_guard<std::mutex> lock(logLock_);
942     auto now = system_clock::now();
943     if (keyEventCountInPeriod_ == 0) {
944         startLogTime_ = now;
945     }
946     keyEventCountInPeriod_++;
947     if (std::chrono::duration_cast<seconds>(now - startLogTime_).count() >= LOG_MAX_TIME) {
948         auto start = std::chrono::duration_cast<seconds>(startLogTime_.time_since_epoch()).count();
949         auto end = std::chrono::duration_cast<seconds>(now.time_since_epoch()).count();
950         IMSA_HILOGI("KeyEventCountInPeriod: %{public}d, startTime: %{public}lld, endTime: %{public}lld",
951             keyEventCountInPeriod_, start, end);
952         keyEventCountInPeriod_ = 0;
953     }
954 }
955 
DispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent,KeyEventCallback callback)956 int32_t InputMethodController::DispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent, KeyEventCallback callback)
957 {
958     PrintKeyEventLog();
959     KeyEventInfo keyEventInfo = { std::chrono::system_clock::now(), keyEvent };
960     keyEventQueue_.Push(keyEventInfo);
961     InputMethodSyncTrace tracer("DispatchKeyEvent trace");
962     keyEventQueue_.Wait(keyEventInfo);
963     if (!IsEditable()) {
964         IMSA_HILOGD("not editable.");
965         keyEventQueue_.Pop();
966         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
967     }
968     if (keyEvent == nullptr) {
969         IMSA_HILOGE("keyEvent is nullptr!");
970         keyEventQueue_.Pop();
971         return ErrorCode::ERROR_EX_NULL_POINTER;
972     }
973     auto agent = GetAgent();
974     if (agent == nullptr) {
975         IMSA_HILOGE("agent is nullptr!");
976         keyEventQueue_.Pop();
977         return ErrorCode::ERROR_IME_NOT_STARTED;
978     }
979     IMSA_HILOGD("start.");
980     sptr<IRemoteObject> channelObject = nullptr;
981     {
982         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
983         channelObject = clientInfo_.channel;
984     }
985     if (channelObject == nullptr) {
986         IMSA_HILOGE("channelObject is nullptr!");
987         keyEventQueue_.Pop();
988         return ErrorCode::ERROR_EX_NULL_POINTER;
989     }
990     auto cbId = keyEventRetHandler_.AddKeyEventCbInfo({ keyEvent, callback });
991     KeyEventValue keyEventValue;
992     keyEventValue.event = keyEvent;
993     auto ret = agent->DispatchKeyEvent(keyEventValue, cbId, channelObject);
994     if (ret != ErrorCode::NO_ERROR) {
995         IMSA_HILOGE("failed to DispatchKeyEvent: %{public}d", ret);
996         keyEventRetHandler_.RemoveKeyEventCbInfo(cbId);
997     }
998     keyEventQueue_.Pop();
999     return ret;
1000 }
1001 
HandleKeyEventResult(uint64_t cbId,bool consumeResult)1002 void InputMethodController::HandleKeyEventResult(uint64_t cbId, bool consumeResult)
1003 {
1004     keyEventRetHandler_.HandleKeyEventResult(cbId, consumeResult);
1005 }
1006 
GetEnterKeyType(int32_t & keyType)1007 int32_t InputMethodController::GetEnterKeyType(int32_t &keyType)
1008 {
1009     IMSA_HILOGD("InputMethodController::GetEnterKeyType start.");
1010     std::lock_guard<std::mutex> lock(textConfigLock_);
1011     keyType = textConfig_.inputAttribute.enterKeyType;
1012     return ErrorCode::NO_ERROR;
1013 }
1014 
GetInputPattern(int32_t & inputpattern)1015 int32_t InputMethodController::GetInputPattern(int32_t &inputpattern)
1016 {
1017     IMSA_HILOGD("InputMethodController::GetInputPattern start.");
1018     std::lock_guard<std::mutex> lock(textConfigLock_);
1019     inputpattern = textConfig_.inputAttribute.inputPattern;
1020     return ErrorCode::NO_ERROR;
1021 }
1022 
GetTextConfig(TextTotalConfig & config)1023 int32_t InputMethodController::GetTextConfig(TextTotalConfig &config)
1024 {
1025     std::lock_guard<std::mutex> lock(textConfigLock_);
1026     config.inputAttribute = textConfig_.inputAttribute;
1027     config.cursorInfo = textConfig_.cursorInfo;
1028     config.windowId = textConfig_.windowId;
1029     config.positionY = textConfig_.positionY;
1030     config.height = textConfig_.height;
1031     config.privateCommand = textConfig_.privateCommand;
1032     config.abilityToken = textConfig_.abilityToken;
1033     if (textConfig_.range.start == INVALID_VALUE) {
1034         IMSA_HILOGD("SelectionRange is invalid.");
1035     } else {
1036         {
1037             std::lock_guard<std::mutex> editorLock(editorContentLock_);
1038             config.textSelection.oldBegin = selectOldBegin_;
1039             config.textSelection.oldEnd = selectOldEnd_;
1040         }
1041         config.textSelection.newBegin = textConfig_.range.start;
1042         config.textSelection.newEnd = textConfig_.range.end;
1043     }
1044     IMSA_HILOGD("textConfig: %{public}s.", config.ToString().c_str());
1045     return ErrorCode::NO_ERROR;
1046 }
1047 
SetCallingWindow(uint32_t windowId)1048 int32_t InputMethodController::SetCallingWindow(uint32_t windowId)
1049 {
1050     if (!IsBound()) {
1051         IMSA_HILOGD("not bound.");
1052         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
1053     }
1054     if (!IsEditable()) {
1055         IMSA_HILOGD("not editable.");
1056         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1057     }
1058     {
1059         std::lock_guard<std::mutex> lock(textConfigLock_);
1060         textConfig_.windowId = windowId;
1061     }
1062     auto agent = GetAgent();
1063     if (agent == nullptr) {
1064         IMSA_HILOGE("agent is nullptr!");
1065         return ErrorCode::ERROR_IME_NOT_STARTED;
1066     }
1067     IMSA_HILOGI("windowId: %{public}d.", windowId);
1068     agent->SetCallingWindow(windowId);
1069     auto proxy = GetSystemAbilityProxy();
1070     if (proxy != nullptr) {
1071         proxy->SetCallingWindow(windowId, clientInfo_.client);
1072     }
1073     return ErrorCode::NO_ERROR;
1074 }
1075 
ShowSoftKeyboardInner(ClientType type)1076 int32_t InputMethodController::ShowSoftKeyboardInner(ClientType type)
1077 {
1078     auto proxy = GetSystemAbilityProxy();
1079     if (proxy == nullptr) {
1080         IMSA_HILOGE("proxy is nullptr!");
1081         return ErrorCode::ERROR_SERVICE_START_FAILED;
1082     }
1083     IMSA_HILOGI("start.");
1084     {
1085         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1086         clientInfo_.isShowKeyboard = true;
1087     }
1088     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_NORMAL);
1089     return proxy->ShowCurrentInput(type);
1090 }
1091 
HideSoftKeyboard()1092 int32_t InputMethodController::HideSoftKeyboard()
1093 {
1094     auto proxy = GetSystemAbilityProxy();
1095     if (proxy == nullptr) {
1096         IMSA_HILOGE("proxy is nullptr!");
1097         return ErrorCode::ERROR_EX_NULL_POINTER;
1098     }
1099     IMSA_HILOGI("start.");
1100     {
1101         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1102         clientInfo_.isShowKeyboard = false;
1103     }
1104     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_NORMAL);
1105     return proxy->HideCurrentInput();
1106 }
1107 
StopInputSession()1108 int32_t InputMethodController::StopInputSession()
1109 {
1110     IMSA_HILOGI("start.");
1111     isEditable_.store(false);
1112     auto proxy = GetSystemAbilityProxy();
1113     if (proxy == nullptr) {
1114         IMSA_HILOGE("proxy is nullptr!");
1115         return ErrorCode::ERROR_EX_NULL_POINTER;
1116     }
1117     return proxy->StopInputSession();
1118 }
1119 
ShowOptionalInputMethod()1120 int32_t InputMethodController::ShowOptionalInputMethod()
1121 {
1122     auto proxy = GetSystemAbilityProxy();
1123     if (proxy == nullptr) {
1124         IMSA_HILOGE("proxy is nullptr!");
1125         return ErrorCode::ERROR_EX_NULL_POINTER;
1126     }
1127     IMSA_HILOGI("IMC start.");
1128     return proxy->DisplayOptionalInputMethod();
1129 }
1130 
ListInputMethodSubtype(const Property & property,std::vector<SubProperty> & subProps)1131 int32_t InputMethodController::ListInputMethodSubtype(const Property &property, std::vector<SubProperty> &subProps)
1132 {
1133     auto proxy = GetSystemAbilityProxy();
1134     if (proxy == nullptr) {
1135         IMSA_HILOGE("proxy is nullptr!");
1136         return ErrorCode::ERROR_EX_NULL_POINTER;
1137     }
1138     IMSA_HILOGD("ime bundleName: %{public}s.", property.name.c_str());
1139     return proxy->ListInputMethodSubtype(property.name, subProps);
1140 }
1141 
ListCurrentInputMethodSubtype(std::vector<SubProperty> & subProps)1142 int32_t InputMethodController::ListCurrentInputMethodSubtype(std::vector<SubProperty> &subProps)
1143 {
1144     auto proxy = GetSystemAbilityProxy();
1145     if (proxy == nullptr) {
1146         IMSA_HILOGE("proxy is nullptr!");
1147         return ErrorCode::ERROR_EX_NULL_POINTER;
1148     }
1149     IMSA_HILOGD("start.");
1150     return proxy->ListCurrentInputMethodSubtype(subProps);
1151 }
1152 
SwitchInputMethod(SwitchTrigger trigger,const std::string & name,const std::string & subName)1153 int32_t InputMethodController::SwitchInputMethod(
1154     SwitchTrigger trigger, const std::string &name, const std::string &subName)
1155 {
1156     InputMethodSyncTrace tracer("IMC_SwitchInputMethod");
1157     auto proxy = GetSystemAbilityProxy();
1158     if (proxy == nullptr) {
1159         IMSA_HILOGE("proxy is nullptr!");
1160         return ErrorCode::ERROR_EX_NULL_POINTER;
1161     }
1162     IMSA_HILOGI("name: %{public}s, subName: %{public}s, trigger: %{public}d.", name.c_str(), subName.c_str(),
1163         static_cast<uint32_t>(trigger));
1164         return proxy->SwitchInputMethod(name, subName, static_cast<uint32_t>(trigger));
1165 }
1166 
SetSimpleKeyboardEnabled(bool enable)1167 int32_t InputMethodController::SetSimpleKeyboardEnabled(bool enable)
1168 {
1169     InputMethodSyncTrace tracer("IMC_SetSimpleKeyboardEnabled");
1170     std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1171     clientInfo_.config.isSimpleKeyboardEnabled = enable;
1172     return ErrorCode::NO_ERROR;
1173 }
1174 
OnInputReady(sptr<IRemoteObject> agentObject,const BindImeInfo & imeInfo)1175 void InputMethodController::OnInputReady(sptr<IRemoteObject> agentObject, const BindImeInfo &imeInfo)
1176 {
1177     IMSA_HILOGI("InputMethodController start.");
1178     if (imeInfo.bundleName != IME_MIRROR_NAME) {
1179         SetBindImeInfo(std::make_pair(imeInfo.pid, imeInfo.bundleName));
1180         isBound_.store(true);
1181         isEditable_.store(true);
1182     } else {
1183         IMSA_HILOGI("[ImeMirrorTag] proxyIme_IME_MIRROR no need to set bindImeInfo");
1184     }
1185 
1186     if (agentObject == nullptr) {
1187         IMSA_HILOGE("agentObject is nullptr!");
1188         return;
1189     }
1190     SetAgent(agentObject, imeInfo.bundleName);
1191 }
1192 
SetInputReady(const std::vector<sptr<IRemoteObject>> & agentObjects,const std::vector<BindImeInfo> & imeInfos)1193 void InputMethodController::SetInputReady(
1194     const std::vector<sptr<IRemoteObject>> &agentObjects, const std::vector<BindImeInfo> &imeInfos)
1195 {
1196     if (agentObjects.size() != imeInfos.size()) {
1197         IMSA_HILOGE("[ImeMirrorTag]agentObjects.size() != imeInfos.size()!");
1198         return;
1199     }
1200     for (size_t i = 0; i < agentObjects.size(); i++) {
1201         OnInputReady(agentObjects[i], imeInfos[i]);
1202     }
1203 }
1204 
OnInputStop(bool isStopInactiveClient,sptr<IRemoteObject> proxy)1205 void InputMethodController::OnInputStop(bool isStopInactiveClient, sptr<IRemoteObject> proxy)
1206 {
1207     ClearAgentInfo();
1208     auto listener = GetTextListener();
1209     if (listener != nullptr) {
1210         IMSA_HILOGD("listener is not nullptr!");
1211         if (textConfig_.inputAttribute.isTextPreviewSupported) {
1212             IMSA_HILOGD("finish text preview.");
1213             listener->FinishTextPreviewV2();
1214         }
1215         if (!isStopInactiveClient || !listener->IsFromTs()) {
1216             listener->SendKeyboardStatusV2(KeyboardStatus::HIDE);
1217         }
1218     }
1219     isBound_.store(false);
1220     isEditable_.store(false);
1221     isTextNotified_.store(false);
1222     keyEventRetHandler_.ClearKeyEventCbInfo();
1223     {
1224         std::lock_guard<std::mutex> lock(editorContentLock_);
1225         textString_ = Str8ToStr16("");
1226         selectOldBegin_ = INVALID_VALUE;
1227         selectOldEnd_ = INVALID_VALUE;
1228         selectNewBegin_ = INVALID_VALUE;
1229         selectNewEnd_ = INVALID_VALUE;
1230     }
1231     if (proxy == nullptr) {
1232         IMSA_HILOGD("proxy is nullptr.");
1233         return;
1234     }
1235     auto channelProxy = std::make_shared<OnInputStopNotifyProxy>(proxy);
1236     channelProxy->NotifyOnInputStopFinished();
1237 }
1238 
OnImeMirrorStop(sptr<IRemoteObject> object)1239 void InputMethodController::OnImeMirrorStop(sptr<IRemoteObject> object)
1240 {
1241     std::lock_guard guard(agentLock_);
1242     auto pos = find_if(agentInfoList_.begin(), agentInfoList_.end(), [object](const AgentInfo &agentInfo) {
1243         return agentInfo.agentObject == object;
1244     });
1245     if (pos == agentInfoList_.end()) {
1246         IMSA_HILOGE("[ImeMirrorTag] object is not in agentInfoList.");
1247         return;
1248     }
1249     pos->agentObject = nullptr;
1250     pos->agent = nullptr;
1251     agentInfoList_.erase(pos);
1252     IMSA_HILOGI("[ImeMirrorTag]remove agent");
1253 }
1254 
ClearEditorCache(bool isNewEditor,sptr<OnTextChangedListener> lastListener)1255 void InputMethodController::ClearEditorCache(bool isNewEditor, sptr<OnTextChangedListener> lastListener)
1256 {
1257     IMSA_HILOGD("isNewEditor: %{public}d.", isNewEditor);
1258     if (isNewEditor && isBound_.load() && lastListener != nullptr &&
1259         textConfig_.inputAttribute.isTextPreviewSupported) {
1260         IMSA_HILOGD("last editor FinishTextPreview");
1261         lastListener->FinishTextPreviewV2();
1262     }
1263     {
1264         std::lock_guard<std::mutex> lock(editorContentLock_);
1265         // reset old range when editor changes or first attach
1266         if (isNewEditor || !isBound_.load()) {
1267             isTextNotified_.store(false);
1268             textString_ = Str8ToStr16("");
1269             selectOldBegin_ = INVALID_VALUE;
1270             selectOldEnd_ = INVALID_VALUE;
1271             selectNewBegin_ = INVALID_VALUE;
1272             selectNewEnd_ = INVALID_VALUE;
1273         }
1274     }
1275     {
1276         std::lock_guard<std::mutex> lock(textConfigLock_);
1277         textConfig_ = {};
1278     }
1279     {
1280         std::lock_guard<std::mutex> lock(cursorInfoMutex_);
1281         cursorInfo_ = {};
1282     }
1283     {
1284         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1285         auto isSimpleKeyboardEnabled = clientInfo_.config.isSimpleKeyboardEnabled;
1286         clientInfo_.config = {};
1287         clientInfo_.config.isSimpleKeyboardEnabled = isSimpleKeyboardEnabled; // global scope
1288     }
1289 }
1290 
SelectByRange(int32_t start,int32_t end)1291 void InputMethodController::SelectByRange(int32_t start, int32_t end)
1292 {
1293     IMSA_HILOGD("InputMethodController start: %{public}d, end: %{public}d.", start, end);
1294     auto listener = GetTextListener();
1295     if (IsEditable() && listener != nullptr) {
1296         listener->HandleSetSelectionV2(start, end);
1297     } else {
1298         IMSA_HILOGE("not editable or textListener_ is nullptr!");
1299     }
1300 
1301     if (controllerListener_ != nullptr) {
1302         controllerListener_->OnSelectByRange(start, end);
1303     } else {
1304         IMSA_HILOGE("controllerListener_ is nullptr!");
1305     }
1306 }
1307 
SelectByMovement(int32_t direction,int32_t cursorMoveSkip)1308 void InputMethodController::SelectByMovement(int32_t direction, int32_t cursorMoveSkip)
1309 {
1310     IMSA_HILOGD(
1311         "InputMethodController start, direction: %{public}d, cursorMoveSkip: %{public}d", direction, cursorMoveSkip);
1312     auto listener = GetTextListener();
1313     if (IsEditable() && listener != nullptr) {
1314         listener->HandleSelectV2(CURSOR_DIRECTION_BASE_VALUE + direction, cursorMoveSkip);
1315     } else {
1316         IMSA_HILOGE("not editable or textListener_ is nullptr!");
1317     }
1318 
1319     if (controllerListener_ != nullptr) {
1320         controllerListener_->OnSelectByMovement(direction);
1321     } else {
1322         IMSA_HILOGE("controllerListener_ is nullptr!");
1323     }
1324 }
1325 
HandleExtendAction(int32_t action)1326 int32_t InputMethodController::HandleExtendAction(int32_t action)
1327 {
1328     IMSA_HILOGD("InputMethodController start, action: %{public}d.", action);
1329     auto listener = GetTextListener();
1330     if (!IsEditable() || listener == nullptr) {
1331         IMSA_HILOGE("not editable or textListener is nullptr!");
1332         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1333     }
1334     listener->HandleExtendActionV2(action);
1335     return ErrorCode::NO_ERROR;
1336 }
1337 
GetTextListener()1338 sptr<OnTextChangedListener> InputMethodController::GetTextListener()
1339 {
1340     std::lock_guard<std::mutex> lock(textListenerLock_);
1341     return textListener_;
1342 }
1343 
SetTextListener(sptr<OnTextChangedListener> listener)1344 void InputMethodController::SetTextListener(sptr<OnTextChangedListener> listener)
1345 {
1346     std::lock_guard<std::mutex> lock(textListenerLock_);
1347     textListener_ = listener;
1348 }
1349 
IsEditable()1350 bool InputMethodController::IsEditable()
1351 {
1352     std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1353     if (clientInfo_.state != ClientState::ACTIVE) {
1354         IMSA_HILOGD("client is not active.");
1355         return false;
1356     }
1357     if (!isEditable_.load()) {
1358         IMSA_HILOGD("not in editable state.");
1359         return false;
1360     }
1361     return true;
1362 }
1363 
IsBound()1364 bool InputMethodController::IsBound()
1365 {
1366     std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1367     if (clientInfo_.state != ClientState::ACTIVE) {
1368         IMSA_HILOGD("client is not active.");
1369         return false;
1370     }
1371     if (!isBound_.load()) {
1372         IMSA_HILOGD("not bound.");
1373         return false;
1374     }
1375     return true;
1376 }
1377 
InsertText(const std::u16string & text)1378 int32_t InputMethodController::InsertText(const std::u16string &text)
1379 {
1380     InputMethodSyncTrace tracer("IMC_InsertText");
1381     IMSA_HILOGD("start.");
1382     auto listener = GetTextListener();
1383     if (!IsEditable() || listener == nullptr) {
1384         IMSA_HILOGE("not editable or textListener is nullptr!");
1385         ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_INSERT_TEXT),
1386             ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1387         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1388     }
1389     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1390     {
1391         InputMethodSyncTrace aceTracer("ACE_InsertText");
1392         IMSA_HILOGD("ACE InsertText.");
1393         listener->InsertTextV2(text);
1394     }
1395 
1396     PrintLogIfAceTimeout(start);
1397     return ErrorCode::NO_ERROR;
1398 }
1399 
DeleteForward(int32_t length)1400 int32_t InputMethodController::DeleteForward(int32_t length)
1401 {
1402     InputMethodSyncTrace tracer("IMC_DeleteForward");
1403     IMSA_HILOGD("start, length: %{public}d.", length);
1404     auto listener = GetTextListener();
1405     if (!IsEditable() || listener == nullptr) {
1406         IMSA_HILOGE("not editable or textListener is nullptr!");
1407         ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_DELETE_FORWARD),
1408             ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1409         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1410     }
1411     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1412     {
1413         InputMethodSyncTrace aceTracer("ACE_DeleteForward");
1414         // reverse for compatibility
1415         listener->DeleteBackwardV2(length);
1416     }
1417     PrintLogIfAceTimeout(start);
1418     return ErrorCode::NO_ERROR;
1419 }
1420 
DeleteBackward(int32_t length)1421 int32_t InputMethodController::DeleteBackward(int32_t length)
1422 {
1423     IMSA_HILOGD("InputMethodController start, length: %{public}d.", length);
1424     auto listener = GetTextListener();
1425     if (!IsEditable() || listener == nullptr) {
1426         IMSA_HILOGE("not editable or textListener is nullptr!");
1427         ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_DELETE_BACKWARD),
1428             ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1429         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1430     }
1431     // reverse for compatibility
1432     listener->DeleteForwardV2(length);
1433     return ErrorCode::NO_ERROR;
1434 }
1435 
MoveCursor(Direction direction)1436 int32_t InputMethodController::MoveCursor(Direction direction)
1437 {
1438     IMSA_HILOGD("InputMethodController start, direction: %{public}d.", static_cast<int32_t>(direction));
1439     auto listener = GetTextListener();
1440     if (!IsEditable() || listener == nullptr) {
1441         IMSA_HILOGE("not editable or textListener_ is nullptr!");
1442         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1443     }
1444     listener->MoveCursorV2(direction);
1445     return ErrorCode::NO_ERROR;
1446 }
1447 
SendKeyboardStatus(KeyboardStatus status)1448 void InputMethodController::SendKeyboardStatus(KeyboardStatus status)
1449 {
1450     IMSA_HILOGD("InputMethodController status: %{public}d.", static_cast<int32_t>(status));
1451     auto listener = GetTextListener();
1452     if (listener == nullptr) {
1453         IMSA_HILOGE("listener is nullptr!");
1454         return;
1455     }
1456     listener->SendKeyboardStatusV2(status);
1457     if (status == KeyboardStatus::HIDE) {
1458         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1459         clientInfo_.isShowKeyboard = false;
1460     }
1461 }
1462 
NotifyPanelStatusInfo(const PanelStatusInfo & info)1463 void InputMethodController::NotifyPanelStatusInfo(const PanelStatusInfo &info)
1464 {
1465     IMSA_HILOGD("InputMethodController start, type: %{public}d, flag: %{public}d, visible: %{public}d, trigger: "
1466                 "%{public}d, sessionId: %{public}u.",
1467         static_cast<PanelType>(info.panelInfo.panelType), static_cast<PanelFlag>(info.panelInfo.panelFlag),
1468         info.visible, static_cast<Trigger>(info.trigger), info.sessionId);
1469     auto listener = GetTextListener();
1470     if (listener == nullptr) {
1471         IMSA_HILOGE("listener is nullptr!");
1472         return;
1473     }
1474     if (info.panelInfo.panelType == PanelType::SOFT_KEYBOARD) {
1475         info.visible ? SendKeyboardStatus(KeyboardStatus::SHOW) : SendKeyboardStatus(KeyboardStatus::HIDE);
1476     }
1477 
1478     if (info.visible || info.sessionId == 0 || info.sessionId == sessionId_) {
1479         listener->NotifyPanelStatusInfoV2(info);
1480     }
1481     if (info.panelInfo.panelType == PanelType::SOFT_KEYBOARD &&
1482         info.panelInfo.panelFlag != PanelFlag::FLG_CANDIDATE_COLUMN && !info.visible) {
1483         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1484         clientInfo_.isShowKeyboard = false;
1485     }
1486 }
1487 
NotifyKeyboardHeight(uint32_t height)1488 void InputMethodController::NotifyKeyboardHeight(uint32_t height)
1489 {
1490     IMSA_HILOGD("InputMethodController start, height: %{public}u.", height);
1491     auto listener = GetTextListener();
1492     if (listener == nullptr) {
1493         IMSA_HILOGE("listener is nullptr!");
1494         return;
1495     }
1496     listener->NotifyKeyboardHeightV2(height);
1497 }
1498 
SendFunctionKey(int32_t functionKey)1499 int32_t InputMethodController::SendFunctionKey(int32_t functionKey)
1500 {
1501     IMSA_HILOGD("InputMethodController start, functionKey: %{public}d", static_cast<int32_t>(functionKey));
1502     auto listener = GetTextListener();
1503     if (!IsEditable() || listener == nullptr) {
1504         IMSA_HILOGE("not editable or listener is nullptr!");
1505         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1506     }
1507     FunctionKey funcKey;
1508     funcKey.SetEnterKeyType(static_cast<EnterKeyType>(functionKey));
1509     listener->SendFunctionKeyV2(funcKey);
1510     SendRequestToImeMirrorAgent([&functionKey](std::shared_ptr<IInputMethodAgent> agent) -> int32_t {
1511         return agent->OnFunctionKey(functionKey);
1512     });
1513     return ErrorCode::NO_ERROR;
1514 }
1515 
IsInputTypeSupported(InputType type)1516 bool InputMethodController::IsInputTypeSupported(InputType type)
1517 {
1518     auto proxy = GetSystemAbilityProxy();
1519     if (proxy == nullptr) {
1520         IMSA_HILOGE("proxy is nullptr!");
1521         return ErrorCode::ERROR_NULL_POINTER;
1522     }
1523     IMSA_HILOGI("type: %{public}d.", static_cast<int32_t>(type));
1524     bool ret = false;
1525     proxy->IsInputTypeSupported(static_cast<int32_t>(type), ret);
1526     return ret;
1527 }
1528 
IsCurrentImeByPid(int32_t pid)1529 bool InputMethodController::IsCurrentImeByPid(int32_t pid)
1530 {
1531     auto proxy = GetSystemAbilityProxy();
1532     if (proxy == nullptr) {
1533         IMSA_HILOGE("proxy is nullptr!");
1534         return false;
1535     }
1536     bool ret = false;
1537     proxy->IsCurrentImeByPid(pid, ret);
1538     return ret;
1539 }
1540 
StartInputType(InputType type)1541 int32_t InputMethodController::StartInputType(InputType type)
1542 {
1543     auto proxy = GetSystemAbilityProxy();
1544     if (proxy == nullptr) {
1545         IMSA_HILOGE("proxy is nullptr!");
1546         return ErrorCode::ERROR_NULL_POINTER;
1547     }
1548     IMSA_HILOGI("type: %{public}d.", static_cast<int32_t>(type));
1549     return proxy->StartInputType(static_cast<int32_t>(type));
1550 }
1551 
StartInputTypeAsync(InputType type)1552 int32_t InputMethodController::StartInputTypeAsync(InputType type)
1553 {
1554     auto proxy = GetSystemAbilityProxy();
1555     if (proxy == nullptr) {
1556         IMSA_HILOGE("proxy is nullptr!");
1557         return ErrorCode::ERROR_NULL_POINTER;
1558     }
1559     IMSA_HILOGI("type: %{public}d.", static_cast<int32_t>(type));
1560     return proxy->StartInputTypeAsync(static_cast<int32_t>(type));
1561 }
1562 
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)1563 int32_t InputMethodController::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
1564 {
1565     auto proxy = GetSystemAbilityProxy();
1566     if (proxy == nullptr) {
1567         IMSA_HILOGE("proxy is nullptr!");
1568         return ErrorCode::ERROR_NULL_POINTER;
1569     }
1570     IMSA_HILOGD("type: %{public}d, flag: %{public}d.", static_cast<int32_t>(panelInfo.panelType),
1571         static_cast<int32_t>(panelInfo.panelFlag));
1572     return proxy->IsPanelShown(panelInfo, isShown);
1573 }
1574 
SetAgent(const sptr<IRemoteObject> & agentObject,const std::string & bundleName)1575 void InputMethodController::SetAgent(const sptr<IRemoteObject> &agentObject, const std::string &bundleName)
1576 {
1577     std::lock_guard<std::mutex> autoLock(agentLock_);
1578     for (auto &agentInfo : agentInfoList_) {
1579         if (agentInfo.agent != nullptr && agentInfo.agentObject.GetRefPtr() == agentObject.GetRefPtr()) {
1580             IMSA_HILOGD("[ImeMirrorTag]agent has already been set.");
1581             return;
1582         }
1583     }
1584 
1585     if (agentInfoList_.size() >= MAX_AGENT_NUMBER) {
1586         IMSA_HILOGW("[ImeMirrorTag]agent num is too many");
1587     }
1588     AgentInfo agentInfo;
1589     agentInfo.agent = std::make_shared<InputMethodAgentProxy>(agentObject);
1590     agentInfo.agentObject = agentObject;
1591     agentInfo.imeType = (bundleName == IME_MIRROR_NAME) ? ImeType::IME_MIRROR : ImeType::NONE;
1592     agentInfoList_.push_back(agentInfo);
1593 }
1594 
GetAgent()1595 std::shared_ptr<IInputMethodAgent> InputMethodController::GetAgent()
1596 {
1597     std::lock_guard<std::mutex> autoLock(agentLock_);
1598     for (auto &agentInfo : agentInfoList_) {
1599         if (agentInfo.agent != nullptr && agentInfo.imeType != ImeType::IME_MIRROR) {
1600             return agentInfo.agent;
1601         }
1602     }
1603     IMSA_HILOGE("no agent found!");
1604     return nullptr;
1605 }
1606 
PrintLogIfAceTimeout(int64_t start)1607 void InputMethodController::PrintLogIfAceTimeout(int64_t start)
1608 {
1609     int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1610     if (end < start || start < 0) {
1611         return;
1612     }
1613     if (end - start > ACE_DEAL_TIME_OUT) {
1614         IMSA_HILOGW("timeout: [%{public}" PRId64 ", %{public}" PRId64 "].", start, end);
1615     }
1616 }
1617 
ReceivePrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1618 int32_t InputMethodController::ReceivePrivateCommand(
1619     const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1620 {
1621     auto listener = GetTextListener();
1622     if (listener == nullptr) {
1623         IMSA_HILOGE("listener is nullptr!");
1624         return ErrorCode::ERROR_EX_NULL_POINTER;
1625     }
1626     IMSA_HILOGD("IMC in.");
1627     auto ret = listener->ReceivePrivateCommandV2(privateCommand);
1628     if (ret != ErrorCode::NO_ERROR) {
1629         IMSA_HILOGE("ReceivePrivateCommand err, ret: %{public}d!", ret);
1630         return ErrorCode::ERROR_TEXT_LISTENER_ERROR;
1631     }
1632     return ErrorCode::NO_ERROR;
1633 }
1634 
SendPrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1635 int32_t InputMethodController::SendPrivateCommand(
1636     const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1637 {
1638     if (!IsBound()) {
1639         IMSA_HILOGD("not bound.");
1640         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
1641     }
1642     if (!IsEditable()) {
1643         IMSA_HILOGD("not editable.");
1644         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1645     }
1646     if (!TextConfig::IsPrivateCommandValid(privateCommand)) {
1647         IMSA_HILOGE("invalid private command size!");
1648         return ErrorCode::ERROR_INVALID_PRIVATE_COMMAND_SIZE;
1649     }
1650     auto agent = GetAgent();
1651     if (agent == nullptr) {
1652         IMSA_HILOGE("agent is nullptr!");
1653         return ErrorCode::ERROR_IME_NOT_STARTED;
1654     }
1655     IMSA_HILOGD("IMC start.");
1656     Value value(privateCommand);
1657     return agent->SendPrivateCommand(value);
1658 }
1659 
SetBindImeInfo(const std::pair<int64_t,std::string> & imeInfo)1660 void InputMethodController::SetBindImeInfo(const std::pair<int64_t, std::string> &imeInfo)
1661 {
1662     std::lock_guard<std::mutex> lock(bindImeInfoLock_);
1663     bindImeInfo_ = imeInfo;
1664 }
1665 
GetBindImeInfo()1666 std::pair<int64_t, std::string> InputMethodController::GetBindImeInfo()
1667 {
1668     std::lock_guard<std::mutex> lock(bindImeInfoLock_);
1669     return bindImeInfo_;
1670 }
1671 
SetPreviewTextInner(const std::string & text,const Range & range)1672 int32_t InputMethodController::SetPreviewTextInner(const std::string &text, const Range &range)
1673 {
1674     InputMethodSyncTrace tracer("IMC_SetPreviewText");
1675     IMSA_HILOGD("IMC start.");
1676     if (!textConfig_.inputAttribute.isTextPreviewSupported) {
1677         IMSA_HILOGE("text preview do not supported!");
1678         return ErrorCode::ERROR_TEXT_PREVIEW_NOT_SUPPORTED;
1679     }
1680     auto listener = GetTextListener();
1681     if (!IsEditable() || listener == nullptr) {
1682         IMSA_HILOGE("not editable or listener is nullptr!");
1683         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1684     }
1685     int32_t ret = 0;
1686     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1687     {
1688         InputMethodSyncTrace aceTracer("ACE_SetPreviewText");
1689         ret = listener->SetPreviewTextV2(Str8ToStr16(text), range);
1690     }
1691     PrintLogIfAceTimeout(start);
1692     if (ret != ErrorCode::NO_ERROR) {
1693         IMSA_HILOGE("failed to SetPreviewText: %{public}d!", ret);
1694         return ret == -1 ? ErrorCode::ERROR_INVALID_RANGE : ErrorCode::ERROR_TEXT_LISTENER_ERROR;
1695     }
1696     return ErrorCode::NO_ERROR;
1697 }
1698 
FinishTextPreview()1699 int32_t InputMethodController::FinishTextPreview()
1700 {
1701     InputMethodSyncTrace tracer("IMC_FinishTextPreview");
1702     IMSA_HILOGD("IMC start.");
1703     if (!textConfig_.inputAttribute.isTextPreviewSupported) {
1704         IMSA_HILOGD("text preview do not supported!");
1705         ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_FINISH_TEXT_PREVIEW),
1706             ErrorCode::ERROR_TEXT_PREVIEW_NOT_SUPPORTED);
1707         return ErrorCode::ERROR_TEXT_PREVIEW_NOT_SUPPORTED;
1708     }
1709     auto listener = GetTextListener();
1710     if (!isBound_.load() || listener == nullptr) {
1711         IMSA_HILOGW("not bound or listener is nullptr!");
1712         ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_FINISH_TEXT_PREVIEW),
1713             ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1714         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1715     }
1716     {
1717         InputMethodSyncTrace aceTracer("ACE_FinishTextPreview");
1718         listener->FinishTextPreviewV2();
1719     }
1720     return ErrorCode::NO_ERROR;
1721 }
1722 
SendMessage(const ArrayBuffer & arrayBuffer)1723 int32_t InputMethodController::SendMessage(const ArrayBuffer &arrayBuffer)
1724 {
1725     if (!IsBound()) {
1726         IMSA_HILOGE("not bound.");
1727         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
1728     }
1729     if (!IsEditable()) {
1730         IMSA_HILOGE("not editable.");
1731         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1732     }
1733     if (!ArrayBuffer::IsSizeValid(arrayBuffer)) {
1734         IMSA_HILOGE("arrayBuffer size is invalid!");
1735         return ErrorCode::ERROR_INVALID_ARRAY_BUFFER_SIZE;
1736     }
1737     auto agent = GetAgent();
1738     if (agent == nullptr) {
1739         IMSA_HILOGE("agent is nullptr!");
1740         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1741     }
1742     return agent->SendMessage(arrayBuffer);
1743 }
1744 
RecvMessage(const ArrayBuffer & arrayBuffer)1745 int32_t InputMethodController::RecvMessage(const ArrayBuffer &arrayBuffer)
1746 {
1747     if (!IsBound()) {
1748         IMSA_HILOGE("not bound.");
1749         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
1750     }
1751     if (!IsEditable()) {
1752         IMSA_HILOGE("not editable.");
1753         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1754     }
1755     auto msgHandlerCallback = GetMsgHandlerCallback();
1756     if (msgHandlerCallback == nullptr) {
1757         IMSA_HILOGW("Message handler was not regist!");
1758         return ErrorCode::ERROR_MSG_HANDLER_NOT_REGIST;
1759     }
1760     return msgHandlerCallback->OnMessage(arrayBuffer);
1761 }
1762 
RegisterMsgHandler(const std::shared_ptr<MsgHandlerCallbackInterface> & msgHandler)1763 int32_t InputMethodController::RegisterMsgHandler(const std::shared_ptr<MsgHandlerCallbackInterface> &msgHandler)
1764 {
1765     IMSA_HILOGI("isRegist: %{public}d", msgHandler != nullptr);
1766     std::shared_ptr<MsgHandlerCallbackInterface> exMsgHandler = nullptr;
1767     {
1768         std::lock_guard<decltype(msgHandlerMutex_)> lock(msgHandlerMutex_);
1769         exMsgHandler = msgHandler_;
1770         msgHandler_ = msgHandler;
1771     }
1772     if (exMsgHandler != nullptr) {
1773         IMSA_HILOGI("Trigger exMessageHandler OnTerminated.");
1774         exMsgHandler->OnTerminated();
1775     }
1776     return ErrorCode::NO_ERROR;
1777 }
1778 
GetMsgHandlerCallback()1779 std::shared_ptr<MsgHandlerCallbackInterface> InputMethodController::GetMsgHandlerCallback()
1780 {
1781     std::lock_guard<decltype(msgHandlerMutex_)> lock(msgHandlerMutex_);
1782     return msgHandler_;
1783 }
1784 
GetInputMethodState(EnabledStatus & state)1785 int32_t InputMethodController::GetInputMethodState(EnabledStatus &state)
1786 {
1787     auto proxy = GetSystemAbilityProxy();
1788     if (proxy == nullptr) {
1789         IMSA_HILOGE("proxy is nullptr!");
1790         return ErrorCode::ERROR_NULL_POINTER;
1791     }
1792     int32_t stateData = 0;
1793     int32_t ret = proxy->GetInputMethodState(stateData);
1794     state = static_cast<EnabledStatus>(stateData);
1795     return ret;
1796 }
1797 
SetPreviewText(const std::string & text,const Range & range)1798 int32_t InputMethodController::SetPreviewText(const std::string &text, const Range &range)
1799 {
1800     auto ret = SetPreviewTextInner(text, range);
1801     ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_SET_PREVIEW_TEXT), ret);
1802     return ret;
1803 }
1804 
ShowTextInput(ClientType type)1805 int32_t InputMethodController::ShowTextInput(ClientType type)
1806 {
1807     AttachOptions attachOptions;
1808     return ShowTextInput(attachOptions, type);
1809 }
1810 
ShowTextInput(const AttachOptions & attachOptions,ClientType type)1811 int32_t InputMethodController::ShowTextInput(const AttachOptions &attachOptions, ClientType type)
1812 {
1813     auto ret = ShowTextInputInner(attachOptions, type);
1814     ReportClientShow(static_cast<int32_t>(IInputMethodSystemAbilityIpcCode::COMMAND_SHOW_INPUT), ret, type);
1815     return ret;
1816 }
1817 
ShowSoftKeyboard(ClientType type)1818 int32_t InputMethodController::ShowSoftKeyboard(ClientType type)
1819 {
1820     auto ret = ShowSoftKeyboardInner(type);
1821     ReportClientShow(static_cast<int32_t>(IInputMethodSystemAbilityIpcCode::COMMAND_SHOW_CURRENT_INPUT), ret, type);
1822     return ret;
1823 }
1824 
ReportClientShow(int32_t eventCode,int32_t errCode,ClientType type)1825 void InputMethodController::ReportClientShow(int32_t eventCode, int32_t errCode, ClientType type)
1826 {
1827     auto evenInfo =
1828         HiSysOriginalInfo::Builder().SetClientType(type).SetEventCode(eventCode).SetErrCode(errCode).Build();
1829     ImcHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_SHOW, *evenInfo);
1830 }
1831 
ReportBaseTextOperation(int32_t eventCode,int32_t errCode)1832 void InputMethodController::ReportBaseTextOperation(int32_t eventCode, int32_t errCode)
1833 {
1834     auto imeInfo = GetBindImeInfo();
1835     auto evenInfo = HiSysOriginalInfo::Builder()
1836                         .SetEventCode(eventCode)
1837                         .SetErrCode(errCode)
1838                         .SetPeerName(imeInfo.second)
1839                         .SetPeerPid(imeInfo.first)
1840                         .SetClientType(clientInfo_.type)
1841                         .Build();
1842     ImcHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::BASE_TEXT_OPERATOR, *evenInfo);
1843 }
1844 
UpdateTextPreviewState(bool isSupport)1845 void InputMethodController::UpdateTextPreviewState(bool isSupport)
1846 {
1847     if (textConfig_.inputAttribute.isTextPreviewSupported == isSupport) {
1848         return;
1849     }
1850     textConfig_.inputAttribute.isTextPreviewSupported = isSupport;
1851     auto agent = GetAgent();
1852     if (agent == nullptr) {
1853         IMSA_HILOGE("agent is nullptr!");
1854         return;
1855     }
1856     InputAttributeInner inner = InputMethodTools::GetInstance().AttributeToInner(textConfig_.inputAttribute);
1857     agent->OnAttributeChange(inner);
1858 }
1859 
SendPrivateData(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1860 int32_t InputMethodController::SendPrivateData(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1861 {
1862     auto proxy = GetSystemAbilityProxy();
1863     if (proxy == nullptr) {
1864         IMSA_HILOGE("proxy is nullptr!");
1865         return ErrorCode::ERROR_NULL_POINTER;
1866     }
1867     Value value(privateCommand);
1868     return proxy->SendPrivateData(value);
1869 }
1870 
RegisterWindowScaleCallbackHandler(WindowScaleCallback && callback)1871 int32_t InputMethodController::RegisterWindowScaleCallbackHandler(WindowScaleCallback&& callback)
1872 {
1873     IMSA_HILOGD("isRegister: %{public}d", callback != nullptr);
1874     std::lock_guard<std::mutex> lock(windowScaleCallbackMutex_);
1875     windowScaleCallback_ = std::move(callback);
1876     return static_cast<int32_t>(ErrorCode::NO_ERROR);
1877 }
1878 
GetWindowScaleCoordinate(uint32_t windowId,CursorInfo & cursorInfo)1879 void InputMethodController::GetWindowScaleCoordinate(uint32_t windowId, CursorInfo &cursorInfo)
1880 {
1881     WindowScaleCallback handler = nullptr;
1882     {
1883         std::lock_guard<std::mutex> lock(windowScaleCallbackMutex_);
1884         handler = windowScaleCallback_;
1885     }
1886     if (handler == nullptr) {
1887         IMSA_HILOGD("handler is nullptr");
1888         return;
1889     }
1890     handler(windowId, cursorInfo);
1891 }
1892 
ResponseDataChannel(const sptr<IRemoteObject> & agentObject,uint64_t msgId,int32_t code,const ResponseData & data)1893 int32_t InputMethodController::ResponseDataChannel(
1894     const sptr<IRemoteObject> &agentObject, uint64_t msgId, int32_t code, const ResponseData &data)
1895 {
1896     if (agentObject == nullptr) {
1897         IMSA_HILOGE("agentObject is nullptr!");
1898         return ErrorCode::ERROR_IME_NOT_STARTED;
1899     }
1900     auto agent = std::make_shared<InputMethodAgentProxy>(agentObject);
1901     ResponseDataInner inner;
1902     inner.rspData = data;
1903     return agent->ResponseDataChannel(msgId, code, inner);
1904 }
1905 
ClearAgentInfo()1906 void InputMethodController::ClearAgentInfo()
1907 {
1908     std::lock_guard guard(agentLock_);
1909     for (auto &agentInfo : agentInfoList_) {
1910         agentInfo.agent = nullptr;
1911         agentInfo.agentObject = nullptr;
1912     }
1913 
1914     IMSA_HILOGD("Clear all agent info");
1915     agentInfoList_.clear();
1916 }
1917 
SendRequestToAllAgents(std::function<int32_t (std::shared_ptr<IInputMethodAgent>)> task)1918 int32_t InputMethodController::SendRequestToAllAgents(std::function<int32_t(std::shared_ptr<IInputMethodAgent>)> task)
1919 {
1920     std::lock_guard guard(agentLock_);
1921     int32_t finalRet = ErrorCode::NO_ERROR;
1922     for (auto &agentInfo : agentInfoList_) {
1923         if (agentInfo.imeType == ImeType::IME_MIRROR && textConfig_.inputAttribute.IsSecurityImeFlag()) {
1924             IMSA_HILOGW("password not allow send to ime mirror");
1925             continue;
1926         }
1927         if (agentInfo.agent == nullptr) {
1928             if (agentInfo.imeType == ImeType::IME_MIRROR) {
1929                 IMSA_HILOGW("ime mirror agent is null");
1930                 continue;
1931             }
1932             IMSA_HILOGE("agent is null");
1933             if (agentInfo.imeType == ImeType::IME_MIRROR) {
1934                 continue;
1935             }
1936             return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1937         }
1938         auto ret = task(agentInfo.agent);
1939         if (ret != ErrorCode::NO_ERROR) {
1940             IMSA_HILOGE("failed, ret = %{public}d", ret);
1941         }
1942         // Only update final return code for non-imeMirror IMEs
1943         // ImeMirror IME errors don't affect the overall result
1944         if (agentInfo.imeType != ImeType::IME_MIRROR) {
1945             finalRet = ret;
1946         }
1947     }
1948     IMSA_HILOGD("end, finalRet = %{public}d", finalRet);
1949     return finalRet;
1950 }
1951 
SendRequestToImeMirrorAgent(std::function<int32_t (std::shared_ptr<IInputMethodAgent>)> task)1952 int32_t InputMethodController::SendRequestToImeMirrorAgent(
1953     std::function<int32_t(std::shared_ptr<IInputMethodAgent>)> task)
1954 {
1955     std::lock_guard guard(agentLock_);
1956     auto itr = std::find_if(agentInfoList_.begin(), agentInfoList_.end(), [](const AgentInfo &info) {
1957         return info.imeType == ImeType::IME_MIRROR;
1958     });
1959     if (itr == agentInfoList_.end()) {
1960         IMSA_HILOGD("ime mirror agent is not exist");
1961         return ErrorCode::ERROR_IME_NOT_FOUND;
1962     }
1963 
1964     if (textConfig_.inputAttribute.IsSecurityImeFlag()) {
1965         IMSA_HILOGE("text type is security, can not send function key");
1966         return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1967     }
1968 
1969     return task(itr->agent);
1970 }
1971 
InsertTextV2(const std::u16string & text)1972 void OnTextChangedListener::InsertTextV2(const std::u16string &text)
1973 {
1974     auto eventHandler = GetEventHandler();
1975     if (eventHandler == nullptr) {
1976         InsertText(text);
1977         return;
1978     }
1979     auto weakPtr = wptr<OnTextChangedListener>(this);
1980     auto task = [weakPtr, text]() {
1981         auto listener = weakPtr.promote();
1982         if (listener == nullptr) {
1983             IMSA_HILOGE("InsertTextV2 listener is nullptr.");
1984             return;
1985         }
1986         listener->InsertText(text);
1987     };
1988     eventHandler->PostTask(task, "InsertTextV2", 0, AppExecFwk::EventQueue::Priority::VIP);
1989 }
1990 
DeleteForwardV2(int32_t length)1991 void OnTextChangedListener::DeleteForwardV2(int32_t length)
1992 {
1993     auto eventHandler = GetEventHandler();
1994     if (eventHandler == nullptr) {
1995         DeleteForward(length);
1996         return;
1997     }
1998     auto weakPtr = wptr<OnTextChangedListener>(this);
1999     auto task = [weakPtr, length]() {
2000         auto listener = weakPtr.promote();
2001         if (listener == nullptr) {
2002             IMSA_HILOGE("DeleteForwardV2 listener is nullptr.");
2003             return;
2004         }
2005         listener->DeleteForward(length);
2006     };
2007     eventHandler->PostTask(task, "DeleteForwardV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2008 }
2009 
DeleteBackwardV2(int32_t length)2010 void OnTextChangedListener::DeleteBackwardV2(int32_t length)
2011 {
2012     auto eventHandler = GetEventHandler();
2013     if (eventHandler == nullptr) {
2014         DeleteBackward(length);
2015         return;
2016     }
2017     auto weakPtr = wptr<OnTextChangedListener>(this);
2018     auto task = [weakPtr, length]() {
2019         auto listener = weakPtr.promote();
2020         if (listener == nullptr) {
2021             IMSA_HILOGE("DeleteBackwardV2 listener is nullptr.");
2022             return;
2023         }
2024         listener->DeleteBackward(length);
2025     };
2026     eventHandler->PostTask(task, "DeleteBackwardV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2027 }
2028 
SendKeyboardStatusV2(const KeyboardStatus & keyboardStatus)2029 void OnTextChangedListener::SendKeyboardStatusV2(const KeyboardStatus &keyboardStatus)
2030 {
2031     auto eventHandler = GetEventHandler();
2032     if (eventHandler == nullptr) {
2033         SendKeyboardStatus(keyboardStatus);
2034         return;
2035     }
2036     auto weakPtr = wptr<OnTextChangedListener>(this);
2037     auto task = [weakPtr, keyboardStatus]() {
2038         auto listener = weakPtr.promote();
2039         if (listener == nullptr) {
2040             IMSA_HILOGE("SendKeyboardStatusV2 listener is nullptr.");
2041             return;
2042         }
2043         listener->SendKeyboardStatus(keyboardStatus);
2044     };
2045     eventHandler->PostTask(task, "SendKeyboardStatusV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2046 }
2047 
SendFunctionKeyV2(const FunctionKey & functionKey)2048 void OnTextChangedListener::SendFunctionKeyV2(const FunctionKey &functionKey)
2049 {
2050     auto eventHandler = GetEventHandler();
2051     if (eventHandler == nullptr) {
2052         SendFunctionKey(functionKey);
2053         return;
2054     }
2055     auto weakPtr = wptr<OnTextChangedListener>(this);
2056     auto task = [weakPtr, functionKey]() {
2057         auto listener = weakPtr.promote();
2058         if (listener == nullptr) {
2059             IMSA_HILOGE("SendFunctionKeyV2 listener is nullptr.");
2060             return;
2061         }
2062         listener->SendFunctionKey(functionKey);
2063     };
2064     eventHandler->PostTask(task, "SendFunctionKeyV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2065 }
2066 
MoveCursorV2(const Direction & direction)2067 void OnTextChangedListener::MoveCursorV2(const Direction &direction)
2068 {
2069     auto eventHandler = GetEventHandler();
2070     if (eventHandler == nullptr) {
2071         MoveCursor(direction);
2072         return;
2073     }
2074     auto weakPtr = wptr<OnTextChangedListener>(this);
2075     auto task = [weakPtr, direction]() {
2076         auto listener = weakPtr.promote();
2077         if (listener == nullptr) {
2078             IMSA_HILOGE("MoveCursorV2 listener is nullptr.");
2079             return;
2080         }
2081         listener->MoveCursor(direction);
2082     };
2083     eventHandler->PostTask(task, "MoveCursorV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2084 }
2085 
HandleExtendActionV2(int32_t action)2086 void OnTextChangedListener::HandleExtendActionV2(int32_t action)
2087 {
2088     auto eventHandler = GetEventHandler();
2089     if (eventHandler == nullptr) {
2090         HandleExtendAction(action);
2091         return;
2092     }
2093     auto weakPtr = wptr<OnTextChangedListener>(this);
2094     auto task = [weakPtr, action]() {
2095         auto listener = weakPtr.promote();
2096         if (listener == nullptr) {
2097             IMSA_HILOGE("HandleExtendActionV2 listener is nullptr.");
2098             return;
2099         }
2100         listener->HandleExtendAction(action);
2101     };
2102     eventHandler->PostTask(task, "HandleExtendActionV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2103 }
2104 
GetLeftTextOfCursorV2(int32_t number)2105 std::u16string OnTextChangedListener::GetLeftTextOfCursorV2(int32_t number)
2106 {
2107     auto eventHandler = GetEventHandler();
2108     if (eventHandler == nullptr) {
2109         return GetLeftTextOfCursor(number);
2110     }
2111     auto textResultHandler = std::make_shared<BlockData<std::u16string>>(MAX_TIMEOUT);
2112     auto weakPtr = wptr<OnTextChangedListener>(this);
2113     auto task = [weakPtr, textResultHandler, number]() {
2114         std::u16string text;
2115         auto listener = weakPtr.promote();
2116         if (listener == nullptr) {
2117             IMSA_HILOGE("GetLeftTextOfCursorV2 listener is nullptr.");
2118         } else {
2119             text = listener->GetLeftTextOfCursor(number);
2120         }
2121         if (textResultHandler != nullptr) {
2122             textResultHandler->SetValue(text);
2123         }
2124     };
2125     eventHandler->PostTask(task, "GetLeftTextOfCursorV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2126     std::u16string text;
2127     if (!textResultHandler->GetValue(text)) {
2128         IMSA_HILOGW("GetLeftTextOfCursorV2 timeout");
2129     }
2130     return text;
2131 }
2132 
GetRightTextOfCursorV2(int32_t number)2133 std::u16string OnTextChangedListener::GetRightTextOfCursorV2(int32_t number)
2134 {
2135     auto eventHandler = GetEventHandler();
2136     if (eventHandler == nullptr) {
2137         return GetRightTextOfCursor(number);
2138     }
2139     auto textResultHandler = std::make_shared<BlockData<std::u16string>>(MAX_TIMEOUT);
2140     auto weakPtr = wptr<OnTextChangedListener>(this);
2141     auto task = [weakPtr, textResultHandler, number]() {
2142         std::u16string text;
2143         auto listener = weakPtr.promote();
2144         if (listener == nullptr) {
2145             IMSA_HILOGE("GetRightTextOfCursorV2 listener is nullptr.");
2146         } else {
2147             text = listener->GetRightTextOfCursor(number);
2148         }
2149         if (textResultHandler != nullptr) {
2150             textResultHandler->SetValue(text);
2151         }
2152     };
2153     eventHandler->PostTask(task, "GetRightTextOfCursorV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2154     std::u16string text;
2155     if (!textResultHandler->GetValue(text)) {
2156         IMSA_HILOGW("GetRightTextOfCursorV2 timeout");
2157     }
2158     return text;
2159 }
2160 
GetTextIndexAtCursorV2()2161 int32_t OnTextChangedListener::GetTextIndexAtCursorV2()
2162 {
2163     auto eventHandler = GetEventHandler();
2164     if (eventHandler == nullptr) {
2165         return GetTextIndexAtCursor();
2166     }
2167     auto textResultHandler = std::make_shared<BlockData<int32_t>>(MAX_TIMEOUT, -1);
2168     auto weakPtr = wptr<OnTextChangedListener>(this);
2169     auto task = [weakPtr, textResultHandler]() {
2170         int32_t index = -1;
2171         auto listener = weakPtr.promote();
2172         if (listener == nullptr) {
2173             IMSA_HILOGE("GetTextIndexAtCursorV2 listener is nullptr.");
2174         } else {
2175             index = listener->GetTextIndexAtCursor();
2176         }
2177         if (textResultHandler != nullptr) {
2178             textResultHandler->SetValue(index);
2179         }
2180     };
2181     eventHandler->PostTask(task, "GetTextIndexAtCursorV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2182     int32_t index = -1;
2183     if (!textResultHandler->GetValue(index)) {
2184         IMSA_HILOGW("GetTextIndexAtCursorV2 timeout");
2185     }
2186     return index;
2187 }
2188 
SendKeyEventFromInputMethodV2(const KeyEvent & event)2189 void OnTextChangedListener::SendKeyEventFromInputMethodV2(const KeyEvent &event)
2190 {
2191     auto eventHandler = GetEventHandler();
2192     if (eventHandler == nullptr) {
2193         SendKeyEventFromInputMethod(event);
2194         return;
2195     }
2196     auto weakPtr = wptr<OnTextChangedListener>(this);
2197     auto task = [weakPtr, event]() {
2198         auto listener = weakPtr.promote();
2199         if (listener == nullptr) {
2200             IMSA_HILOGE("SendKeyEventFromInputMethodV2 listener is nullptr.");
2201             return;
2202         }
2203         listener->SendKeyEventFromInputMethod(event);
2204     };
2205     eventHandler->PostTask(task, "SendKeyEventFromInputMethodV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2206 }
2207 
NotifyPanelStatusInfoV2(const PanelStatusInfo & info)2208 void OnTextChangedListener::NotifyPanelStatusInfoV2(const PanelStatusInfo &info)
2209 {
2210     auto eventHandler = GetEventHandler();
2211     if (eventHandler == nullptr) {
2212         NotifyPanelStatusInfo(info);
2213         return;
2214     }
2215     auto weakPtr = wptr<OnTextChangedListener>(this);
2216     auto task = [weakPtr, info]() {
2217         auto listener = weakPtr.promote();
2218         if (listener == nullptr) {
2219             IMSA_HILOGE("NotifyPanelStatusInfoV2 listener is nullptr.");
2220             return;
2221         }
2222         listener->NotifyPanelStatusInfo(info);
2223     };
2224     eventHandler->PostTask(task, "NotifyPanelStatusInfoV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2225 }
2226 
NotifyKeyboardHeightV2(uint32_t height)2227 void OnTextChangedListener::NotifyKeyboardHeightV2(uint32_t height)
2228 {
2229     auto eventHandler = GetEventHandler();
2230     if (eventHandler == nullptr) {
2231         NotifyKeyboardHeight(height);
2232         return;
2233     }
2234     auto weakPtr = wptr<OnTextChangedListener>(this);
2235     auto task = [weakPtr, height]() {
2236         auto listener = weakPtr.promote();
2237         if (listener == nullptr) {
2238             IMSA_HILOGE("NotifyKeyboardHeightV2 listener is nullptr.");
2239             return;
2240         }
2241         listener->NotifyKeyboardHeight(height);
2242     };
2243     eventHandler->PostTask(task, "NotifyKeyboardHeightV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2244 }
2245 
SetKeyboardStatusV2(bool status)2246 void OnTextChangedListener::SetKeyboardStatusV2(bool status)
2247 {
2248     auto eventHandler = GetEventHandler();
2249     if (eventHandler == nullptr) {
2250         SetKeyboardStatus(status);
2251         return;
2252     }
2253     auto weakPtr = wptr<OnTextChangedListener>(this);
2254     auto task = [weakPtr, status]() {
2255         auto listener = weakPtr.promote();
2256         if (listener == nullptr) {
2257             IMSA_HILOGE("SetKeyboardStatusV2 listener is nullptr.");
2258             return;
2259         }
2260         listener->SetKeyboardStatus(status);
2261     };
2262     eventHandler->PostTask(task, "SetKeyboardStatusV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2263 }
2264 
HandleSetSelectionV2(int32_t start,int32_t end)2265 void OnTextChangedListener::HandleSetSelectionV2(int32_t start, int32_t end)
2266 {
2267     auto eventHandler = GetEventHandler();
2268     if (eventHandler == nullptr) {
2269         HandleSetSelection(start, end);
2270         return;
2271     }
2272     auto weakPtr = wptr<OnTextChangedListener>(this);
2273     auto task = [weakPtr, start, end]() {
2274         auto listener = weakPtr.promote();
2275         if (listener == nullptr) {
2276             IMSA_HILOGE("HandleSetSelectionV2 listener is nullptr.");
2277             return;
2278         }
2279         listener->HandleSetSelection(start, end);
2280     };
2281     eventHandler->PostTask(task, "HandleSetSelectionV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2282 }
2283 
HandleSelectV2(int32_t keyCode,int32_t cursorMoveSkip)2284 void OnTextChangedListener::HandleSelectV2(int32_t keyCode, int32_t cursorMoveSkip)
2285 {
2286     auto eventHandler = GetEventHandler();
2287     if (eventHandler == nullptr) {
2288         HandleSelect(keyCode, cursorMoveSkip);
2289         return;
2290     }
2291     auto weakPtr = wptr<OnTextChangedListener>(this);
2292     auto task = [weakPtr, keyCode, cursorMoveSkip]() {
2293         auto listener = weakPtr.promote();
2294         if (listener == nullptr) {
2295             IMSA_HILOGE("HandleSelectV2 listener is nullptr.");
2296             return;
2297         }
2298         listener->HandleSelect(keyCode, cursorMoveSkip);
2299     };
2300     eventHandler->PostTask(task, "HandleSelectV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2301 }
2302 
ReceivePrivateCommandV2(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)2303 int32_t OnTextChangedListener::ReceivePrivateCommandV2(
2304     const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
2305 {
2306     auto eventHandler = GetEventHandler();
2307     if (eventHandler == nullptr) {
2308         return ReceivePrivateCommand(privateCommand);
2309     }
2310     auto weakPtr = wptr<OnTextChangedListener>(this);
2311     auto task = [weakPtr, privateCommand]() {
2312         auto listener = weakPtr.promote();
2313         if (listener == nullptr) {
2314             IMSA_HILOGE("ReceivePrivateCommandV2 listener is nullptr.");
2315             return;
2316         }
2317         listener->ReceivePrivateCommand(privateCommand);
2318     };
2319     eventHandler->PostTask(task, "ReceivePrivateCommandV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2320     return ErrorCode::NO_ERROR;
2321 }
2322 
SetPreviewTextV2(const std::u16string & text,const Range & range)2323 int32_t OnTextChangedListener::SetPreviewTextV2(const std::u16string &text, const Range &range)
2324 {
2325     auto eventHandler = GetEventHandler();
2326     if (eventHandler == nullptr) {
2327         return SetPreviewText(text, range);
2328     }
2329     auto weakPtr = wptr<OnTextChangedListener>(this);
2330     auto task = [weakPtr, text, range]() {
2331         auto listener = weakPtr.promote();
2332         if (listener == nullptr) {
2333             IMSA_HILOGE("SetPreviewTextV2 listener is nullptr.");
2334             return;
2335         }
2336         listener->SetPreviewText(text, range);
2337     };
2338     eventHandler->PostTask(task, "SetPreviewTextV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2339     return ErrorCode::NO_ERROR;
2340 }
2341 
FinishTextPreviewV2()2342 void OnTextChangedListener::FinishTextPreviewV2()
2343 {
2344     auto eventHandler = GetEventHandler();
2345     if (eventHandler == nullptr) {
2346         FinishTextPreview();
2347         return;
2348     }
2349     auto weakPtr = wptr<OnTextChangedListener>(this);
2350     auto task = [weakPtr]() {
2351         auto listener = weakPtr.promote();
2352         if (listener == nullptr) {
2353             IMSA_HILOGE("FinishTextPreviewV2 listener is nullptr.");
2354             return;
2355         }
2356         listener->FinishTextPreview();
2357     };
2358     eventHandler->PostTask(task, "FinishTextPreviewV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2359 }
2360 
OnDetachV2()2361 void OnTextChangedListener::OnDetachV2()
2362 {
2363     auto eventHandler = GetEventHandler();
2364     if (eventHandler == nullptr) {
2365         OnDetach();
2366         return;
2367     }
2368     auto weakPtr = wptr<OnTextChangedListener>(this);
2369     auto task = [weakPtr]() {
2370         auto listener = weakPtr.promote();
2371         if (listener == nullptr) {
2372             IMSA_HILOGE("OnDetachV2 listener is nullptr.");
2373             return;
2374         }
2375         listener->OnDetach();
2376     };
2377     eventHandler->PostTask(task, "OnDetachV2", 0, AppExecFwk::EventQueue::Priority::VIP);
2378 }
2379 } // namespace MiscServices
2380 } // namespace OHOS
2381