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 "input_client_stub.h"
24 #include "input_data_channel_stub.h"
25 #include "input_method_agent_proxy.h"
26 #include "input_method_property.h"
27 #include "input_method_status.h"
28 #include "input_method_system_ability_proxy.h"
29 #include "inputmethod_sysevent.h"
30 #include "inputmethod_trace.h"
31 #include "iservice_registry.h"
32 #include "keyevent_consumer_stub.h"
33 #include "string_ex.h"
34 #include "sys/prctl.h"
35 #include "system_ability_definition.h"
36
37 namespace OHOS {
38 namespace MiscServices {
39 using namespace MessageID;
40 using namespace std::chrono;
41 sptr<InputMethodController> InputMethodController::instance_;
42 std::shared_ptr<AppExecFwk::EventHandler> InputMethodController::handler_{ nullptr };
43 std::mutex InputMethodController::instanceLock_;
44 constexpr int32_t LOOP_COUNT = 5;
45 constexpr int64_t DELAY_TIME = 100;
46 constexpr int32_t ACE_DEAL_TIME_OUT = 200;
47 const std::unordered_map<std::string, EventType> EVENT_TYPE{ { "imeChange", IME_CHANGE }, { "imeShow", IME_SHOW },
48 { "imeHide", IME_HIDE } };
InputMethodController()49 InputMethodController::InputMethodController()
50 {
51 IMSA_HILOGD("IMC structure");
52 }
53
~InputMethodController()54 InputMethodController::~InputMethodController()
55 {
56 }
57
GetInstance()58 sptr<InputMethodController> InputMethodController::GetInstance()
59 {
60 if (instance_ == nullptr) {
61 std::lock_guard<std::mutex> autoLock(instanceLock_);
62 if (instance_ == nullptr) {
63 IMSA_HILOGD("IMC instance_ is nullptr");
64 instance_ = new (std::nothrow) InputMethodController();
65 if (instance_ == nullptr) {
66 IMSA_HILOGE("failed to create InputMethodController");
67 return instance_;
68 }
69 int32_t ret = instance_->Initialize();
70 if (ret != ErrorCode::NO_ERROR) {
71 InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, "", "IMC initialize failed!");
72 }
73 }
74 }
75 return instance_;
76 }
77
SetSettingListener(std::shared_ptr<InputMethodSettingListener> listener)78 void InputMethodController::SetSettingListener(std::shared_ptr<InputMethodSettingListener> listener)
79 {
80 settingListener_ = std::move(listener);
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 return proxy->UpdateListenEventFlag(clientInfo_, IME_NONE);
91 }
92
UpdateListenEventFlag(const std::string & type,bool isOn)93 int32_t InputMethodController::UpdateListenEventFlag(const std::string &type, bool isOn)
94 {
95 auto it = EVENT_TYPE.find(type);
96 if (it == EVENT_TYPE.end()) {
97 return ErrorCode::ERROR_BAD_PARAMETERS;
98 }
99 auto eventType = it->second;
100 auto proxy = GetSystemAbilityProxy();
101 if (proxy == nullptr) {
102 IMSA_HILOGE("proxy is nullptr");
103 return ErrorCode::ERROR_SERVICE_START_FAILED;
104 }
105 std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
106 auto oldEventFlag = clientInfo_.eventFlag;
107 UpdateNativeEventFlag(eventType, isOn);
108 auto ret = proxy->UpdateListenEventFlag(clientInfo_, eventType);
109 if (ret != ErrorCode::NO_ERROR && isOn) {
110 clientInfo_.eventFlag = oldEventFlag;
111 }
112 return ret;
113 }
114
UpdateNativeEventFlag(EventType eventType,bool isOn)115 void InputMethodController::UpdateNativeEventFlag(EventType eventType, bool isOn)
116 {
117 uint32_t currentEvent = isOn ? 1u << eventType : ~(1u << eventType);
118 clientInfo_.eventFlag = isOn ? clientInfo_.eventFlag | currentEvent : clientInfo_.eventFlag & currentEvent;
119 }
120
SetControllerListener(std::shared_ptr<ControllerListener> controllerListener)121 void InputMethodController::SetControllerListener(std::shared_ptr<ControllerListener> controllerListener)
122 {
123 IMSA_HILOGD("InputMethodController run in");
124 controllerListener_ = std::move(controllerListener);
125 }
126
Initialize()127 int32_t InputMethodController::Initialize()
128 {
129 auto client = new (std::nothrow) InputClientStub();
130 if (client == nullptr) {
131 IMSA_HILOGE("failed to new client");
132 return ErrorCode::ERROR_NULL_POINTER;
133 }
134 auto channel = new (std::nothrow) InputDataChannelStub();
135 if (channel == nullptr) {
136 delete client;
137 IMSA_HILOGE("failed to new channel");
138 return ErrorCode::ERROR_NULL_POINTER;
139 }
140 InputAttribute attribute = { .inputPattern = InputAttribute::PATTERN_TEXT };
141 clientInfo_ = { .attribute = attribute, .client = client, .channel = channel };
142
143 // make AppExecFwk::EventHandler handler
144 handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
145 return ErrorCode::NO_ERROR;
146 }
147
GetSystemAbilityProxy()148 sptr<IInputMethodSystemAbility> InputMethodController::GetSystemAbilityProxy()
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 sptr<ISystemAbilityManager> systemAbilityManager =
156 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
157 if (systemAbilityManager == nullptr) {
158 IMSA_HILOGE("system ability manager is nullptr");
159 return nullptr;
160 }
161 auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, "");
162 if (systemAbility == nullptr) {
163 IMSA_HILOGE("system ability is nullptr");
164 return nullptr;
165 }
166 if (deathRecipient_ == nullptr) {
167 deathRecipient_ = new (std::nothrow) InputDeathRecipient();
168 if (deathRecipient_ == nullptr) {
169 IMSA_HILOGE("new death recipient failed");
170 return nullptr;
171 }
172 }
173 deathRecipient_->SetDeathRecipient([this](const wptr<IRemoteObject> &remote) { OnRemoteSaDied(remote); });
174 if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) {
175 IMSA_HILOGE("failed to add death recipient.");
176 return nullptr;
177 }
178 abilityManager_ = iface_cast<IInputMethodSystemAbility>(systemAbility);
179 return abilityManager_;
180 }
181
OnSwitchInput(const Property & property,const SubProperty & subProperty)182 int32_t InputMethodController::OnSwitchInput(const Property &property, const SubProperty &subProperty)
183 {
184 if (settingListener_ == nullptr) {
185 IMSA_HILOGE("imeListener_ is nullptr");
186 return ErrorCode::ERROR_NULL_POINTER;
187 }
188 settingListener_->OnImeChange(property, subProperty);
189 return ErrorCode::NO_ERROR;
190 }
191
OnPanelStatusChange(const InputWindowStatus & status,const std::vector<InputWindowInfo> & windowInfo)192 int32_t InputMethodController::OnPanelStatusChange(
193 const InputWindowStatus &status, const std::vector<InputWindowInfo> &windowInfo)
194 {
195 if (settingListener_ == nullptr) {
196 IMSA_HILOGE("imeListener_ is nullptr");
197 return ErrorCode::ERROR_NULL_POINTER;
198 }
199 settingListener_->OnPanelStatusChange(status, windowInfo);
200 return ErrorCode::NO_ERROR;
201 }
202
DeactivateClient()203 void InputMethodController::DeactivateClient()
204 {
205 {
206 std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
207 clientInfo_.state = ClientState::INACTIVE;
208 }
209 {
210 std::lock_guard<std::mutex> autoLock(agentLock_);
211 agent_ = nullptr;
212 agentObject_ = nullptr;
213 }
214 auto listener = GetTextListener();
215 if (listener != nullptr) {
216 IMSA_HILOGD("textListener_ is not nullptr");
217 listener->SendKeyboardStatus(KeyboardStatus::NONE);
218 }
219 }
220
SaveTextConfig(const TextConfig & textConfig)221 void InputMethodController::SaveTextConfig(const TextConfig &textConfig)
222 {
223 std::lock_guard<std::mutex> lock(textConfigLock_);
224 IMSA_HILOGD("inputPattern: %{public}d, enterKeyType: %{public}d, windowId: %{public}d",
225 textConfig.inputAttribute.inputPattern, textConfig.inputAttribute.enterKeyType, textConfig.windowId);
226 textConfig_ = textConfig;
227 }
228
Attach(sptr<OnTextChangedListener> & listener)229 int32_t InputMethodController::Attach(sptr<OnTextChangedListener> &listener)
230 {
231 return Attach(listener, true);
232 }
233
Attach(sptr<OnTextChangedListener> & listener,bool isShowKeyboard)234 int32_t InputMethodController::Attach(sptr<OnTextChangedListener> &listener, bool isShowKeyboard)
235 {
236 InputAttribute attribute;
237 attribute.inputPattern = InputAttribute::PATTERN_TEXT;
238 return Attach(listener, isShowKeyboard, attribute);
239 }
240
Attach(sptr<OnTextChangedListener> & listener,bool isShowKeyboard,const InputAttribute & attribute)241 int32_t InputMethodController::Attach(
242 sptr<OnTextChangedListener> &listener, bool isShowKeyboard, const InputAttribute &attribute)
243 {
244 InputMethodSyncTrace tracer("InputMethodController Attach trace.");
245 TextConfig textConfig;
246 textConfig.inputAttribute = attribute;
247 return Attach(listener, isShowKeyboard, textConfig);
248 }
249
Attach(sptr<OnTextChangedListener> & listener,bool isShowKeyboard,const TextConfig & textConfig)250 int32_t InputMethodController::Attach(
251 sptr<OnTextChangedListener> &listener, bool isShowKeyboard, const TextConfig &textConfig)
252 {
253 IMSA_HILOGI("isShowKeyboard %{public}d", isShowKeyboard);
254 ClearEditorCache();
255 InputMethodSyncTrace tracer("InputMethodController Attach with textConfig trace.");
256 clientInfo_.isNotifyInputStart = GetTextListener() != listener;
257 SetTextListener(listener);
258 clientInfo_.isShowKeyboard = isShowKeyboard;
259 SaveTextConfig(textConfig);
260 GetTextConfig(clientInfo_.config);
261
262 sptr<IRemoteObject> agent = nullptr;
263 int32_t ret = StartInput(clientInfo_, agent);
264 if (ret != ErrorCode::NO_ERROR) {
265 IMSA_HILOGE("failed to start input, ret:%{public}d", ret);
266 return ret;
267 }
268 clientInfo_.state = ClientState::ACTIVE;
269 OnInputReady(agent);
270 if (isShowKeyboard) {
271 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_ATTACH);
272 }
273 IMSA_HILOGI("bind imf successfully");
274 return ErrorCode::NO_ERROR;
275 }
276
ShowTextInput()277 int32_t InputMethodController::ShowTextInput()
278 {
279 if (!IsBound()) {
280 IMSA_HILOGE("not bound");
281 return ErrorCode::ERROR_CLIENT_NOT_BOUND;
282 }
283 IMSA_HILOGI("run in");
284 clientInfo_.isShowKeyboard = true;
285 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_ENEDITABLE);
286 int32_t ret = ShowInput(clientInfo_.client);
287 if (ret != ErrorCode::NO_ERROR) {
288 IMSA_HILOGE("failed to start input, ret: %{public}d", ret);
289 return ret;
290 }
291 isEditable_.store(true);
292 IMSA_HILOGI("enter editable state");
293 return ret;
294 }
295
HideTextInput()296 int32_t InputMethodController::HideTextInput()
297 {
298 if (!IsBound()) {
299 IMSA_HILOGE("not bound");
300 return ErrorCode::ERROR_CLIENT_NOT_BOUND;
301 }
302 IMSA_HILOGI("run in");
303 isEditable_.store(false);
304 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNEDITABLE);
305 return HideInput(clientInfo_.client);
306 }
307
HideCurrentInput()308 int32_t InputMethodController::HideCurrentInput()
309 {
310 IMSA_HILOGD("InputMethodController::HideCurrentInput");
311 if (!IsEditable()) {
312 IMSA_HILOGD("not editable");
313 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
314 }
315 auto proxy = GetSystemAbilityProxy();
316 if (proxy == nullptr) {
317 IMSA_HILOGE("proxy is nullptr");
318 return ErrorCode::ERROR_EX_NULL_POINTER;
319 }
320 clientInfo_.isShowKeyboard = false;
321 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_NORMAL);
322 return proxy->HideCurrentInputDeprecated();
323 }
324
ShowCurrentInput()325 int32_t InputMethodController::ShowCurrentInput()
326 {
327 if (!IsEditable()) {
328 IMSA_HILOGD("not editable");
329 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
330 }
331 auto proxy = GetSystemAbilityProxy();
332 if (proxy == nullptr) {
333 IMSA_HILOGE("proxy is nullptr");
334 return ErrorCode::ERROR_EX_NULL_POINTER;
335 }
336 IMSA_HILOGI("run in");
337 clientInfo_.isShowKeyboard = true;
338 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_NORMAL);
339 return proxy->ShowCurrentInputDeprecated();
340 }
341
Close()342 int32_t InputMethodController::Close()
343 {
344 IMSA_HILOGI("run in");
345 bool isReportHide = clientInfo_.isShowKeyboard;
346 InputMethodSyncTrace tracer("InputMethodController Close trace.");
347 isReportHide ? InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNBIND)
348 : InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_UNBIND);
349 return ReleaseInput(clientInfo_.client);
350 }
351
RequestShowInput()352 int32_t InputMethodController::RequestShowInput()
353 {
354 auto proxy = GetSystemAbilityProxy();
355 if (proxy == nullptr) {
356 IMSA_HILOGE("proxy is nullptr");
357 return ErrorCode::ERROR_EX_NULL_POINTER;
358 }
359 IMSA_HILOGI("InputMethodController, run in");
360 return proxy->RequestShowInput();
361 }
362
RequestHideInput()363 int32_t InputMethodController::RequestHideInput()
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("InputMethodController, run in");
371 return proxy->RequestHideInput();
372 }
373
DisplayOptionalInputMethod()374 int32_t InputMethodController::DisplayOptionalInputMethod()
375 {
376 IMSA_HILOGD("InputMethodController::DisplayOptionalInputMethod");
377 auto proxy = GetSystemAbilityProxy();
378 if (proxy == nullptr) {
379 IMSA_HILOGE("proxy is nullptr");
380 return ErrorCode::ERROR_EX_NULL_POINTER;
381 }
382 return proxy->DisplayOptionalInputMethod();
383 }
384
WasAttached()385 bool InputMethodController::WasAttached()
386 {
387 return isBound_.load();
388 }
389
ListInputMethodCommon(InputMethodStatus status,std::vector<Property> & props)390 int32_t InputMethodController::ListInputMethodCommon(InputMethodStatus status, std::vector<Property> &props)
391 {
392 IMSA_HILOGD("InputMethodController::ListInputMethodCommon");
393 auto proxy = GetSystemAbilityProxy();
394 if (proxy == nullptr) {
395 IMSA_HILOGE("proxy is nullptr");
396 return ErrorCode::ERROR_EX_NULL_POINTER;
397 }
398 return proxy->ListInputMethod(status, props);
399 }
400
ListInputMethod(std::vector<Property> & props)401 int32_t InputMethodController::ListInputMethod(std::vector<Property> &props)
402 {
403 IMSA_HILOGD("InputMethodController::listInputMethod");
404 return ListInputMethodCommon(ALL, props);
405 }
406
ListInputMethod(bool enable,std::vector<Property> & props)407 int32_t InputMethodController::ListInputMethod(bool enable, std::vector<Property> &props)
408 {
409 IMSA_HILOGI("enable = %{public}s", enable ? "ENABLE" : "DISABLE");
410 return ListInputMethodCommon(enable ? ENABLE : DISABLE, props);
411 }
412
GetDefaultInputMethod(std::shared_ptr<Property> & property)413 int32_t InputMethodController::GetDefaultInputMethod(std::shared_ptr<Property> &property)
414 {
415 IMSA_HILOGD("InputMethodController::GetDefaultInputMethod");
416 auto proxy = GetSystemAbilityProxy();
417 if (proxy == nullptr) {
418 IMSA_HILOGE("proxy is nullptr");
419 return ErrorCode::ERROR_SERVICE_START_FAILED;
420 }
421 return proxy->GetDefaultInputMethod(property);
422 }
423
GetInputMethodConfig(OHOS::AppExecFwk::ElementName & inputMethodConfig)424 int32_t InputMethodController::GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig)
425 {
426 IMSA_HILOGD("InputMethodController::inputMethodConfig");
427 auto proxy = GetSystemAbilityProxy();
428 if (proxy == nullptr) {
429 IMSA_HILOGE("proxy is nullptr");
430 return ErrorCode::ERROR_SERVICE_START_FAILED;
431 }
432 return proxy->GetInputMethodConfig(inputMethodConfig);
433 }
434
GetCurrentInputMethod()435 std::shared_ptr<Property> InputMethodController::GetCurrentInputMethod()
436 {
437 IMSA_HILOGD("InputMethodController::GetCurrentInputMethod");
438 auto proxy = GetSystemAbilityProxy();
439 if (proxy == nullptr) {
440 IMSA_HILOGE("proxy is nullptr");
441 return nullptr;
442 }
443 auto property = proxy->GetCurrentInputMethod();
444 if (property == nullptr) {
445 IMSA_HILOGE("property is nullptr");
446 return nullptr;
447 }
448 return property;
449 }
450
GetCurrentInputMethodSubtype()451 std::shared_ptr<SubProperty> InputMethodController::GetCurrentInputMethodSubtype()
452 {
453 IMSA_HILOGD("InputMethodController::GetCurrentInputMethod");
454 auto proxy = GetSystemAbilityProxy();
455 if (proxy == nullptr) {
456 IMSA_HILOGE("proxy is nullptr");
457 return nullptr;
458 }
459 auto property = proxy->GetCurrentInputMethodSubtype();
460 if (property == nullptr) {
461 IMSA_HILOGE("property is nullptr");
462 return nullptr;
463 }
464 return property;
465 }
466
StartInput(InputClientInfo & inputClientInfo,sptr<IRemoteObject> & agent)467 int32_t InputMethodController::StartInput(InputClientInfo &inputClientInfo, sptr<IRemoteObject> &agent)
468 {
469 IMSA_HILOGD("InputMethodController::StartInput");
470 auto proxy = GetSystemAbilityProxy();
471 if (proxy == nullptr) {
472 IMSA_HILOGE("proxy is nullptr");
473 return ErrorCode::ERROR_SERVICE_START_FAILED;
474 }
475 return proxy->StartInput(inputClientInfo, agent);
476 }
477
ReleaseInput(sptr<IInputClient> & client)478 int32_t InputMethodController::ReleaseInput(sptr<IInputClient> &client)
479 {
480 IMSA_HILOGD("InputMethodController::ReleaseInput");
481 auto proxy = GetSystemAbilityProxy();
482 if (proxy == nullptr) {
483 IMSA_HILOGE("proxy is nullptr");
484 return ErrorCode::ERROR_SERVICE_START_FAILED;
485 }
486 int32_t ret = proxy->ReleaseInput(client);
487 if (ret == ErrorCode::NO_ERROR) {
488 OnInputStop();
489 }
490 return ret;
491 }
492
ShowInput(sptr<IInputClient> & client)493 int32_t InputMethodController::ShowInput(sptr<IInputClient> &client)
494 {
495 IMSA_HILOGD("InputMethodController::ShowInput");
496 auto proxy = GetSystemAbilityProxy();
497 if (proxy == nullptr) {
498 IMSA_HILOGE("proxy is nullptr");
499 return ErrorCode::ERROR_SERVICE_START_FAILED;
500 }
501 return proxy->ShowInput(client);
502 }
503
HideInput(sptr<IInputClient> & client)504 int32_t InputMethodController::HideInput(sptr<IInputClient> &client)
505 {
506 IMSA_HILOGD("InputMethodController::HideInput");
507 auto proxy = GetSystemAbilityProxy();
508 if (proxy == nullptr) {
509 IMSA_HILOGE("proxy is nullptr");
510 return ErrorCode::ERROR_SERVICE_START_FAILED;
511 }
512 return proxy->HideInput(client);
513 }
514
OnRemoteSaDied(const wptr<IRemoteObject> & remote)515 void InputMethodController::OnRemoteSaDied(const wptr<IRemoteObject> &remote)
516 {
517 IMSA_HILOGI("input method service death");
518 {
519 std::lock_guard<std::mutex> lock(abilityLock_);
520 abilityManager_ = nullptr;
521 }
522 if (handler_ == nullptr) {
523 IMSA_HILOGE("handler_ is nullptr");
524 return;
525 }
526 RestoreListenInfoInSaDied();
527 RestoreAttachInfoInSaDied();
528 }
529
RestoreListenInfoInSaDied()530 void InputMethodController::RestoreListenInfoInSaDied()
531 {
532 {
533 std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
534 if (clientInfo_.eventFlag == EventStatusManager::NO_EVENT_ON) {
535 return;
536 }
537 }
538 isDiedRestoreListen_.store(false);
539 auto restoreListenTask = [=]() {
540 if (isDiedRestoreListen_.load()) {
541 return;
542 }
543 auto ret = RestoreListenEventFlag();
544 if (ret == ErrorCode::NO_ERROR) {
545 isDiedRestoreListen_.store(true);
546 IMSA_HILOGI("Try to RestoreListen success.");
547 }
548 };
549 for (int i = 0; i < LOOP_COUNT; i++) {
550 handler_->PostTask(restoreListenTask, "OnRemoteSaDied", DELAY_TIME * (i + 1));
551 }
552 }
553
RestoreAttachInfoInSaDied()554 void InputMethodController::RestoreAttachInfoInSaDied()
555 {
556 if (!IsEditable()) {
557 IMSA_HILOGD("not editable");
558 return;
559 }
560 auto attach = [=]() -> bool {
561 TextConfig tempConfig{};
562 {
563 std::lock_guard<std::mutex> lock(textConfigLock_);
564 tempConfig = textConfig_;
565 tempConfig.cursorInfo = cursorInfo_;
566 tempConfig.range.start = selectNewBegin_;
567 tempConfig.range.end = selectNewEnd_;
568 }
569 auto listener = GetTextListener();
570 auto errCode = Attach(listener, clientInfo_.isShowKeyboard, tempConfig);
571 IMSA_HILOGI("attach end, errCode = %{public}d", errCode);
572 return errCode == ErrorCode::NO_ERROR;
573 };
574 if (attach()) {
575 return;
576 }
577 isDiedAttached_.store(false);
578 auto attachTask = [this, attach]() {
579 if (isDiedAttached_.load()) {
580 return;
581 }
582 attach();
583 };
584 for (int i = 0; i < LOOP_COUNT; i++) {
585 handler_->PostTask(attachTask, "OnRemoteSaDied", DELAY_TIME * (i + 1));
586 }
587 }
588
OnCursorUpdate(CursorInfo cursorInfo)589 int32_t InputMethodController::OnCursorUpdate(CursorInfo cursorInfo)
590 {
591 if (!IsBound()) {
592 IMSA_HILOGD("not bound");
593 return ErrorCode::ERROR_CLIENT_NOT_BOUND;
594 }
595 if (!IsEditable()) {
596 IMSA_HILOGD("not editable");
597 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
598 }
599 {
600 std::lock_guard<std::mutex> lock(textConfigLock_);
601 textConfig_.cursorInfo = cursorInfo;
602 }
603 {
604 std::lock_guard<std::mutex> lk(cursorInfoMutex_);
605 if (cursorInfo_ == cursorInfo) {
606 IMSA_HILOGD("same to last update");
607 return ErrorCode::NO_ERROR;
608 }
609 cursorInfo_ = cursorInfo;
610 }
611 auto agent = GetAgent();
612 if (agent == nullptr) {
613 IMSA_HILOGE("agent is nullptr");
614 return ErrorCode::ERROR_SERVICE_START_FAILED;
615 }
616 IMSA_HILOGI("left: %{public}d, top: %{public}d, height: %{public}d", static_cast<int32_t>(cursorInfo.left),
617 static_cast<int32_t>(cursorInfo.top), static_cast<int32_t>(cursorInfo.height));
618 agent->OnCursorUpdate(cursorInfo.left, cursorInfo.top, cursorInfo.height);
619 return ErrorCode::NO_ERROR;
620 }
621
OnSelectionChange(std::u16string text,int start,int end)622 int32_t InputMethodController::OnSelectionChange(std::u16string text, int start, int end)
623 {
624 if (!IsBound()) {
625 IMSA_HILOGD("not bound");
626 return ErrorCode::ERROR_CLIENT_NOT_BOUND;
627 }
628 if (!IsEditable()) {
629 IMSA_HILOGD("not editable");
630 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
631 }
632 {
633 std::lock_guard<std::mutex> lock(textConfigLock_);
634 textConfig_.range = { start, end };
635 }
636 if (textString_ == text && selectNewBegin_ == start && selectNewEnd_ == end) {
637 IMSA_HILOGD("same to last update");
638 return ErrorCode::NO_ERROR;
639 }
640 textString_ = text;
641 selectOldBegin_ = selectNewBegin_;
642 selectOldEnd_ = selectNewEnd_;
643 selectNewBegin_ = start;
644 selectNewEnd_ = end;
645 auto agent = GetAgent();
646 if (agent == nullptr) {
647 IMSA_HILOGE("agent is nullptr");
648 return ErrorCode::ERROR_SERVICE_START_FAILED;
649 }
650 IMSA_HILOGI("IMC size: %{public}zu, range: %{public}d/%{public}d", text.size(), start, end);
651 agent->OnSelectionChange(textString_, selectOldBegin_, selectOldEnd_, selectNewBegin_, selectNewEnd_);
652 return ErrorCode::NO_ERROR;
653 }
654
OnConfigurationChange(Configuration info)655 int32_t InputMethodController::OnConfigurationChange(Configuration info)
656 {
657 if (!IsBound()) {
658 IMSA_HILOGD("not bound");
659 return ErrorCode::ERROR_CLIENT_NOT_BOUND;
660 }
661 {
662 std::lock_guard<std::mutex> lock(textConfigLock_);
663 textConfig_.inputAttribute.enterKeyType = static_cast<int32_t>(info.GetEnterKeyType());
664 textConfig_.inputAttribute.inputPattern = static_cast<int32_t>(info.GetTextInputType());
665 }
666 if (!IsEditable()) {
667 IMSA_HILOGD("not editable");
668 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
669 }
670 IMSA_HILOGI("IMC enterKeyType: %{public}d, textInputType: %{public}d", textConfig_.inputAttribute.enterKeyType,
671 textConfig_.inputAttribute.inputPattern);
672 auto agent = GetAgent();
673 if (agent == nullptr) {
674 IMSA_HILOGE("agent is nullptr");
675 return ErrorCode::ERROR_SERVICE_START_FAILED;
676 }
677 agent->OnConfigurationChange(info);
678 return ErrorCode::NO_ERROR;
679 }
680
GetLeft(int32_t length,std::u16string & text)681 int32_t InputMethodController::GetLeft(int32_t length, std::u16string &text)
682 {
683 InputMethodSyncTrace tracer("IMC_GetForward");
684 IMSA_HILOGD("run in, length: %{public}d", length);
685 auto listener = GetTextListener();
686 if (!IsEditable() || listener == nullptr) {
687 IMSA_HILOGE("not editable or listener is nullptr");
688 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
689 }
690 int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
691 {
692 InputMethodSyncTrace aceTracer("ACE_GetForward");
693 text = listener->GetLeftTextOfCursor(length);
694 }
695 PrintLogIfAceTimeout(start);
696 return ErrorCode::NO_ERROR;
697 }
698
GetRight(int32_t length,std::u16string & text)699 int32_t InputMethodController::GetRight(int32_t length, std::u16string &text)
700 {
701 IMSA_HILOGD("run in, length: %{public}d", length);
702 auto listener = GetTextListener();
703 if (!IsEditable() || listener == nullptr) {
704 IMSA_HILOGE("not editable or textListener_ is nullptr");
705 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
706 }
707 text = listener->GetRightTextOfCursor(length);
708 return ErrorCode::NO_ERROR;
709 }
710
GetTextIndexAtCursor(int32_t & index)711 int32_t InputMethodController::GetTextIndexAtCursor(int32_t &index)
712 {
713 IMSA_HILOGD("run in");
714 auto listener = GetTextListener();
715 if (!IsEditable() || listener == nullptr) {
716 IMSA_HILOGE("not editable or textListener_ is nullptr");
717 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
718 }
719 index = listener->GetTextIndexAtCursor();
720 return ErrorCode::NO_ERROR;
721 }
722
DispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent,KeyEventCallback callback)723 int32_t InputMethodController::DispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent, KeyEventCallback callback)
724 {
725 auto ret = DispatchKeyEventInner(keyEvent, callback);
726 if (ret != ErrorCode::NO_ERROR && callback != nullptr) {
727 IMSA_HILOGE("DispatchKeyEventInner error");
728 callback(keyEvent, false);
729 }
730 return ret;
731 }
732
DispatchKeyEventInner(std::shared_ptr<MMI::KeyEvent> & keyEvent,KeyEventCallback & callback)733 int32_t InputMethodController::DispatchKeyEventInner(
734 std::shared_ptr<MMI::KeyEvent> &keyEvent, KeyEventCallback &callback)
735 {
736 KeyEventInfo keyEventInfo = { std::chrono::system_clock::now(), keyEvent };
737 keyEventQueue_.Push(keyEventInfo);
738 InputMethodSyncTrace tracer("DispatchKeyEvent trace");
739 keyEventQueue_.Wait(keyEventInfo);
740 if (!IsEditable()) {
741 IMSA_HILOGD("not editable");
742 keyEventQueue_.Pop();
743 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
744 }
745 if (keyEvent == nullptr) {
746 IMSA_HILOGE("keyEvent is nullptr");
747 keyEventQueue_.Pop();
748 return ErrorCode::ERROR_EX_NULL_POINTER;
749 }
750 auto agent = GetAgent();
751 if (agent == nullptr) {
752 IMSA_HILOGE("agent is nullptr");
753 keyEventQueue_.Pop();
754 return ErrorCode::ERROR_SERVICE_START_FAILED;
755 }
756 IMSA_HILOGI("start");
757 sptr<IKeyEventConsumer> consumer = new (std::nothrow) KeyEventConsumerStub(callback, keyEvent);
758 if (consumer == nullptr) {
759 IMSA_HILOGE("keyEvent is nullptr");
760 keyEventQueue_.Pop();
761 return ErrorCode::ERROR_EX_NULL_POINTER;
762 }
763 auto ret = agent->DispatchKeyEvent(keyEvent, consumer);
764 if (ret != ErrorCode::NO_ERROR) {
765 IMSA_HILOGE("DispatchKeyEvent failed");
766 }
767 keyEventQueue_.Pop();
768 return ret;
769 }
770
GetEnterKeyType(int32_t & keyType)771 int32_t InputMethodController::GetEnterKeyType(int32_t &keyType)
772 {
773 IMSA_HILOGD("InputMethodController::GetEnterKeyType");
774 std::lock_guard<std::mutex> lock(textConfigLock_);
775 keyType = textConfig_.inputAttribute.enterKeyType;
776 return ErrorCode::NO_ERROR;
777 }
778
GetInputPattern(int32_t & inputpattern)779 int32_t InputMethodController::GetInputPattern(int32_t &inputpattern)
780 {
781 IMSA_HILOGD("InputMethodController::GetInputPattern");
782 std::lock_guard<std::mutex> lock(textConfigLock_);
783 inputpattern = textConfig_.inputAttribute.inputPattern;
784 return ErrorCode::NO_ERROR;
785 }
786
GetTextConfig(TextTotalConfig & config)787 int32_t InputMethodController::GetTextConfig(TextTotalConfig &config)
788 {
789 IMSA_HILOGD("InputMethodController run in.");
790 std::lock_guard<std::mutex> lock(textConfigLock_);
791 config.inputAttribute = textConfig_.inputAttribute;
792 config.cursorInfo = textConfig_.cursorInfo;
793 config.windowId = textConfig_.windowId;
794 config.positionY = textConfig_.positionY;
795 config.height = textConfig_.height;
796
797 if (textConfig_.range.start == INVALID_VALUE) {
798 IMSA_HILOGD("no valid SelectionRange param.");
799 return ErrorCode::NO_ERROR;
800 }
801 {
802 std::lock_guard<std::mutex> editorLock(editorContentLock_);
803 config.textSelection.oldBegin = selectOldBegin_;
804 config.textSelection.oldEnd = selectOldEnd_;
805 }
806 config.textSelection.newBegin = textConfig_.range.start;
807 config.textSelection.newEnd = textConfig_.range.end;
808
809 return ErrorCode::NO_ERROR;
810 }
811
SetCallingWindow(uint32_t windowId)812 int32_t InputMethodController::SetCallingWindow(uint32_t windowId)
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_.windowId = windowId;
825 }
826 auto agent = GetAgent();
827 if (agent == nullptr) {
828 IMSA_HILOGE("agent_ is nullptr");
829 return ErrorCode::ERROR_SERVICE_START_FAILED;
830 }
831 IMSA_HILOGI("windowId = %{public}d", windowId);
832 agent->SetCallingWindow(windowId);
833 return ErrorCode::NO_ERROR;
834 }
835
ShowSoftKeyboard()836 int32_t InputMethodController::ShowSoftKeyboard()
837 {
838 auto proxy = GetSystemAbilityProxy();
839 if (proxy == nullptr) {
840 IMSA_HILOGE("proxy is nullptr");
841 return ErrorCode::ERROR_EX_NULL_POINTER;
842 }
843 IMSA_HILOGI("start");
844 clientInfo_.isShowKeyboard = true;
845 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_NORMAL);
846 return proxy->ShowCurrentInput();
847 }
848
HideSoftKeyboard()849 int32_t InputMethodController::HideSoftKeyboard()
850 {
851 auto proxy = GetSystemAbilityProxy();
852 if (proxy == nullptr) {
853 IMSA_HILOGE("proxy is nullptr");
854 return ErrorCode::ERROR_EX_NULL_POINTER;
855 }
856 IMSA_HILOGI("start");
857 clientInfo_.isShowKeyboard = false;
858 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_NORMAL);
859 return proxy->HideCurrentInput();
860 }
861
StopInputSession()862 int32_t InputMethodController::StopInputSession()
863 {
864 IMSA_HILOGI("run in");
865 isEditable_.store(false);
866 auto proxy = GetSystemAbilityProxy();
867 if (proxy == nullptr) {
868 IMSA_HILOGE("proxy is nullptr");
869 return ErrorCode::ERROR_EX_NULL_POINTER;
870 }
871 return proxy->StopInputSession();
872 }
873
ShowOptionalInputMethod()874 int32_t InputMethodController::ShowOptionalInputMethod()
875 {
876 auto proxy = GetSystemAbilityProxy();
877 if (proxy == nullptr) {
878 IMSA_HILOGE("proxy is nullptr");
879 return ErrorCode::ERROR_EX_NULL_POINTER;
880 }
881 IMSA_HILOGI("IMC run in");
882 return proxy->DisplayOptionalInputMethod();
883 }
884
ListInputMethodSubtype(const Property & property,std::vector<SubProperty> & subProps)885 int32_t InputMethodController::ListInputMethodSubtype(const Property &property, std::vector<SubProperty> &subProps)
886 {
887 auto proxy = GetSystemAbilityProxy();
888 if (proxy == nullptr) {
889 IMSA_HILOGE("proxy is nullptr");
890 return ErrorCode::ERROR_EX_NULL_POINTER;
891 }
892 IMSA_HILOGD("ime bundleName: %{public}s", property.name.c_str());
893 return proxy->ListInputMethodSubtype(property.name, subProps);
894 }
895
ListCurrentInputMethodSubtype(std::vector<SubProperty> & subProps)896 int32_t InputMethodController::ListCurrentInputMethodSubtype(std::vector<SubProperty> &subProps)
897 {
898 auto proxy = GetSystemAbilityProxy();
899 if (proxy == nullptr) {
900 IMSA_HILOGE("proxy is nullptr");
901 return ErrorCode::ERROR_EX_NULL_POINTER;
902 }
903 IMSA_HILOGD("run in");
904 return proxy->ListCurrentInputMethodSubtype(subProps);
905 }
906
SwitchInputMethod(SwitchTrigger trigger,const std::string & name,const std::string & subName)907 int32_t InputMethodController::SwitchInputMethod(
908 SwitchTrigger trigger, const std::string &name, const std::string &subName)
909 {
910 auto proxy = GetSystemAbilityProxy();
911 if (proxy == nullptr) {
912 IMSA_HILOGE("proxy is nullptr");
913 return ErrorCode::ERROR_EX_NULL_POINTER;
914 }
915 IMSA_HILOGI("name: %{public}s, subName: %{public}s, trigger: %{public}d", name.c_str(), subName.c_str(),
916 static_cast<uint32_t>(trigger));
917 return proxy->SwitchInputMethod(name, subName, trigger);
918 }
919
OnInputReady(sptr<IRemoteObject> agentObject)920 void InputMethodController::OnInputReady(sptr<IRemoteObject> agentObject)
921 {
922 IMSA_HILOGI("IMC");
923 isBound_.store(true);
924 isEditable_.store(true);
925 if (agentObject == nullptr) {
926 IMSA_HILOGE("agentObject is nullptr");
927 return;
928 }
929 SetAgent(agentObject);
930 }
931
OnInputStop()932 void InputMethodController::OnInputStop()
933 {
934 {
935 std::lock_guard<std::mutex> autoLock(agentLock_);
936 agent_ = nullptr;
937 agentObject_ = nullptr;
938 }
939 auto listener = GetTextListener();
940 if (listener != nullptr) {
941 IMSA_HILOGD("textListener_ is not nullptr");
942 listener->SendKeyboardStatus(KeyboardStatus::HIDE);
943 }
944 isBound_.store(false);
945 isEditable_.store(false);
946 }
947
ClearEditorCache()948 void InputMethodController::ClearEditorCache()
949 {
950 IMSA_HILOGD("clear editor content cache");
951 {
952 std::lock_guard<std::mutex> lock(editorContentLock_);
953 textString_ = Str8ToStr16("");
954 selectOldBegin_ = 0;
955 selectOldEnd_ = 0;
956 selectNewBegin_ = 0;
957 selectNewEnd_ = 0;
958 }
959 {
960 std::lock_guard<std::mutex> lock(textConfigLock_);
961 textConfig_ = {};
962 }
963 std::lock_guard<std::mutex> lock(cursorInfoMutex_);
964 cursorInfo_ = {};
965 }
966
SelectByRange(int32_t start,int32_t end)967 void InputMethodController::SelectByRange(int32_t start, int32_t end)
968 {
969 IMSA_HILOGD("InputMethodController start: %{public}d, end: %{public}d", start, end);
970 auto listener = GetTextListener();
971 if (IsEditable() && listener != nullptr) {
972 listener->HandleSetSelection(start, end);
973 } else {
974 IMSA_HILOGE("not editable or textListener_ is nullptr");
975 }
976
977 if (controllerListener_ != nullptr) {
978 controllerListener_->OnSelectByRange(start, end);
979 } else {
980 IMSA_HILOGE("controllerListener_ is nullptr");
981 }
982 }
983
SelectByMovement(int32_t direction,int32_t cursorMoveSkip)984 void InputMethodController::SelectByMovement(int32_t direction, int32_t cursorMoveSkip)
985 {
986 IMSA_HILOGD("InputMethodController, direction: %{public}d, cursorMoveSkip: %{public}d", direction, cursorMoveSkip);
987 auto listener = GetTextListener();
988 if (IsEditable() && listener != nullptr) {
989 listener->HandleSelect(CURSOR_DIRECTION_BASE_VALUE + direction, cursorMoveSkip);
990 } else {
991 IMSA_HILOGE("not editable or textListener_ is nullptr");
992 }
993
994 if (controllerListener_ != nullptr) {
995 controllerListener_->OnSelectByMovement(direction);
996 } else {
997 IMSA_HILOGE("controllerListener_ is nullptr");
998 }
999 }
1000
HandleExtendAction(int32_t action)1001 int32_t InputMethodController::HandleExtendAction(int32_t action)
1002 {
1003 IMSA_HILOGD("InputMethodController, action: %{public}d", action);
1004 auto listener = GetTextListener();
1005 if (!IsEditable() || listener == nullptr) {
1006 IMSA_HILOGE("not editable or textListener is nullptr");
1007 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1008 }
1009 listener->HandleExtendAction(action);
1010 return ErrorCode::NO_ERROR;
1011 }
1012
GetTextListener()1013 sptr<OnTextChangedListener> InputMethodController::GetTextListener()
1014 {
1015 std::lock_guard<std::mutex> lock(textListenerLock_);
1016 return textListener_;
1017 }
1018
SetTextListener(sptr<OnTextChangedListener> listener)1019 void InputMethodController::SetTextListener(sptr<OnTextChangedListener> listener)
1020 {
1021 std::lock_guard<std::mutex> lock(textListenerLock_);
1022 textListener_ = listener;
1023 }
1024
IsEditable()1025 bool InputMethodController::IsEditable()
1026 {
1027 std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1028 if (clientInfo_.state != ClientState::ACTIVE) {
1029 IMSA_HILOGD("client not active");
1030 return false;
1031 }
1032 if (!isEditable_.load()) {
1033 IMSA_HILOGD("not in editable state");
1034 return false;
1035 }
1036 return true;
1037 }
1038
IsBound()1039 bool InputMethodController::IsBound()
1040 {
1041 std::lock_guard<std::recursive_mutex> lock(clientInfoLock_);
1042 if (clientInfo_.state != ClientState::ACTIVE) {
1043 IMSA_HILOGD("client not active");
1044 return false;
1045 }
1046 if (!isBound_.load()) {
1047 IMSA_HILOGD("not bound");
1048 return false;
1049 }
1050 return true;
1051 }
1052
InsertText(const std::u16string & text)1053 int32_t InputMethodController::InsertText(const std::u16string &text)
1054 {
1055 InputMethodSyncTrace tracer("IMC_InsertText");
1056 IMSA_HILOGD("in");
1057 auto listener = GetTextListener();
1058 if (!IsEditable() || listener == nullptr) {
1059 IMSA_HILOGE("not editable or textListener is nullptr");
1060 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1061 }
1062 int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1063 {
1064 InputMethodSyncTrace aceTracer("ACE_InsertText");
1065 listener->InsertText(text);
1066 }
1067 PrintLogIfAceTimeout(start);
1068 return ErrorCode::NO_ERROR;
1069 }
1070
DeleteForward(int32_t length)1071 int32_t InputMethodController::DeleteForward(int32_t length)
1072 {
1073 InputMethodSyncTrace tracer("IMC_DeleteForward");
1074 IMSA_HILOGD("run in, length: %{public}d", length);
1075 auto listener = GetTextListener();
1076 if (!IsEditable() || listener == nullptr) {
1077 IMSA_HILOGE("not editable or textListener is nullptr");
1078 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1079 }
1080 int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1081 {
1082 InputMethodSyncTrace aceTracer("ACE_DeleteForward");
1083 // reverse for compatibility
1084 listener->DeleteBackward(length);
1085 }
1086 PrintLogIfAceTimeout(start);
1087 return ErrorCode::NO_ERROR;
1088 }
1089
DeleteBackward(int32_t length)1090 int32_t InputMethodController::DeleteBackward(int32_t length)
1091 {
1092 IMSA_HILOGD("run in, length: %{public}d", length);
1093 auto listener = GetTextListener();
1094 if (!IsEditable() || listener == nullptr) {
1095 IMSA_HILOGE("not editable or textListener is nullptr");
1096 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1097 }
1098 // reverse for compatibility
1099 listener->DeleteForward(length);
1100 return ErrorCode::NO_ERROR;
1101 }
1102
MoveCursor(Direction direction)1103 int32_t InputMethodController::MoveCursor(Direction direction)
1104 {
1105 IMSA_HILOGD("run in, direction: %{public}d", static_cast<int32_t>(direction));
1106 auto listener = GetTextListener();
1107 if (!IsEditable() || listener == nullptr) {
1108 IMSA_HILOGE("not editable or textListener_ is nullptr");
1109 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1110 }
1111 listener->MoveCursor(direction);
1112 return ErrorCode::NO_ERROR;
1113 }
1114
SendKeyboardStatus(KeyboardStatus status)1115 void InputMethodController::SendKeyboardStatus(KeyboardStatus status)
1116 {
1117 IMSA_HILOGD("InputMethodController status: %{public}d", static_cast<int32_t>(status));
1118 auto listener = GetTextListener();
1119 if (listener == nullptr) {
1120 IMSA_HILOGE("textListener_ is nullptr");
1121 return;
1122 }
1123 listener->SendKeyboardStatus(status);
1124 if (status == KeyboardStatus::HIDE) {
1125 clientInfo_.isShowKeyboard = false;
1126 }
1127 }
1128
NotifyPanelStatusInfo(const PanelStatusInfo & info)1129 void InputMethodController::NotifyPanelStatusInfo(const PanelStatusInfo &info)
1130 {
1131 IMSA_HILOGD("InputMethodController, type: %{public}d, flag: %{public}d, visible: %{public}d, trigger: %{public}d.",
1132 static_cast<PanelType>(info.panelInfo.panelType), static_cast<PanelFlag>(info.panelInfo.panelFlag),
1133 info.visible, static_cast<Trigger>(info.trigger));
1134 auto listener = GetTextListener();
1135 if (listener == nullptr) {
1136 IMSA_HILOGE("textListener_ is nullptr");
1137 return;
1138 }
1139 listener->NotifyPanelStatusInfo(info);
1140 if (info.panelInfo.panelType == PanelType::SOFT_KEYBOARD
1141 && info.panelInfo.panelFlag != PanelFlag::FLG_CANDIDATE_COLUMN && !info.visible) {
1142 clientInfo_.isShowKeyboard = false;
1143 }
1144 }
1145
NotifyKeyboardHeight(uint32_t height)1146 void InputMethodController::NotifyKeyboardHeight(uint32_t height)
1147 {
1148 IMSA_HILOGD("InputMethodController, height: %{public}u.", height);
1149 auto listener = GetTextListener();
1150 if (listener == nullptr) {
1151 IMSA_HILOGE("textListener_ is nullptr");
1152 return;
1153 }
1154 listener->NotifyKeyboardHeight(height);
1155 }
1156
SendFunctionKey(int32_t functionKey)1157 int32_t InputMethodController::SendFunctionKey(int32_t functionKey)
1158 {
1159 IMSA_HILOGD("run in, functionKey: %{public}d", static_cast<int32_t>(functionKey));
1160 auto listener = GetTextListener();
1161 if (!IsEditable() || listener == nullptr) {
1162 IMSA_HILOGE("not editable or textListener_ is nullptr");
1163 return ErrorCode::ERROR_CLIENT_NOT_EDITABLE;
1164 }
1165 FunctionKey funcKey;
1166 funcKey.SetEnterKeyType(static_cast<EnterKeyType>(functionKey));
1167 listener->SendFunctionKey(funcKey);
1168 return ErrorCode::NO_ERROR;
1169 }
1170
IsInputTypeSupported(InputType type)1171 bool InputMethodController::IsInputTypeSupported(InputType type)
1172 {
1173 auto proxy = GetSystemAbilityProxy();
1174 if (proxy == nullptr) {
1175 IMSA_HILOGE("proxy is nullptr");
1176 return ErrorCode::ERROR_NULL_POINTER;
1177 }
1178 IMSA_HILOGI("type: %{public}d", static_cast<int32_t>(type));
1179 return proxy->IsInputTypeSupported(type);
1180 }
1181
StartInputType(InputType type)1182 int32_t InputMethodController::StartInputType(InputType type)
1183 {
1184 auto proxy = GetSystemAbilityProxy();
1185 if (proxy == nullptr) {
1186 IMSA_HILOGE("proxy is nullptr");
1187 return ErrorCode::ERROR_NULL_POINTER;
1188 }
1189 IMSA_HILOGI("type: %{public}d", static_cast<int32_t>(type));
1190 return proxy->StartInputType(type);
1191 }
1192
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)1193 int32_t InputMethodController::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
1194 {
1195 auto proxy = GetSystemAbilityProxy();
1196 if (proxy == nullptr) {
1197 IMSA_HILOGE("proxy is nullptr");
1198 return ErrorCode::ERROR_NULL_POINTER;
1199 }
1200 IMSA_HILOGI("type: %{public}d, flag: %{public}d", static_cast<int32_t>(panelInfo.panelType),
1201 static_cast<int32_t>(panelInfo.panelFlag));
1202 return proxy->IsPanelShown(panelInfo, isShown);
1203 }
1204
SetAgent(sptr<IRemoteObject> & agentObject)1205 void InputMethodController::SetAgent(sptr<IRemoteObject> &agentObject)
1206 {
1207 std::lock_guard<std::mutex> autoLock(agentLock_);
1208 if (agent_ != nullptr && agentObject_.GetRefPtr() == agentObject.GetRefPtr()) {
1209 IMSA_HILOGD("agent has already been set");
1210 return;
1211 }
1212 agent_ = std::make_shared<InputMethodAgentProxy>(agentObject);
1213 agentObject_ = agentObject;
1214 }
1215
GetAgent()1216 std::shared_ptr<IInputMethodAgent> InputMethodController::GetAgent()
1217 {
1218 std::lock_guard<std::mutex> autoLock(agentLock_);
1219 return agent_;
1220 }
1221
PrintLogIfAceTimeout(int64_t start)1222 void InputMethodController::PrintLogIfAceTimeout(int64_t start)
1223 {
1224 int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1225 if (end - start > ACE_DEAL_TIME_OUT) {
1226 IMSA_HILOGW("timeout:[%{public}" PRId64 ", %{public}" PRId64 "]", start, end);
1227 }
1228 }
1229 } // namespace MiscServices
1230 } // namespace OHOS
1231