• 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 
21 #include "block_data.h"
22 #include "global.h"
23 #include "imc_hisysevent_reporter.h"
24 #include "ime_event_monitor_manager_impl.h"
25 #include "input_client_stub.h"
26 #include "input_data_channel_stub.h"
27 #include "input_method_agent_proxy.h"
28 #include "input_method_property.h"
29 #include "input_method_status.h"
30 #include "input_method_system_ability_proxy.h"
31 #include "inputmethod_service_ipc_interface_code.h"
32 #include "inputmethod_sysevent.h"
33 #include "inputmethod_trace.h"
34 #include "iservice_registry.h"
35 #include "keyevent_consumer_stub.h"
36 #include "on_demand_start_stop_sa.h"
37 #include "string_ex.h"
38 #include "sys/prctl.h"
39 #include "system_ability_definition.h"
40 #include "system_cmd_channel_stub.h"
41 
42 namespace OHOS {
43 namespace MiscServices {
44 using namespace MessageID;
45 using namespace std::chrono;
46 sptr<InputMethodController> InputMethodController::instance_;
47 std::shared_ptr<AppExecFwk::EventHandler> InputMethodController::handler_ { nullptr };
48 std::mutex InputMethodController::instanceLock_;
49 std::mutex InputMethodController::logLock_;
50 int InputMethodController::keyEventCountInPeriod_ = 0;
51 std::chrono::system_clock::time_point InputMethodController::startLogTime_ = system_clock::now();
52 constexpr int32_t LOOP_COUNT = 5;
53 constexpr int32_t LOG_MAX_TIME = 20;
54 constexpr int64_t DELAY_TIME = 100;
55 constexpr int32_t ACE_DEAL_TIME_OUT = 200;
InputMethodController()56 InputMethodController::InputMethodController()
57 {
58     IMSA_HILOGD("IMC structure.");
59 }
60 
~InputMethodController()61 InputMethodController::~InputMethodController() { }
62 
GetInstance()63 sptr<InputMethodController> InputMethodController::GetInstance()
64 {
65     if (instance_ == nullptr) {
66         std::lock_guard<std::mutex> autoLock(instanceLock_);
67         if (instance_ == nullptr) {
68             IMSA_HILOGD("instance_ is nullptr.");
69             instance_ = new (std::nothrow) InputMethodController();
70             if (instance_ == nullptr) {
71                 IMSA_HILOGE("failed to create InputMethodController!");
72                 return instance_;
73             }
74             int32_t ret = instance_->Initialize();
75             if (ret != ErrorCode::NO_ERROR) {
76                 InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, "", "IMC initialize failed!");
77             }
78         }
79     }
80     return instance_;
81 }
82 
RestoreListenEventFlag()83 int32_t InputMethodController::RestoreListenEventFlag()
84 {
85     auto proxy = GetSystemAbilityProxy();
86     if (proxy == nullptr) {
87         IMSA_HILOGE("proxy is nullptr!");
88         return ErrorCode::ERROR_SERVICE_START_FAILED;
89     }
90     // 0 represent no need to check permission
91     return proxy->UpdateListenEventFlag(clientInfo_, 0);
92 }
93 
UpdateListenEventFlag(uint32_t finalEventFlag,uint32_t eventFlag,bool isOn)94 int32_t InputMethodController::UpdateListenEventFlag(uint32_t finalEventFlag, uint32_t eventFlag, bool isOn)
95 {
96     auto oldEventFlag = clientInfo_.eventFlag;
97     clientInfo_.eventFlag = finalEventFlag;
98     auto proxy = GetSystemAbilityProxy();
99     if (proxy == nullptr) {
100         IMSA_HILOGE("proxy is nullptr!");
101         if (isOn) {
102             clientInfo_.eventFlag = oldEventFlag;
103         }
104         return ErrorCode::ERROR_SERVICE_START_FAILED;
105     }
106     auto ret = proxy->UpdateListenEventFlag(clientInfo_, eventFlag);
107     if (ret != ErrorCode::NO_ERROR && isOn) {
108         clientInfo_.eventFlag = oldEventFlag;
109     }
110     return ret;
111 }
112 
SetControllerListener(std::shared_ptr<ControllerListener> controllerListener)113 void InputMethodController::SetControllerListener(std::shared_ptr<ControllerListener> controllerListener)
114 {
115     IMSA_HILOGD("InputMethodController run in");
116     controllerListener_ = std::move(controllerListener);
117 }
118 
Initialize()119 int32_t InputMethodController::Initialize()
120 {
121     sptr<IInputClient> client = new (std::nothrow) InputClientStub();
122     if (client == nullptr) {
123         IMSA_HILOGE("failed to create client!");
124         return ErrorCode::ERROR_NULL_POINTER;
125     }
126     sptr<IInputDataChannel> channel = new (std::nothrow) InputDataChannelStub();
127     if (channel == nullptr) {
128         IMSA_HILOGE("failed to new channel!");
129         return ErrorCode::ERROR_NULL_POINTER;
130     }
131     InputAttribute attribute = { .inputPattern = InputAttribute::PATTERN_TEXT };
132     clientInfo_ = { .attribute = attribute, .client = client, .channel = channel->AsObject() };
133 
134     // make AppExecFwk::EventHandler handler
135     handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
136     return ErrorCode::NO_ERROR;
137 }
138 
TryGetSystemAbilityProxy()139 sptr<IInputMethodSystemAbility> InputMethodController::TryGetSystemAbilityProxy()
140 {
141 #ifdef IMF_ON_DEMAND_START_STOP_SA_ENABLE
142     return GetSystemAbilityProxy(false);
143 #else
144     return GetSystemAbilityProxy(true);
145 #endif
146 }
147 
GetSystemAbilityProxy(bool ifRetry)148 sptr<IInputMethodSystemAbility> InputMethodController::GetSystemAbilityProxy(bool ifRetry)
149 {
150     std::lock_guard<std::mutex> lock(abilityLock_);
151     if (abilityManager_ != nullptr) {
152         return abilityManager_;
153     }
154     IMSA_HILOGI("get input method service proxy.");
155     auto systemAbility = OnDemandStartStopSa::GetInputMethodSystemAbility(ifRetry);
156     if (systemAbility == nullptr) {
157         IMSA_HILOGE("systemAbility is nullptr!");
158         return nullptr;
159     }
160 
161     if (deathRecipient_ == nullptr) {
162         deathRecipient_ = new (std::nothrow) InputDeathRecipient();
163         if (deathRecipient_ == nullptr) {
164             IMSA_HILOGE("create death recipient failed!");
165             return nullptr;
166         }
167     }
168     deathRecipient_->SetDeathRecipient([this](const wptr<IRemoteObject> &remote) {
169         OnRemoteSaDied(remote);
170     });
171     if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) {
172         IMSA_HILOGE("failed to add death recipient!");
173         return nullptr;
174     }
175     abilityManager_ = iface_cast<IInputMethodSystemAbility>(systemAbility);
176     return abilityManager_;
177 }
178 
RemoveDeathRecipient()179 void InputMethodController::RemoveDeathRecipient()
180 {
181     std::lock_guard<std::mutex> lock(abilityLock_);
182     if (abilityManager_ != nullptr && abilityManager_->AsObject() != nullptr && deathRecipient_ != nullptr) {
183         abilityManager_->AsObject()->RemoveDeathRecipient(deathRecipient_);
184     }
185     deathRecipient_ = nullptr;
186     abilityManager_ = nullptr;
187 }
188 
DeactivateClient()189 void InputMethodController::DeactivateClient()
190 {
191     {
192         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
193         clientInfo_.state = ClientState::INACTIVE;
194     }
195     SendKeyboardStatus(KeyboardStatus::NONE);
196 }
197 
SaveTextConfig(const TextConfig & textConfig)198 void InputMethodController::SaveTextConfig(const TextConfig &textConfig)
199 {
200     IMSA_HILOGD("textConfig: %{public}s.", textConfig.ToString().c_str());
201     {
202         std::lock_guard<std::mutex> lock(textConfigLock_);
203         textConfig_ = textConfig;
204     }
205     if (textConfig.range.start != INVALID_VALUE) {
206         std::lock_guard<std::mutex> lock(editorContentLock_);
207         selectOldBegin_ = selectNewBegin_;
208         selectOldEnd_ = selectNewEnd_;
209         selectNewBegin_ = textConfig.range.start;
210         selectNewEnd_ = textConfig.range.end;
211     }
212 }
213 
Attach(sptr<OnTextChangedListener> listener,ClientType type)214 int32_t InputMethodController::Attach(sptr<OnTextChangedListener> listener, ClientType type)
215 {
216     return Attach(listener, true, type);
217 }
218 
Attach(sptr<OnTextChangedListener> listener,bool isShowKeyboard,ClientType type)219 int32_t InputMethodController::Attach(sptr<OnTextChangedListener> listener, bool isShowKeyboard, ClientType type)
220 {
221     InputAttribute attribute;
222     attribute.inputPattern = InputAttribute::PATTERN_TEXT;
223     return Attach(listener, isShowKeyboard, attribute, type);
224 }
225 
Attach(sptr<OnTextChangedListener> listener,bool isShowKeyboard,const InputAttribute & attribute,ClientType type)226 int32_t InputMethodController::Attach(
227     sptr<OnTextChangedListener> listener, bool isShowKeyboard, const InputAttribute &attribute, ClientType type)
228 {
229     InputMethodSyncTrace tracer("InputMethodController Attach trace.");
230     TextConfig textConfig;
231     textConfig.inputAttribute = attribute;
232     return Attach(listener, isShowKeyboard, textConfig, type);
233 }
234 
Attach(sptr<OnTextChangedListener> listener,bool isShowKeyboard,const TextConfig & textConfig,ClientType type)235 int32_t InputMethodController::Attach(
236     sptr<OnTextChangedListener> listener, bool isShowKeyboard, const TextConfig &textConfig, ClientType type)
237 {
238     AttachOptions attachOptions;
239     attachOptions.isShowKeyboard = isShowKeyboard;
240     attachOptions.requestKeyboardReason = RequestKeyboardReason::NONE;
241     return Attach(listener, attachOptions, textConfig, type);
242 }
243 
IsValidTextConfig(const TextConfig & textConfig)244 int32_t InputMethodController::IsValidTextConfig(const TextConfig &textConfig)
245 {
246     if (textConfig.inputAttribute.immersiveMode < static_cast<int32_t>(ImmersiveMode::NONE_IMMERSIVE) ||
247         textConfig.inputAttribute.immersiveMode >= static_cast<int32_t>(ImmersiveMode::END)) {
248         IMSA_HILOGE("invalid immersiveMode: %{public}d", textConfig.inputAttribute.immersiveMode);
249         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
250     }
251     return ErrorCode::NO_ERROR;
252 }
253 
Attach(sptr<OnTextChangedListener> listener,const AttachOptions & attachOptions,const TextConfig & textConfig,ClientType type)254 int32_t InputMethodController::Attach(sptr<OnTextChangedListener> listener, const AttachOptions &attachOptions,
255     const TextConfig &textConfig, ClientType type)
256 {
257     IMSA_HILOGI("isShowKeyboard %{public}d.", attachOptions.isShowKeyboard);
258     InputMethodSyncTrace tracer("InputMethodController Attach with textConfig trace.");
259     if (IsValidTextConfig(textConfig) != ErrorCode::NO_ERROR) {
260         IMSA_HILOGE("invalid textConfig.");
261         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
262     }
263     auto lastListener = GetTextListener();
264     clientInfo_.isNotifyInputStart = lastListener != listener;
265     if (clientInfo_.isNotifyInputStart && lastListener != nullptr) {
266         lastListener->OnDetach();
267     }
268     ClearEditorCache(clientInfo_.isNotifyInputStart, lastListener);
269     SetTextListener(listener);
270     {
271         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
272         clientInfo_.isShowKeyboard = attachOptions.isShowKeyboard;
273     }
274     SaveTextConfig(textConfig);
275     GetTextConfig(clientInfo_.config);
276     clientInfo_.requestKeyboardReason = attachOptions.requestKeyboardReason;
277     clientInfo_.type = type;
278 
279     sptr<IRemoteObject> agent = nullptr;
280     std::pair<int64_t, std::string> imeInfo{ 0, "" };
281     int32_t ret = StartInput(clientInfo_, agent, imeInfo);
282     if (ret != ErrorCode::NO_ERROR) {
283         auto evenInfo = HiSysOriginalInfo::Builder()
284                             .SetErrCode(ret)
285                             .SetInputPattern(textConfig.inputAttribute.inputPattern)
286                             .SetIsShowKeyboard(attachOptions.isShowKeyboard)
287                             .SetClientType(type)
288                             .Build();
289         ImcHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_ATTACH, *evenInfo);
290         return ret;
291     }
292     clientInfo_.state = ClientState::ACTIVE;
293     OnInputReady(agent, imeInfo);
294     if (attachOptions.isShowKeyboard) {
295         InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_ATTACH);
296     }
297     IMSA_HILOGI("bind imf successfully.");
298     return ErrorCode::NO_ERROR;
299 }
300 
ShowTextInputInner(const AttachOptions & attachOptions,ClientType type)301 int32_t InputMethodController::ShowTextInputInner(const AttachOptions &attachOptions, ClientType type)
302 {
303     InputMethodSyncTrace tracer("IMC_ShowTextInput");
304     if (!IsBound()) {
305         IMSA_HILOGE("not bound!");
306         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
307     }
308     IMSA_HILOGI("start.");
309     {
310         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
311         clientInfo_.isShowKeyboard = true;
312     }
313     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_ENEDITABLE);
314     int32_t ret = ShowInput(clientInfo_.client, type, static_cast<int32_t>(attachOptions.requestKeyboardReason));
315     if (ret != ErrorCode::NO_ERROR) {
316         IMSA_HILOGE("failed to start input: %{public}d", ret);
317         return ret;
318     }
319     isEditable_.store(true);
320     IMSA_HILOGI("enter editable state.");
321     return ret;
322 }
323 
HideTextInput()324 int32_t InputMethodController::HideTextInput()
325 {
326     InputMethodSyncTrace tracer("IMC_HideTextInput");
327     if (!IsBound()) {
328         IMSA_HILOGE("not bound!");
329         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
330     }
331     IMSA_HILOGI("start.");
332     isEditable_.store(false);
333     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNEDITABLE);
334     return HideInput(clientInfo_.client);
335 }
336 
HideCurrentInput()337 int32_t InputMethodController::HideCurrentInput()
338 {
339     InputMethodSyncTrace tracer("IMC_HideCurrentInput");
340     IMSA_HILOGD("InputMethodController::HideCurrentInput");
341     if (!IsEditable()) {
342         IMSA_HILOGD("not editable.");
343         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
344     }
345     auto proxy = GetSystemAbilityProxy();
346     if (proxy == nullptr) {
347         IMSA_HILOGE("proxy is nullptr!");
348         return ErrorCode::ERROR_EX_NULL_POINTER;
349     }
350     {
351         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
352         clientInfo_.isShowKeyboard = false;
353     }
354     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_NORMAL);
355     return proxy->HideCurrentInputDeprecated();
356 }
357 
ShowCurrentInput()358 int32_t InputMethodController::ShowCurrentInput()
359 {
360     InputMethodSyncTrace tracer("IMC_ShowCurrentInput");
361     if (!IsEditable()) {
362         IMSA_HILOGD("not editable.");
363         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
364     }
365     auto proxy = GetSystemAbilityProxy();
366     if (proxy == nullptr) {
367         IMSA_HILOGE("proxy is nullptr!");
368         return ErrorCode::ERROR_EX_NULL_POINTER;
369     }
370     IMSA_HILOGI("start.");
371     {
372         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
373         clientInfo_.isShowKeyboard = true;
374     }
375     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_NORMAL);
376     return proxy->ShowCurrentInputDeprecated();
377 }
378 
Close()379 int32_t InputMethodController::Close()
380 {
381     if (IsBound()) {
382         IMSA_HILOGI("start.");
383     }
384 
385     auto listener = GetTextListener();
386     if (listener != nullptr) {
387         listener->OnDetach();
388     }
389     OperateIMEInfoCode infoCode = OperateIMEInfoCode::IME_UNBIND;
390     {
391         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
392         if (clientInfo_.isShowKeyboard) {
393             infoCode = OperateIMEInfoCode::IME_HIDE_UNBIND;
394         }
395     }
396     InputMethodSyncTrace tracer("InputMethodController Close trace.");
397     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(infoCode);
398     return ReleaseInput(clientInfo_.client);
399 }
400 
Reset()401 void InputMethodController::Reset()
402 {
403     Close();
404     RemoveDeathRecipient();
405 }
406 
RequestShowInput()407 int32_t InputMethodController::RequestShowInput()
408 {
409     auto proxy = GetSystemAbilityProxy();
410     if (proxy == nullptr) {
411         IMSA_HILOGE("proxy is nullptr!");
412         return ErrorCode::ERROR_SERVICE_START_FAILED; // ERROR_EX_NULL_POINTER
413     }
414     IMSA_HILOGI("InputMethodController start.");
415     return proxy->RequestShowInput();
416 }
417 
RequestHideInput(bool isFocusTriggered)418 int32_t InputMethodController::RequestHideInput(bool isFocusTriggered)
419 {
420     auto proxy = TryGetSystemAbilityProxy();
421     if (proxy == nullptr) {
422         IMSA_HILOGE("proxy is nullptr!");
423         return ErrorCode::ERROR_EX_NULL_POINTER;
424     }
425     IMSA_HILOGD("InputMethodController start.");
426     return proxy->RequestHideInput(isFocusTriggered);
427 }
428 
DisplayOptionalInputMethod()429 int32_t InputMethodController::DisplayOptionalInputMethod()
430 {
431     IMSA_HILOGD("InputMethodController::DisplayOptionalInputMethod start.");
432     auto proxy = GetSystemAbilityProxy();
433     if (proxy == nullptr) {
434         IMSA_HILOGE("proxy is nullptr!");
435         return ErrorCode::ERROR_EX_NULL_POINTER;
436     }
437     return proxy->DisplayOptionalInputMethod();
438 }
439 
WasAttached()440 bool InputMethodController::WasAttached()
441 {
442     return isBound_.load();
443 }
444 
GetInputStartInfo(bool & isInputStart,uint32_t & callingWndId,int32_t & requestKeyboardReason)445 int32_t InputMethodController::GetInputStartInfo(bool &isInputStart,
446     uint32_t &callingWndId, int32_t &requestKeyboardReason)
447 {
448     auto proxy = GetSystemAbilityProxy();
449     if (proxy == nullptr) {
450         IMSA_HILOGE("proxy is nullptr!");
451         return false;
452     }
453     return proxy->GetInputStartInfo(isInputStart, callingWndId, requestKeyboardReason);
454 }
455 
ListInputMethodCommon(InputMethodStatus status,std::vector<Property> & props)456 int32_t InputMethodController::ListInputMethodCommon(InputMethodStatus status, std::vector<Property> &props)
457 {
458     IMSA_HILOGD("InputMethodController::ListInputMethodCommon start.");
459     auto proxy = GetSystemAbilityProxy();
460     if (proxy == nullptr) {
461         IMSA_HILOGE("proxy is nullptr!");
462         return ErrorCode::ERROR_EX_NULL_POINTER;
463     }
464     return proxy->ListInputMethod(status, props);
465 }
466 
ListInputMethod(std::vector<Property> & props)467 int32_t InputMethodController::ListInputMethod(std::vector<Property> &props)
468 {
469     IMSA_HILOGD("InputMethodController::listInputMethod start.");
470     return ListInputMethodCommon(ALL, props);
471 }
472 
ListInputMethod(bool enable,std::vector<Property> & props)473 int32_t InputMethodController::ListInputMethod(bool enable, std::vector<Property> &props)
474 {
475     IMSA_HILOGI("enable: %{public}s.", enable ? "ENABLE" : "DISABLE");
476     return ListInputMethodCommon(enable ? ENABLE : DISABLE, props);
477 }
478 
GetDefaultInputMethod(std::shared_ptr<Property> & property)479 int32_t InputMethodController::GetDefaultInputMethod(std::shared_ptr<Property> &property)
480 {
481     InputMethodSyncTrace tracer("IMC_GetDefaultInputMethod");
482     IMSA_HILOGD("InputMethodController::GetDefaultInputMethod start.");
483     auto proxy = GetSystemAbilityProxy();
484     if (proxy == nullptr) {
485         IMSA_HILOGE("proxy is nullptr!");
486         return ErrorCode::ERROR_SERVICE_START_FAILED;
487     }
488     return proxy->GetDefaultInputMethod(property, false);
489 }
490 
GetInputMethodConfig(OHOS::AppExecFwk::ElementName & inputMethodConfig)491 int32_t InputMethodController::GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig)
492 {
493     InputMethodSyncTrace tracer("IMC_GetInputMethodConfig");
494     IMSA_HILOGD("InputMethodController::inputMethodConfig start.");
495     auto proxy = GetSystemAbilityProxy();
496     if (proxy == nullptr) {
497         IMSA_HILOGE("proxy is nullptr!");
498         return ErrorCode::ERROR_SERVICE_START_FAILED;
499     }
500     return proxy->GetInputMethodConfig(inputMethodConfig);
501 }
502 
GetCurrentInputMethod()503 std::shared_ptr<Property> InputMethodController::GetCurrentInputMethod()
504 {
505     InputMethodSyncTrace tracer("IMC_GetCurrentInputMethod");
506     IMSA_HILOGD("InputMethodController::GetCurrentInputMethod start.");
507     auto proxy = GetSystemAbilityProxy();
508     if (proxy == nullptr) {
509         IMSA_HILOGE("proxy is nullptr!");
510         return nullptr;
511     }
512     auto property = proxy->GetCurrentInputMethod();
513     if (property == nullptr) {
514         IMSA_HILOGE("property is nullptr!");
515         return nullptr;
516     }
517     return property;
518 }
519 
GetCurrentInputMethodSubtype()520 std::shared_ptr<SubProperty> InputMethodController::GetCurrentInputMethodSubtype()
521 {
522     InputMethodSyncTrace tracer("IMC_GetCurrentInputMethodSubtype");
523     IMSA_HILOGD("InputMethodController::GetCurrentInputMethodSubtype start.");
524     auto proxy = GetSystemAbilityProxy();
525     if (proxy == nullptr) {
526         IMSA_HILOGE("proxy is nullptr!");
527         return nullptr;
528     }
529     auto property = proxy->GetCurrentInputMethodSubtype();
530     if (property == nullptr) {
531         IMSA_HILOGE("property is nullptr!");
532         return nullptr;
533     }
534     return property;
535 }
536 
IsDefaultImeSet()537 bool InputMethodController::IsDefaultImeSet()
538 {
539     IMSA_HILOGI("enter.");
540     auto proxy = GetSystemAbilityProxy();
541     if (proxy == nullptr) {
542         IMSA_HILOGE("proxy is nullptr!");
543         return false;
544     }
545     return proxy->IsDefaultImeSet();
546 }
547 
EnableIme(const std::string & bundleName)548 bool InputMethodController::EnableIme(const std::string &bundleName)
549 {
550     IMSA_HILOGI("enter.");
551     auto proxy = GetSystemAbilityProxy();
552     if (proxy == nullptr) {
553         IMSA_HILOGE("proxy is nullptr!");
554         return false;
555     }
556     return proxy->EnableIme(bundleName);
557 }
558 
StartInput(InputClientInfo & inputClientInfo,sptr<IRemoteObject> & agent,std::pair<int64_t,std::string> & imeInfo)559 int32_t InputMethodController::StartInput(
560     InputClientInfo &inputClientInfo, sptr<IRemoteObject> &agent, std::pair<int64_t, std::string> &imeInfo)
561 {
562     IMSA_HILOGD("InputMethodController::StartInput start.");
563     auto proxy = GetSystemAbilityProxy();
564     if (proxy == nullptr) {
565         IMSA_HILOGE("proxy is nullptr!");
566         return ErrorCode::ERROR_SERVICE_START_FAILED;
567     }
568     return proxy->StartInput(inputClientInfo, agent, imeInfo);
569 }
570 
ReleaseInput(sptr<IInputClient> & client)571 int32_t InputMethodController::ReleaseInput(sptr<IInputClient> &client)
572 {
573     IMSA_HILOGD("InputMethodController::ReleaseInput start.");
574     auto proxy = TryGetSystemAbilityProxy();
575     if (proxy == nullptr) {
576         IMSA_HILOGE("proxy is nullptr!");
577         return ErrorCode::ERROR_SERVICE_START_FAILED;
578     }
579     int32_t ret = proxy->ReleaseInput(client);
580     if (ret == ErrorCode::NO_ERROR) {
581         OnInputStop();
582     }
583     SetTextListener(nullptr);
584     return ret;
585 }
586 
ShowInput(sptr<IInputClient> & client,ClientType type,int32_t requestKeyboardReason)587 int32_t InputMethodController::ShowInput(sptr<IInputClient> &client, ClientType type, int32_t requestKeyboardReason)
588 {
589     IMSA_HILOGD("InputMethodController::ShowInput start.");
590     auto proxy = GetSystemAbilityProxy();
591     if (proxy == nullptr) {
592         IMSA_HILOGE("proxy is nullptr!");
593         return ErrorCode::ERROR_SERVICE_START_FAILED;
594     }
595     return proxy->ShowInput(client, type, requestKeyboardReason);
596 }
597 
HideInput(sptr<IInputClient> & client)598 int32_t InputMethodController::HideInput(sptr<IInputClient> &client)
599 {
600     IMSA_HILOGD("InputMethodController::HideInput start.");
601     auto proxy = GetSystemAbilityProxy();
602     if (proxy == nullptr) {
603         IMSA_HILOGE("proxy is nullptr!");
604         return ErrorCode::ERROR_SERVICE_START_FAILED;
605     }
606     return proxy->HideInput(client);
607 }
608 
OnRemoteSaDied(const wptr<IRemoteObject> & remote)609 void InputMethodController::OnRemoteSaDied(const wptr<IRemoteObject> &remote)
610 {
611     IMSA_HILOGI("input method service death.");
612     // imf sa died, current client callback inputStop
613     ImeEventMonitorManagerImpl::GetInstance().OnInputStop();
614     auto textListener = GetTextListener();
615     if (textListener != nullptr && textConfig_.inputAttribute.isTextPreviewSupported) {
616         IMSA_HILOGD("finish text preview.");
617         textListener->FinishTextPreview();
618     }
619     {
620         std::lock_guard<std::mutex> lock(abilityLock_);
621         abilityManager_ = nullptr;
622     }
623     if (handler_ == nullptr) {
624         IMSA_HILOGE("handler_ is nullptr!");
625         return;
626     }
627     RestoreClientInfoInSaDied();
628 }
629 
RestoreListenInfoInSaDied()630 void InputMethodController::RestoreListenInfoInSaDied()
631 {
632     {
633         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
634         if (clientInfo_.eventFlag == NO_EVENT_ON) {
635             return;
636         }
637     }
638     isDiedRestoreListen_.store(false);
639     auto restoreListenTask = [=]() {
640         if (isDiedRestoreListen_.load()) {
641             return;
642         }
643         auto ret = RestoreListenEventFlag();
644         if (ret == ErrorCode::NO_ERROR) {
645             isDiedRestoreListen_.store(true);
646             IMSA_HILOGI("try to RestoreListen success.");
647         }
648     };
649     for (int i = 0; i < LOOP_COUNT; i++) {
650         handler_->PostTask(restoreListenTask, "OnRemoteSaDied", DELAY_TIME * (i + 1),
651             AppExecFwk::EventQueue::Priority::VIP);
652     }
653 }
654 
RestoreClientInfoInSaDied()655 void InputMethodController::RestoreClientInfoInSaDied()
656 {
657     if (!IsEditable()) {
658         IMSA_HILOGD("not editable.");
659         RestoreListenInfoInSaDied();
660         return;
661     }
662     auto attach = [=]() -> bool {
663         TextConfig tempConfig {};
664         {
665             std::lock_guard<std::mutex> lock(textConfigLock_);
666             tempConfig = textConfig_;
667             tempConfig.cursorInfo = cursorInfo_;
668             tempConfig.range.start = selectNewBegin_;
669             tempConfig.range.end = selectNewEnd_;
670         }
671         auto listener = GetTextListener();
672         bool isShowKeyboard = false;
673         {
674             std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
675             isShowKeyboard = clientInfo_.isShowKeyboard;
676         }
677         auto errCode = Attach(listener, isShowKeyboard, tempConfig);
678         IMSA_HILOGI("attach end, errCode: %{public}d", errCode);
679         return errCode == ErrorCode::NO_ERROR;
680     };
681     if (attach()) {
682         return;
683     }
684     isDiedAttached_.store(false);
685     auto attachTask = [this, attach]() {
686         if (isDiedAttached_.load()) {
687             return;
688         }
689         attach();
690     };
691     for (int i = 0; i < LOOP_COUNT; i++) {
692         handler_->PostTask(attachTask, "OnRemoteSaDied", DELAY_TIME * (i + 1), AppExecFwk::EventQueue::Priority::VIP);
693     }
694 }
695 
OnCursorUpdate(CursorInfo cursorInfo)696 int32_t InputMethodController::OnCursorUpdate(CursorInfo cursorInfo)
697 {
698     if (!IsBound()) {
699         IMSA_HILOGD("not bound.");
700         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
701     }
702     if (!IsEditable()) {
703         IMSA_HILOGD("not editable.");
704         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
705     }
706     {
707         std::lock_guard<std::mutex> lock(textConfigLock_);
708         textConfig_.cursorInfo = cursorInfo;
709     }
710     {
711         std::lock_guard<std::mutex> lk(cursorInfoMutex_);
712         if (cursorInfo_ == cursorInfo) {
713             IMSA_HILOGD("same to last update.");
714             return ErrorCode::NO_ERROR;
715         }
716         cursorInfo_ = cursorInfo;
717     }
718     auto agent = GetAgent();
719     if (agent == nullptr) {
720         IMSA_HILOGE("agent is nullptr!");
721         return ErrorCode::ERROR_IME_NOT_STARTED;
722     }
723     IMSA_HILOGI("left: %{public}d, top: %{public}d, height: %{public}d.", static_cast<int32_t>(cursorInfo.left),
724         static_cast<int32_t>(cursorInfo.top), static_cast<int32_t>(cursorInfo.height));
725     agent->OnCursorUpdate(cursorInfo.left, cursorInfo.top, cursorInfo.height);
726     return ErrorCode::NO_ERROR;
727 }
728 
OnSelectionChange(std::u16string text,int start,int end)729 int32_t InputMethodController::OnSelectionChange(std::u16string text, int start, int end)
730 {
731     if (!IsBound()) {
732         IMSA_HILOGD("not bound.");
733         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
734     }
735     if (!IsEditable()) {
736         IMSA_HILOGD("not editable.");
737         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
738     }
739     {
740         std::lock_guard<std::mutex> lock(textConfigLock_);
741         textConfig_.range = { start, end };
742     }
743     if (isTextNotified_.exchange(true) && textString_ == text && selectNewBegin_ == start && selectNewEnd_ == end) {
744         IMSA_HILOGD("same to last update.");
745         return ErrorCode::NO_ERROR;
746     }
747     textString_ = text;
748     selectOldBegin_ = selectNewBegin_;
749     selectOldEnd_ = selectNewEnd_;
750     selectNewBegin_ = start;
751     selectNewEnd_ = end;
752     auto agent = GetAgent();
753     if (agent == nullptr) {
754         IMSA_HILOGE("agent is nullptr!");
755         return ErrorCode::ERROR_IME_NOT_STARTED;
756     }
757     IMSA_HILOGI("IMC size: %{public}zu, range: %{public}d/%{public}d/%{public}d/%{public}d.", text.size(),
758         selectOldBegin_, selectOldEnd_, start, end);
759     agent->OnSelectionChange(textString_, selectOldBegin_, selectOldEnd_, selectNewBegin_, selectNewEnd_);
760     return ErrorCode::NO_ERROR;
761 }
762 
OnConfigurationChange(Configuration info)763 int32_t InputMethodController::OnConfigurationChange(Configuration info)
764 {
765     if (!IsBound()) {
766         IMSA_HILOGD("not bound.");
767         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
768     }
769     bool oldSecurityFlag = textConfig_.inputAttribute.GetSecurityFlag();
770     InputAttribute attribute;
771     {
772         std::lock_guard<std::mutex> lock(textConfigLock_);
773         textConfig_.inputAttribute.enterKeyType = static_cast<int32_t>(info.GetEnterKeyType());
774         textConfig_.inputAttribute.inputPattern = static_cast<int32_t>(info.GetTextInputType());
775         attribute = textConfig_.inputAttribute;
776     }
777     if (!IsEditable()) {
778         IMSA_HILOGD("not editable.");
779         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
780     }
781     IMSA_HILOGI(
782         "IMC enterKeyType: %{public}d, textInputType: %{public}d.", attribute.enterKeyType, attribute.inputPattern);
783     if (oldSecurityFlag != attribute.GetSecurityFlag()) {
784         GetTextConfig(clientInfo_.config);
785         sptr<IRemoteObject> agent = nullptr;
786         std::pair<int64_t, std::string> imeInfo{ 0, "" };
787         int32_t ret = StartInput(clientInfo_, agent, imeInfo);
788         if (ret != ErrorCode::NO_ERROR) {
789             return ret;
790         }
791         OnInputReady(agent, imeInfo);
792     }
793     auto agent = GetAgent();
794     if (agent == nullptr) {
795         IMSA_HILOGE("agent is nullptr!");
796         return ErrorCode::ERROR_IME_NOT_STARTED;
797     }
798     agent->OnAttributeChange(attribute);
799     return ErrorCode::NO_ERROR;
800 }
801 
GetLeft(int32_t length,std::u16string & text)802 int32_t InputMethodController::GetLeft(int32_t length, std::u16string &text)
803 {
804     InputMethodSyncTrace tracer("IMC_GetForward");
805     IMSA_HILOGD("start, length: %{public}d", length);
806     auto listener = GetTextListener();
807     if (!IsEditable() || listener == nullptr) {
808         IMSA_HILOGE("not editable or listener is nullptr!");
809         ReportBaseTextOperation(IInputDataChannel::GET_TEXT_BEFORE_CURSOR, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
810         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
811     }
812     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
813     {
814         InputMethodSyncTrace aceTracer("ACE_GetForward");
815         text = listener->GetLeftTextOfCursor(length);
816     }
817     PrintLogIfAceTimeout(start);
818     return ErrorCode::NO_ERROR;
819 }
820 
GetRight(int32_t length,std::u16string & text)821 int32_t InputMethodController::GetRight(int32_t length, std::u16string &text)
822 {
823     IMSA_HILOGD("start, length: %{public}d", length);
824     auto listener = GetTextListener();
825     if (!IsEditable() || listener == nullptr) {
826         IMSA_HILOGE("not editable or textListener_ is nullptr!");
827         ReportBaseTextOperation(IInputDataChannel::GET_TEXT_AFTER_CURSOR, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
828         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
829     }
830     text = listener->GetRightTextOfCursor(length);
831     return ErrorCode::NO_ERROR;
832 }
833 
GetTextIndexAtCursor(int32_t & index)834 int32_t InputMethodController::GetTextIndexAtCursor(int32_t &index)
835 {
836     IMSA_HILOGD("start.");
837     auto listener = GetTextListener();
838     if (!IsEditable() || listener == nullptr) {
839         IMSA_HILOGE("not editable or textListener_ is nullptr!");
840         ReportBaseTextOperation(IInputDataChannel::GET_TEXT_INDEX_AT_CURSOR, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
841         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
842     }
843     index = listener->GetTextIndexAtCursor();
844     return ErrorCode::NO_ERROR;
845 }
846 
PrintKeyEventLog()847 void InputMethodController::PrintKeyEventLog()
848 {
849     std::lock_guard<std::mutex> lock(logLock_);
850     auto now = system_clock::now();
851     if (keyEventCountInPeriod_ == 0) {
852         startLogTime_ = now;
853     }
854     keyEventCountInPeriod_++;
855     if (std::chrono::duration_cast<seconds>(now - startLogTime_).count() >= LOG_MAX_TIME) {
856         auto start = std::chrono::duration_cast<seconds>(startLogTime_.time_since_epoch()).count();
857         auto end = std::chrono::duration_cast<seconds>(now.time_since_epoch()).count();
858         IMSA_HILOGI("KeyEventCountInPeriod: %{public}d, startTime: %{public}lld, endTime: %{public}lld",
859             keyEventCountInPeriod_, start, end);
860         keyEventCountInPeriod_ = 0;
861     }
862 }
863 
DispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent,KeyEventCallback callback)864 int32_t InputMethodController::DispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent, KeyEventCallback callback)
865 {
866     PrintKeyEventLog();
867     KeyEventInfo keyEventInfo = { std::chrono::system_clock::now(), keyEvent };
868     keyEventQueue_.Push(keyEventInfo);
869     InputMethodSyncTrace tracer("DispatchKeyEvent trace");
870     keyEventQueue_.Wait(keyEventInfo);
871     if (!IsEditable()) {
872         IMSA_HILOGD("not editable.");
873         keyEventQueue_.Pop();
874         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
875     }
876     if (keyEvent == nullptr) {
877         IMSA_HILOGE("keyEvent is nullptr!");
878         keyEventQueue_.Pop();
879         return ErrorCode::ERROR_EX_NULL_POINTER;
880     }
881     auto agent = GetAgent();
882     if (agent == nullptr) {
883         IMSA_HILOGE("agent is nullptr!");
884         keyEventQueue_.Pop();
885         return ErrorCode::ERROR_IME_NOT_STARTED;
886     }
887     IMSA_HILOGD("start.");
888     sptr<IKeyEventConsumer> consumer = new (std::nothrow) KeyEventConsumerStub(callback, keyEvent);
889     if (consumer == nullptr) {
890         IMSA_HILOGE("consumer is nullptr!");
891         keyEventQueue_.Pop();
892         return ErrorCode::ERROR_EX_NULL_POINTER;
893     }
894     auto ret = agent->DispatchKeyEvent(keyEvent, consumer);
895     if (ret != ErrorCode::NO_ERROR) {
896         IMSA_HILOGE("failed to DispatchKeyEvent: %{public}d", ret);
897     }
898     keyEventQueue_.Pop();
899     return ret;
900 }
901 
GetEnterKeyType(int32_t & keyType)902 int32_t InputMethodController::GetEnterKeyType(int32_t &keyType)
903 {
904     IMSA_HILOGD("InputMethodController::GetEnterKeyType start.");
905     std::lock_guard<std::mutex> lock(textConfigLock_);
906     keyType = textConfig_.inputAttribute.enterKeyType;
907     return ErrorCode::NO_ERROR;
908 }
909 
GetInputPattern(int32_t & inputpattern)910 int32_t InputMethodController::GetInputPattern(int32_t &inputpattern)
911 {
912     IMSA_HILOGD("InputMethodController::GetInputPattern start.");
913     std::lock_guard<std::mutex> lock(textConfigLock_);
914     inputpattern = textConfig_.inputAttribute.inputPattern;
915     return ErrorCode::NO_ERROR;
916 }
917 
GetTextConfig(TextTotalConfig & config)918 int32_t InputMethodController::GetTextConfig(TextTotalConfig &config)
919 {
920     std::lock_guard<std::mutex> lock(textConfigLock_);
921     config.inputAttribute = textConfig_.inputAttribute;
922     config.cursorInfo = textConfig_.cursorInfo;
923     config.windowId = textConfig_.windowId;
924     config.positionY = textConfig_.positionY;
925     config.height = textConfig_.height;
926     config.privateCommand = textConfig_.privateCommand;
927     if (textConfig_.range.start == INVALID_VALUE) {
928         IMSA_HILOGD("SelectionRange is invalid.");
929     } else {
930         {
931             std::lock_guard<std::mutex> editorLock(editorContentLock_);
932             config.textSelection.oldBegin = selectOldBegin_;
933             config.textSelection.oldEnd = selectOldEnd_;
934         }
935         config.textSelection.newBegin = textConfig_.range.start;
936         config.textSelection.newEnd = textConfig_.range.end;
937     }
938     IMSA_HILOGD("textConfig: %{public}s.", config.ToString().c_str());
939     return ErrorCode::NO_ERROR;
940 }
941 
SetCallingWindow(uint32_t windowId)942 int32_t InputMethodController::SetCallingWindow(uint32_t windowId)
943 {
944     if (!IsBound()) {
945         IMSA_HILOGD("not bound.");
946         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
947     }
948     if (!IsEditable()) {
949         IMSA_HILOGD("not editable.");
950         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
951     }
952     {
953         std::lock_guard<std::mutex> lock(textConfigLock_);
954         textConfig_.windowId = windowId;
955     }
956     auto agent = GetAgent();
957     if (agent == nullptr) {
958         IMSA_HILOGE("agent is nullptr!");
959         return ErrorCode::ERROR_IME_NOT_STARTED;
960     }
961     IMSA_HILOGI("windowId: %{public}d.", windowId);
962     agent->SetCallingWindow(windowId);
963     auto proxy = GetSystemAbilityProxy();
964     if (proxy != nullptr) {
965         proxy->SetCallingWindow(windowId, clientInfo_.client);
966     }
967     return ErrorCode::NO_ERROR;
968 }
969 
ShowSoftKeyboardInner(ClientType type)970 int32_t InputMethodController::ShowSoftKeyboardInner(ClientType type)
971 {
972     auto proxy = GetSystemAbilityProxy();
973     if (proxy == nullptr) {
974         IMSA_HILOGE("proxy is nullptr!");
975         return ErrorCode::ERROR_SERVICE_START_FAILED;
976     }
977     IMSA_HILOGI("start.");
978     {
979         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
980         clientInfo_.isShowKeyboard = true;
981     }
982     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_NORMAL);
983     return proxy->ShowCurrentInput(type);
984 }
985 
HideSoftKeyboard()986 int32_t InputMethodController::HideSoftKeyboard()
987 {
988     auto proxy = GetSystemAbilityProxy();
989     if (proxy == nullptr) {
990         IMSA_HILOGE("proxy is nullptr!");
991         return ErrorCode::ERROR_EX_NULL_POINTER;
992     }
993     IMSA_HILOGI("start.");
994     {
995         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
996         clientInfo_.isShowKeyboard = false;
997     }
998     InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_NORMAL);
999     return proxy->HideCurrentInput();
1000 }
1001 
StopInputSession()1002 int32_t InputMethodController::StopInputSession()
1003 {
1004     IMSA_HILOGI("start.");
1005     isEditable_.store(false);
1006     auto proxy = GetSystemAbilityProxy();
1007     if (proxy == nullptr) {
1008         IMSA_HILOGE("proxy is nullptr!");
1009         return ErrorCode::ERROR_EX_NULL_POINTER;
1010     }
1011     return proxy->StopInputSession();
1012 }
1013 
ShowOptionalInputMethod()1014 int32_t InputMethodController::ShowOptionalInputMethod()
1015 {
1016     auto proxy = GetSystemAbilityProxy();
1017     if (proxy == nullptr) {
1018         IMSA_HILOGE("proxy is nullptr!");
1019         return ErrorCode::ERROR_EX_NULL_POINTER;
1020     }
1021     IMSA_HILOGI("IMC start.");
1022     return proxy->DisplayOptionalInputMethod();
1023 }
1024 
ListInputMethodSubtype(const Property & property,std::vector<SubProperty> & subProps)1025 int32_t InputMethodController::ListInputMethodSubtype(const Property &property, std::vector<SubProperty> &subProps)
1026 {
1027     auto proxy = GetSystemAbilityProxy();
1028     if (proxy == nullptr) {
1029         IMSA_HILOGE("proxy is nullptr!");
1030         return ErrorCode::ERROR_EX_NULL_POINTER;
1031     }
1032     IMSA_HILOGD("ime bundleName: %{public}s.", property.name.c_str());
1033     return proxy->ListInputMethodSubtype(property.name, subProps);
1034 }
1035 
ListCurrentInputMethodSubtype(std::vector<SubProperty> & subProps)1036 int32_t InputMethodController::ListCurrentInputMethodSubtype(std::vector<SubProperty> &subProps)
1037 {
1038     auto proxy = GetSystemAbilityProxy();
1039     if (proxy == nullptr) {
1040         IMSA_HILOGE("proxy is nullptr!");
1041         return ErrorCode::ERROR_EX_NULL_POINTER;
1042     }
1043     IMSA_HILOGD("start.");
1044     return proxy->ListCurrentInputMethodSubtype(subProps);
1045 }
1046 
SwitchInputMethod(SwitchTrigger trigger,const std::string & name,const std::string & subName)1047 int32_t InputMethodController::SwitchInputMethod(
1048     SwitchTrigger trigger, const std::string &name, const std::string &subName)
1049 {
1050     InputMethodSyncTrace tracer("IMC_SwitchInputMethod");
1051     auto proxy = GetSystemAbilityProxy();
1052     if (proxy == nullptr) {
1053         IMSA_HILOGE("proxy is nullptr!");
1054         return ErrorCode::ERROR_EX_NULL_POINTER;
1055     }
1056     IMSA_HILOGI("name: %{public}s, subName: %{public}s, trigger: %{public}d.", name.c_str(), subName.c_str(),
1057         static_cast<uint32_t>(trigger));
1058     return proxy->SwitchInputMethod(name, subName, trigger);
1059 }
1060 
OnInputReady(sptr<IRemoteObject> agentObject,const std::pair<int64_t,std::string> & imeInfo)1061 void InputMethodController::OnInputReady(
1062     sptr<IRemoteObject> agentObject, const std::pair<int64_t, std::string> &imeInfo)
1063 {
1064     IMSA_HILOGI("InputMethodController start.");
1065     SetBindImeInfo(imeInfo);
1066     isBound_.store(true);
1067     isEditable_.store(true);
1068     if (agentObject == nullptr) {
1069         IMSA_HILOGE("agentObject is nullptr!");
1070         return;
1071     }
1072     SetAgent(agentObject);
1073 }
1074 
OnInputStop(bool isStopInactiveClient)1075 void InputMethodController::OnInputStop(bool isStopInactiveClient)
1076 {
1077     {
1078         std::lock_guard<std::mutex> autoLock(agentLock_);
1079         agent_ = nullptr;
1080         agentObject_ = nullptr;
1081     }
1082     auto listener = GetTextListener();
1083     if (listener != nullptr) {
1084         IMSA_HILOGD("listener is not nullptr!");
1085         if (textConfig_.inputAttribute.isTextPreviewSupported) {
1086             IMSA_HILOGD("finish text preview.");
1087             listener->FinishTextPreview();
1088         }
1089         if (!isStopInactiveClient || !listener->IsFromTs()) {
1090             listener->SendKeyboardStatus(KeyboardStatus::HIDE);
1091         }
1092     }
1093     isBound_.store(false);
1094     isEditable_.store(false);
1095 }
1096 
ClearEditorCache(bool isNewEditor,sptr<OnTextChangedListener> lastListener)1097 void InputMethodController::ClearEditorCache(bool isNewEditor, sptr<OnTextChangedListener> lastListener)
1098 {
1099     IMSA_HILOGD("isNewEditor: %{public}d.", isNewEditor);
1100     if (isNewEditor && isBound_.load() && lastListener != nullptr &&
1101         textConfig_.inputAttribute.isTextPreviewSupported) {
1102         IMSA_HILOGD("last editor FinishTextPreview");
1103         lastListener->FinishTextPreview();
1104     }
1105     {
1106         std::lock_guard<std::mutex> lock(editorContentLock_);
1107         // reset old range when editor changes or first attach
1108         if (isNewEditor || !isBound_.load()) {
1109             isTextNotified_.store(false);
1110             textString_ = Str8ToStr16("");
1111             selectOldBegin_ = INVALID_VALUE;
1112             selectOldEnd_ = INVALID_VALUE;
1113             selectNewBegin_ = INVALID_VALUE;
1114             selectNewEnd_ = INVALID_VALUE;
1115         }
1116     }
1117     {
1118         std::lock_guard<std::mutex> lock(textConfigLock_);
1119         textConfig_ = {};
1120     }
1121     {
1122         std::lock_guard<std::mutex> lock(cursorInfoMutex_);
1123         cursorInfo_ = {};
1124     }
1125     clientInfo_.config = {};
1126 }
1127 
SelectByRange(int32_t start,int32_t end)1128 void InputMethodController::SelectByRange(int32_t start, int32_t end)
1129 {
1130     IMSA_HILOGD("InputMethodController start: %{public}d, end: %{public}d.", start, end);
1131     auto listener = GetTextListener();
1132     if (IsEditable() && listener != nullptr) {
1133         listener->HandleSetSelection(start, end);
1134     } else {
1135         IMSA_HILOGE("not editable or textListener_ is nullptr!");
1136     }
1137 
1138     if (controllerListener_ != nullptr) {
1139         controllerListener_->OnSelectByRange(start, end);
1140     } else {
1141         IMSA_HILOGE("controllerListener_ is nullptr!");
1142     }
1143 }
1144 
SelectByMovement(int32_t direction,int32_t cursorMoveSkip)1145 void InputMethodController::SelectByMovement(int32_t direction, int32_t cursorMoveSkip)
1146 {
1147     IMSA_HILOGD(
1148         "InputMethodController start, direction: %{public}d, cursorMoveSkip: %{public}d", direction, cursorMoveSkip);
1149     auto listener = GetTextListener();
1150     if (IsEditable() && listener != nullptr) {
1151         listener->HandleSelect(CURSOR_DIRECTION_BASE_VALUE + direction, cursorMoveSkip);
1152     } else {
1153         IMSA_HILOGE("not editable or textListener_ is nullptr!");
1154     }
1155 
1156     if (controllerListener_ != nullptr) {
1157         controllerListener_->OnSelectByMovement(direction);
1158     } else {
1159         IMSA_HILOGE("controllerListener_ is nullptr!");
1160     }
1161 }
1162 
HandleExtendAction(int32_t action)1163 int32_t InputMethodController::HandleExtendAction(int32_t action)
1164 {
1165     IMSA_HILOGD("InputMethodController start, action: %{public}d.", action);
1166     auto listener = GetTextListener();
1167     if (!IsEditable() || listener == nullptr) {
1168         IMSA_HILOGE("not editable or textListener is nullptr!");
1169         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1170     }
1171     listener->HandleExtendAction(action);
1172     return ErrorCode::NO_ERROR;
1173 }
1174 
GetTextListener()1175 sptr<OnTextChangedListener> InputMethodController::GetTextListener()
1176 {
1177     std::lock_guard<std::mutex> lock(textListenerLock_);
1178     return textListener_;
1179 }
1180 
SetTextListener(sptr<OnTextChangedListener> listener)1181 void InputMethodController::SetTextListener(sptr<OnTextChangedListener> listener)
1182 {
1183     std::lock_guard<std::mutex> lock(textListenerLock_);
1184     textListener_ = listener;
1185 }
1186 
IsEditable()1187 bool InputMethodController::IsEditable()
1188 {
1189     std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1190     if (clientInfo_.state != ClientState::ACTIVE) {
1191         IMSA_HILOGD("client is not active.");
1192         return false;
1193     }
1194     if (!isEditable_.load()) {
1195         IMSA_HILOGD("not in editable state.");
1196         return false;
1197     }
1198     return true;
1199 }
1200 
IsBound()1201 bool InputMethodController::IsBound()
1202 {
1203     std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1204     if (clientInfo_.state != ClientState::ACTIVE) {
1205         IMSA_HILOGD("client is not active.");
1206         return false;
1207     }
1208     if (!isBound_.load()) {
1209         IMSA_HILOGD("not bound.");
1210         return false;
1211     }
1212     return true;
1213 }
1214 
InsertText(const std::u16string & text)1215 int32_t InputMethodController::InsertText(const std::u16string &text)
1216 {
1217     InputMethodSyncTrace tracer("IMC_InsertText");
1218     IMSA_HILOGD("start.");
1219     auto listener = GetTextListener();
1220     if (!IsEditable() || listener == nullptr) {
1221         IMSA_HILOGE("not editable or textListener is nullptr!");
1222         ReportBaseTextOperation(IInputDataChannel::INSERT_TEXT, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1223         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1224     }
1225     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1226     {
1227         InputMethodSyncTrace aceTracer("ACE_InsertText");
1228         IMSA_HILOGD("ACE InsertText.");
1229         listener->InsertText(text);
1230     }
1231 
1232     PrintLogIfAceTimeout(start);
1233     return ErrorCode::NO_ERROR;
1234 }
1235 
DeleteForward(int32_t length)1236 int32_t InputMethodController::DeleteForward(int32_t length)
1237 {
1238     InputMethodSyncTrace tracer("IMC_DeleteForward");
1239     IMSA_HILOGD("start, length: %{public}d.", length);
1240     auto listener = GetTextListener();
1241     if (!IsEditable() || listener == nullptr) {
1242         IMSA_HILOGE("not editable or textListener is nullptr!");
1243         ReportBaseTextOperation(IInputDataChannel::DELETE_FORWARD, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1244         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1245     }
1246     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1247     {
1248         InputMethodSyncTrace aceTracer("ACE_DeleteForward");
1249         // reverse for compatibility
1250         listener->DeleteBackward(length);
1251     }
1252     PrintLogIfAceTimeout(start);
1253     return ErrorCode::NO_ERROR;
1254 }
1255 
DeleteBackward(int32_t length)1256 int32_t InputMethodController::DeleteBackward(int32_t length)
1257 {
1258     IMSA_HILOGD("InputMethodController start, length: %{public}d.", length);
1259     auto listener = GetTextListener();
1260     if (!IsEditable() || listener == nullptr) {
1261         IMSA_HILOGE("not editable or textListener is nullptr!");
1262         ReportBaseTextOperation(IInputDataChannel::DELETE_BACKWARD, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1263         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1264     }
1265     // reverse for compatibility
1266     listener->DeleteForward(length);
1267     return ErrorCode::NO_ERROR;
1268 }
1269 
MoveCursor(Direction direction)1270 int32_t InputMethodController::MoveCursor(Direction direction)
1271 {
1272     IMSA_HILOGD("InputMethodController start, direction: %{public}d.", static_cast<int32_t>(direction));
1273     auto listener = GetTextListener();
1274     if (!IsEditable() || listener == nullptr) {
1275         IMSA_HILOGE("not editable or textListener_ is nullptr!");
1276         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1277     }
1278     listener->MoveCursor(direction);
1279     return ErrorCode::NO_ERROR;
1280 }
1281 
SendKeyboardStatus(KeyboardStatus status)1282 void InputMethodController::SendKeyboardStatus(KeyboardStatus status)
1283 {
1284     IMSA_HILOGD("InputMethodController status: %{public}d.", static_cast<int32_t>(status));
1285     auto listener = GetTextListener();
1286     if (listener == nullptr) {
1287         IMSA_HILOGE("listener is nullptr!");
1288         return;
1289     }
1290     listener->SendKeyboardStatus(status);
1291     if (status == KeyboardStatus::HIDE) {
1292         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1293         clientInfo_.isShowKeyboard = false;
1294     }
1295 }
1296 
NotifyPanelStatusInfo(const PanelStatusInfo & info)1297 void InputMethodController::NotifyPanelStatusInfo(const PanelStatusInfo &info)
1298 {
1299     IMSA_HILOGD("InputMethodController start, type: %{public}d, flag: %{public}d, visible: %{public}d, trigger: "
1300                 "%{public}d.",
1301         static_cast<PanelType>(info.panelInfo.panelType), static_cast<PanelFlag>(info.panelInfo.panelFlag),
1302         info.visible, static_cast<Trigger>(info.trigger));
1303     auto listener = GetTextListener();
1304     if (listener == nullptr) {
1305         IMSA_HILOGE("listener is nullptr!");
1306         return;
1307     }
1308     if (info.panelInfo.panelType == PanelType::SOFT_KEYBOARD) {
1309         info.visible ? SendKeyboardStatus(KeyboardStatus::SHOW) : SendKeyboardStatus(KeyboardStatus::HIDE);
1310     }
1311     listener->NotifyPanelStatusInfo(info);
1312     if (info.panelInfo.panelType == PanelType::SOFT_KEYBOARD &&
1313         info.panelInfo.panelFlag != PanelFlag::FLG_CANDIDATE_COLUMN && !info.visible) {
1314         std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1315         clientInfo_.isShowKeyboard = false;
1316     }
1317 }
1318 
NotifyKeyboardHeight(uint32_t height)1319 void InputMethodController::NotifyKeyboardHeight(uint32_t height)
1320 {
1321     IMSA_HILOGD("InputMethodController start, height: %{public}u.", height);
1322     auto listener = GetTextListener();
1323     if (listener == nullptr) {
1324         IMSA_HILOGE("listener is nullptr!");
1325         return;
1326     }
1327     listener->NotifyKeyboardHeight(height);
1328 }
1329 
SendFunctionKey(int32_t functionKey)1330 int32_t InputMethodController::SendFunctionKey(int32_t functionKey)
1331 {
1332     IMSA_HILOGD("InputMethodController start, functionKey: %{public}d", static_cast<int32_t>(functionKey));
1333     auto listener = GetTextListener();
1334     if (!IsEditable() || listener == nullptr) {
1335         IMSA_HILOGE("not editable or listener is nullptr!");
1336         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1337     }
1338     FunctionKey funcKey;
1339     funcKey.SetEnterKeyType(static_cast<EnterKeyType>(functionKey));
1340     listener->SendFunctionKey(funcKey);
1341     return ErrorCode::NO_ERROR;
1342 }
1343 
IsInputTypeSupported(InputType type)1344 bool InputMethodController::IsInputTypeSupported(InputType type)
1345 {
1346     auto proxy = GetSystemAbilityProxy();
1347     if (proxy == nullptr) {
1348         IMSA_HILOGE("proxy is nullptr!");
1349         return ErrorCode::ERROR_NULL_POINTER;
1350     }
1351     IMSA_HILOGI("type: %{public}d.", static_cast<int32_t>(type));
1352     return proxy->IsInputTypeSupported(type);
1353 }
1354 
IsCurrentImeByPid(int32_t pid)1355 bool InputMethodController::IsCurrentImeByPid(int32_t pid)
1356 {
1357     auto proxy = GetSystemAbilityProxy();
1358     if (proxy == nullptr) {
1359         IMSA_HILOGE("proxy is nullptr!");
1360         return false;
1361     }
1362     return proxy->IsCurrentImeByPid(pid);
1363 }
1364 
StartInputType(InputType type)1365 int32_t InputMethodController::StartInputType(InputType type)
1366 {
1367     auto proxy = GetSystemAbilityProxy();
1368     if (proxy == nullptr) {
1369         IMSA_HILOGE("proxy is nullptr!");
1370         return ErrorCode::ERROR_NULL_POINTER;
1371     }
1372     IMSA_HILOGI("type: %{public}d.", static_cast<int32_t>(type));
1373     return proxy->StartInputType(type);
1374 }
1375 
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)1376 int32_t InputMethodController::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
1377 {
1378     auto proxy = GetSystemAbilityProxy();
1379     if (proxy == nullptr) {
1380         IMSA_HILOGE("proxy is nullptr!");
1381         return ErrorCode::ERROR_NULL_POINTER;
1382     }
1383     IMSA_HILOGD("type: %{public}d, flag: %{public}d.", static_cast<int32_t>(panelInfo.panelType),
1384         static_cast<int32_t>(panelInfo.panelFlag));
1385     return proxy->IsPanelShown(panelInfo, isShown);
1386 }
1387 
SetAgent(sptr<IRemoteObject> & agentObject)1388 void InputMethodController::SetAgent(sptr<IRemoteObject> &agentObject)
1389 {
1390     std::lock_guard<std::mutex> autoLock(agentLock_);
1391     if (agent_ != nullptr && agentObject_.GetRefPtr() == agentObject.GetRefPtr()) {
1392         IMSA_HILOGD("agent has already been set.");
1393         return;
1394     }
1395     agent_ = std::make_shared<InputMethodAgentProxy>(agentObject);
1396     agentObject_ = agentObject;
1397 }
1398 
GetAgent()1399 std::shared_ptr<IInputMethodAgent> InputMethodController::GetAgent()
1400 {
1401     std::lock_guard<std::mutex> autoLock(agentLock_);
1402     return agent_;
1403 }
1404 
PrintLogIfAceTimeout(int64_t start)1405 void InputMethodController::PrintLogIfAceTimeout(int64_t start)
1406 {
1407     int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1408     if (end - start > ACE_DEAL_TIME_OUT) {
1409         IMSA_HILOGW("timeout: [%{public}" PRId64 ", %{public}" PRId64 "].", start, end);
1410     }
1411 }
1412 
ReceivePrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1413 int32_t InputMethodController::ReceivePrivateCommand(
1414     const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1415 {
1416     auto listener = GetTextListener();
1417     if (listener == nullptr) {
1418         IMSA_HILOGE("listener is nullptr!");
1419         return ErrorCode::ERROR_EX_NULL_POINTER;
1420     }
1421     IMSA_HILOGD("IMC in.");
1422     auto ret = listener->ReceivePrivateCommand(privateCommand);
1423     if (ret != ErrorCode::NO_ERROR) {
1424         IMSA_HILOGE("ReceivePrivateCommand err, ret: %{public}d!", ret);
1425         return ErrorCode::ERROR_TEXT_LISTENER_ERROR;
1426     }
1427     return ErrorCode::NO_ERROR;
1428 }
1429 
SendPrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1430 int32_t InputMethodController::SendPrivateCommand(
1431     const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1432 {
1433     if (!IsBound()) {
1434         IMSA_HILOGD("not bound.");
1435         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
1436     }
1437     if (!IsEditable()) {
1438         IMSA_HILOGD("not editable.");
1439         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1440     }
1441     if (!TextConfig::IsPrivateCommandValid(privateCommand)) {
1442         IMSA_HILOGE("invalid private command size!");
1443         return ErrorCode::ERROR_INVALID_PRIVATE_COMMAND_SIZE;
1444     }
1445     auto agent = GetAgent();
1446     if (agent == nullptr) {
1447         IMSA_HILOGE("agent is nullptr!");
1448         return ErrorCode::ERROR_IME_NOT_STARTED;
1449     }
1450     IMSA_HILOGD("IMC start.");
1451     return agent->SendPrivateCommand(privateCommand);
1452 }
1453 
SetBindImeInfo(const std::pair<int64_t,std::string> & imeInfo)1454 void InputMethodController::SetBindImeInfo(const std::pair<int64_t, std::string> &imeInfo)
1455 {
1456     std::lock_guard<std::mutex> lock(bindImeInfoLock_);
1457     bindImeInfo_ = imeInfo;
1458 }
1459 
GetBindImeInfo()1460 std::pair<int64_t, std::string> InputMethodController::GetBindImeInfo()
1461 {
1462     std::lock_guard<std::mutex> lock(bindImeInfoLock_);
1463     return bindImeInfo_;
1464 }
1465 
SetPreviewTextInner(const std::string & text,const Range & range)1466 int32_t InputMethodController::SetPreviewTextInner(const std::string &text, const Range &range)
1467 {
1468     InputMethodSyncTrace tracer("IMC_SetPreviewText");
1469     IMSA_HILOGD("IMC start.");
1470     if (!textConfig_.inputAttribute.isTextPreviewSupported) {
1471         IMSA_HILOGE("text preview do not supported!");
1472         return ErrorCode::ERROR_TEXT_PREVIEW_NOT_SUPPORTED;
1473     }
1474     auto listener = GetTextListener();
1475     if (!IsEditable() || listener == nullptr) {
1476         IMSA_HILOGE("not editable or listener is nullptr!");
1477         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1478     }
1479     int32_t ret = 0;
1480     int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1481     {
1482         InputMethodSyncTrace aceTracer("ACE_SetPreviewText");
1483         ret = listener->SetPreviewText(Str8ToStr16(text), range);
1484     }
1485     PrintLogIfAceTimeout(start);
1486     if (ret != ErrorCode::NO_ERROR) {
1487         IMSA_HILOGE("failed to SetPreviewText: %{public}d!", ret);
1488         return ret == -1 ? ErrorCode::ERROR_INVALID_RANGE : ErrorCode::ERROR_TEXT_LISTENER_ERROR;
1489     }
1490     return ErrorCode::NO_ERROR;
1491 }
1492 
FinishTextPreview()1493 int32_t InputMethodController::FinishTextPreview()
1494 {
1495     InputMethodSyncTrace tracer("IMC_FinishTextPreview");
1496     IMSA_HILOGD("IMC start.");
1497     if (!textConfig_.inputAttribute.isTextPreviewSupported) {
1498         IMSA_HILOGD("text preview do not supported!");
1499         ReportBaseTextOperation(IInputDataChannel::FINISH_TEXT_PREVIEW, ErrorCode::ERROR_TEXT_PREVIEW_NOT_SUPPORTED);
1500         return ErrorCode::ERROR_TEXT_PREVIEW_NOT_SUPPORTED;
1501     }
1502     auto listener = GetTextListener();
1503     if (!isBound_.load() || listener == nullptr) {
1504         IMSA_HILOGW("not bound or listener is nullptr!");
1505         ReportBaseTextOperation(IInputDataChannel::FINISH_TEXT_PREVIEW, ErrorCode::ERROR_CLIENT_NOT_EDITABLE);
1506         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1507     }
1508     {
1509         InputMethodSyncTrace aceTracer("ACE_FinishTextPreview");
1510         listener->FinishTextPreview();
1511     }
1512     return ErrorCode::NO_ERROR;
1513 }
1514 
SendMessage(const ArrayBuffer & arrayBuffer)1515 int32_t InputMethodController::SendMessage(const ArrayBuffer &arrayBuffer)
1516 {
1517     if (!IsBound()) {
1518         IMSA_HILOGE("not bound.");
1519         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
1520     }
1521     if (!IsEditable()) {
1522         IMSA_HILOGE("not editable.");
1523         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1524     }
1525     if (!ArrayBuffer::IsSizeValid(arrayBuffer)) {
1526         IMSA_HILOGE("arrayBuffer size is invalid!");
1527         return ErrorCode::ERROR_INVALID_ARRAY_BUFFER_SIZE;
1528     }
1529     auto agent = GetAgent();
1530     if (agent == nullptr) {
1531         IMSA_HILOGE("agent is nullptr!");
1532         return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1533     }
1534     return agent->SendMessage(arrayBuffer);
1535 }
1536 
RecvMessage(const ArrayBuffer & arrayBuffer)1537 int32_t InputMethodController::RecvMessage(const ArrayBuffer &arrayBuffer)
1538 {
1539     if (!IsBound()) {
1540         IMSA_HILOGE("not bound.");
1541         return ErrorCode::ERROR_CLIENT_NOT_BOUND;
1542     }
1543     if (!IsEditable()) {
1544         IMSA_HILOGE("not editable.");
1545         return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1546     }
1547     auto msgHandlerCallback = GetMsgHandlerCallback();
1548     if (msgHandlerCallback == nullptr) {
1549         IMSA_HILOGW("Message handler was not regist!");
1550         return ErrorCode::ERROR_MSG_HANDLER_NOT_REGIST;
1551     }
1552     return msgHandlerCallback->OnMessage(arrayBuffer);
1553 }
1554 
RegisterMsgHandler(const std::shared_ptr<MsgHandlerCallbackInterface> & msgHandler)1555 int32_t InputMethodController::RegisterMsgHandler(const std::shared_ptr<MsgHandlerCallbackInterface> &msgHandler)
1556 {
1557     IMSA_HILOGI("isRegist: %{public}d", msgHandler != nullptr);
1558     std::shared_ptr<MsgHandlerCallbackInterface> exMsgHandler = nullptr;
1559     {
1560         std::lock_guard<decltype(msgHandlerMutex_)> lock(msgHandlerMutex_);
1561         exMsgHandler = msgHandler_;
1562         msgHandler_ = msgHandler;
1563     }
1564     if (exMsgHandler != nullptr) {
1565         IMSA_HILOGI("Trigger exMessageHandler OnTerminated.");
1566         exMsgHandler->OnTerminated();
1567     }
1568     return ErrorCode::NO_ERROR;
1569 }
1570 
GetMsgHandlerCallback()1571 std::shared_ptr<MsgHandlerCallbackInterface> InputMethodController::GetMsgHandlerCallback()
1572 {
1573     std::lock_guard<decltype(msgHandlerMutex_)> lock(msgHandlerMutex_);
1574     return msgHandler_;
1575 }
1576 
GetInputMethodState(EnabledStatus & state)1577 int32_t InputMethodController::GetInputMethodState(EnabledStatus &state)
1578 {
1579     auto proxy = GetSystemAbilityProxy();
1580     if (proxy == nullptr) {
1581         IMSA_HILOGE("proxy is nullptr!");
1582         return ErrorCode::ERROR_NULL_POINTER;
1583     }
1584     return proxy->GetInputMethodState(state);
1585 }
1586 
SetPreviewText(const std::string & text,const Range & range)1587 int32_t InputMethodController::SetPreviewText(const std::string &text, const Range &range)
1588 {
1589     auto ret = SetPreviewTextInner(text, range);
1590     ReportBaseTextOperation(IInputDataChannel::SET_PREVIEW_TEXT, ret);
1591     return ret;
1592 }
1593 
ShowTextInput(ClientType type)1594 int32_t InputMethodController::ShowTextInput(ClientType type)
1595 {
1596     AttachOptions attachOptions;
1597     return ShowTextInput(attachOptions, type);
1598 }
1599 
ShowTextInput(const AttachOptions & attachOptions,ClientType type)1600 int32_t InputMethodController::ShowTextInput(const AttachOptions &attachOptions, ClientType type)
1601 {
1602     auto ret = ShowTextInputInner(attachOptions, type);
1603     ReportClientShow(static_cast<int32_t>(InputMethodInterfaceCode::SHOW_INPUT), ret, type);
1604     return ret;
1605 }
1606 
ShowSoftKeyboard(ClientType type)1607 int32_t InputMethodController::ShowSoftKeyboard(ClientType type)
1608 {
1609     auto ret = ShowSoftKeyboardInner(type);
1610     ReportClientShow(static_cast<int32_t>(InputMethodInterfaceCode::SHOW_CURRENT_INPUT), ret, type);
1611     return ret;
1612 }
1613 
ReportClientShow(int32_t eventCode,int32_t errCode,ClientType type)1614 void InputMethodController::ReportClientShow(int32_t eventCode, int32_t errCode, ClientType type)
1615 {
1616     auto evenInfo =
1617         HiSysOriginalInfo::Builder().SetClientType(type).SetEventCode(eventCode).SetErrCode(errCode).Build();
1618     ImcHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::CLIENT_SHOW, *evenInfo);
1619 }
1620 
ReportBaseTextOperation(int32_t eventCode,int32_t errCode)1621 void InputMethodController::ReportBaseTextOperation(int32_t eventCode, int32_t errCode)
1622 {
1623     auto imeInfo = GetBindImeInfo();
1624     auto evenInfo = HiSysOriginalInfo::Builder()
1625                         .SetEventCode(eventCode)
1626                         .SetErrCode(errCode)
1627                         .SetPeerName(imeInfo.second)
1628                         .SetPeerPid(imeInfo.first)
1629                         .SetClientType(clientInfo_.type)
1630                         .Build();
1631     ImcHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::BASE_TEXT_OPERATOR, *evenInfo);
1632 }
1633 
UpdateTextPreviewState(bool isSupport)1634 void InputMethodController::UpdateTextPreviewState(bool isSupport)
1635 {
1636     if (textConfig_.inputAttribute.isTextPreviewSupported == isSupport) {
1637         return;
1638     }
1639     textConfig_.inputAttribute.isTextPreviewSupported = isSupport;
1640     auto agent = GetAgent();
1641     if (agent == nullptr) {
1642         IMSA_HILOGE("agent is nullptr!");
1643         return;
1644     }
1645     agent->OnAttributeChange(textConfig_.inputAttribute);
1646 }
1647 } // namespace MiscServices
1648 } // namespace OHOS
1649