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