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