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_ability.h"
17
18 #include <unistd.h>
19 #include <utility>
20
21 #include "global.h"
22 #include "input_method_agent_stub.h"
23 #include "input_method_core_stub.h"
24 #include "input_method_system_ability_proxy.h"
25 #include "input_method_utils.h"
26 #include "inputmethod_sysevent.h"
27 #include "inputmethod_trace.h"
28 #include "iservice_registry.h"
29 #include "itypes_util.h"
30 #include "message_parcel.h"
31 #include "string_ex.h"
32 #include "sys/prctl.h"
33 #include "system_ability_definition.h"
34 #include "tasks/task.h"
35 #include "task_manager.h"
36
37 namespace OHOS {
38 namespace MiscServices {
39 using namespace MessageID;
40 sptr<InputMethodAbility> InputMethodAbility::instance_;
41 std::mutex InputMethodAbility::instanceLock_;
42 constexpr double INVALID_CURSOR_VALUE = -1.0;
43 constexpr int32_t INVALID_SELECTION_VALUE = -1;
44 constexpr uint32_t FIND_PANEL_RETRY_INTERVAL = 10;
45 constexpr uint32_t MAX_RETRY_TIMES = 100;
46 constexpr uint32_t START_INPUT_CALLBACK_TIMEOUT_MS = 1000;
47
InputMethodAbility()48 InputMethodAbility::InputMethodAbility()
49 {
50 }
51
~InputMethodAbility()52 InputMethodAbility::~InputMethodAbility()
53 {
54 IMSA_HILOGI("InputMethodAbility::~InputMethodAbility.");
55 }
56
GetInstance()57 sptr<InputMethodAbility> InputMethodAbility::GetInstance()
58 {
59 if (instance_ == nullptr) {
60 std::lock_guard<std::mutex> autoLock(instanceLock_);
61 if (instance_ == nullptr) {
62 IMSA_HILOGI("InputMethodAbility need new IMA.");
63 instance_ = new (std::nothrow) InputMethodAbility();
64 if (instance_ == nullptr) {
65 IMSA_HILOGE("instance is nullptr!");
66 return instance_;
67 }
68 instance_->Initialize();
69 }
70 }
71 return instance_;
72 }
73
GetImsaProxy()74 sptr<IInputMethodSystemAbility> InputMethodAbility::GetImsaProxy()
75 {
76 std::lock_guard<std::mutex> lock(abilityLock_);
77 if (abilityManager_ != nullptr) {
78 return abilityManager_;
79 }
80 IMSA_HILOGI("InputMethodAbility get imsa proxy.");
81 sptr<ISystemAbilityManager> systemAbilityManager =
82 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
83 if (systemAbilityManager == nullptr) {
84 IMSA_HILOGE("systemAbilityManager is nullptr!");
85 return nullptr;
86 }
87 auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, "");
88 if (systemAbility == nullptr) {
89 IMSA_HILOGE("systemAbility is nullptr!");
90 return nullptr;
91 }
92 if (deathRecipient_ == nullptr) {
93 deathRecipient_ = new (std::nothrow) InputDeathRecipient();
94 if (deathRecipient_ == nullptr) {
95 IMSA_HILOGE("failed to new death recipient!");
96 return nullptr;
97 }
98 }
99 deathRecipient_->SetDeathRecipient([this](const wptr<IRemoteObject> &remote) { OnRemoteSaDied(remote); });
100 if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) {
101 IMSA_HILOGE("failed to add death recipient!");
102 return nullptr;
103 }
104 abilityManager_ = iface_cast<IInputMethodSystemAbility>(systemAbility);
105 return abilityManager_;
106 }
107
SetCoreAndAgent()108 int32_t InputMethodAbility::SetCoreAndAgent()
109 {
110 IMSA_HILOGD("InputMethodAbility, start.");
111 TaskManager::GetInstance().SetInited(true);
112
113 if (isBound_.load()) {
114 IMSA_HILOGD("already bound.");
115 return ErrorCode::NO_ERROR;
116 }
117 auto proxy = GetImsaProxy();
118 if (proxy == nullptr) {
119 IMSA_HILOGE("imsa proxy is nullptr!");
120 return ErrorCode::ERROR_NULL_POINTER;
121 }
122 int32_t ret = proxy->SetCoreAndAgent(coreStub_, agentStub_->AsObject());
123 if (ret != ErrorCode::NO_ERROR) {
124 IMSA_HILOGE("set failed, ret: %{public}d!", ret);
125 return ret;
126 }
127 isBound_.store(true);
128 IMSA_HILOGD("set successfully.");
129 return ErrorCode::NO_ERROR;
130 }
131
InitConnect()132 int32_t InputMethodAbility::InitConnect()
133 {
134 IMSA_HILOGD("InputMethodAbility, init connect.");
135 auto proxy = GetImsaProxy();
136 if (proxy == nullptr) {
137 IMSA_HILOGE("imsa proxy is nullptr!");
138 return ErrorCode::ERROR_NULL_POINTER;
139 }
140 int32_t ret = proxy->InitConnect();
141 if (ret != ErrorCode::NO_ERROR) {
142 IMSA_HILOGE("set failed, ret: %{public}d!", ret);
143 return ret;
144 }
145 return ErrorCode::NO_ERROR;
146 }
147
UnRegisteredProxyIme(UnRegisteredType type)148 int32_t InputMethodAbility::UnRegisteredProxyIme(UnRegisteredType type)
149 {
150 isBound_.store(false);
151 auto proxy = GetImsaProxy();
152 if (proxy == nullptr) {
153 IMSA_HILOGE("imsa proxy is nullptr!");
154 return ErrorCode::ERROR_NULL_POINTER;
155 }
156 return proxy->UnRegisteredProxyIme(type, coreStub_);
157 }
158
Initialize()159 void InputMethodAbility::Initialize()
160 {
161 IMSA_HILOGD("IMA init.");
162 sptr<InputMethodCoreStub> coreStub = new (std::nothrow) InputMethodCoreStub();
163 if (coreStub == nullptr) {
164 IMSA_HILOGE("failed to create core!");
165 return;
166 }
167 sptr<InputMethodAgentStub> agentStub = new (std::nothrow) InputMethodAgentStub();
168 if (agentStub == nullptr) {
169 IMSA_HILOGE("failed to create agent!");
170 return;
171 }
172 agentStub_ = agentStub;
173 coreStub_ = coreStub;
174 }
175
SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)176 void InputMethodAbility::SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)
177 {
178 IMSA_HILOGD("InputMethodAbility start.");
179 if (imeListener_ == nullptr) {
180 imeListener_ = std::move(imeListener);
181 }
182 }
183
GetImeListener()184 std::shared_ptr<InputMethodEngineListener> InputMethodAbility::GetImeListener()
185 {
186 return imeListener_;
187 }
188
SetKdListener(std::shared_ptr<KeyboardListener> kdListener)189 void InputMethodAbility::SetKdListener(std::shared_ptr<KeyboardListener> kdListener)
190 {
191 IMSA_HILOGD("InputMethodAbility start.");
192 if (kdListener_ == nullptr) {
193 kdListener_ = std::move(kdListener);
194 }
195 }
196
OnInitInputControlChannel(sptr<IRemoteObject> channelObj)197 void InputMethodAbility::OnInitInputControlChannel(sptr<IRemoteObject> channelObj)
198 {
199 IMSA_HILOGD("InputMethodAbility::OnInitInputControlChannel start.");
200 SetInputControlChannel(channelObj);
201 }
202
StartInput(const InputClientInfo &clientInfo, bool isBindFromClient)203 int32_t InputMethodAbility::StartInput(const InputClientInfo &clientInfo, bool isBindFromClient)
204 {
205 if (clientInfo.channel == nullptr) {
206 IMSA_HILOGE("channelObject is nullptr!");
207 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
208 }
209 IMSA_HILOGI("IMA isShowKeyboard: %{public}d, isBindFromClient: %{public}d.", clientInfo.isShowKeyboard,
210 isBindFromClient);
211 SetInputDataChannel(clientInfo.channel);
212 if (clientInfo.needHide) {
213 IMSA_HILOGD("pwd or normal input pattern changed, need hide panel first.");
214 auto panel = GetSoftKeyboardPanel();
215 if (panel != nullptr) {
216 panel->HidePanel(false);
217 }
218 }
219 int32_t ret = isBindFromClient ? InvokeStartInputCallback(clientInfo.config, clientInfo.isNotifyInputStart)
220 : InvokeStartInputCallback(clientInfo.isNotifyInputStart);
221 if (ret != ErrorCode::NO_ERROR) {
222 IMSA_HILOGE("failed to invoke callback, ret: %{public}d!", ret);
223 return ret;
224 }
225
226 auto showPanel = [&, needShow = clientInfo.isShowKeyboard] {
227 if (needShow) {
228 ShowKeyboardImplWithoutLock(cmdId_);
229 }
230 isImeTerminating.store(false);
231 };
232
233 if (!imeListener_) {
234 showPanel();
235 return ErrorCode::NO_ERROR;
236 }
237
238 uint64_t seqId = Task::GetNextSeqId();
239 imeListener_->PostTaskToEventHandler(
240 [seqId] {
241 TaskManager::GetInstance().Complete(seqId);
242 },
243 "task_manager_complete");
244
245 TaskManager::GetInstance().WaitExec(seqId, START_INPUT_CALLBACK_TIMEOUT_MS, showPanel);
246 return ErrorCode::NO_ERROR;
247 }
248
OnSetSubtype(SubProperty subProperty)249 void InputMethodAbility::OnSetSubtype(SubProperty subProperty)
250 {
251 imeListener_->OnSetSubtype(subProperty);
252 }
253
OnSetInputType(InputType inputType)254 void InputMethodAbility::OnSetInputType(InputType inputType)
255 {
256 inputType_ = inputType;
257 IMSA_HILOGD("OnSetInputType, inputType = %{public}d", static_cast<int32_t>(inputType));
258 auto panel = GetSoftKeyboardPanel();
259 if (panel != nullptr) {
260 auto keyboardSize = panel->GetKeyboardSize();
261 SysPanelStatus sysPanelStatus = { inputType_, panel->GetPanelFlag(), keyboardSize.width, keyboardSize.height };
262 NotifyPanelStatus(panel, sysPanelStatus);
263 }
264 }
265
ClearDataChannel(const sptr<IRemoteObject> &channel)266 void InputMethodAbility::ClearDataChannel(const sptr<IRemoteObject> &channel)
267 {
268 std::lock_guard<std::mutex> lock(dataChannelLock_);
269 if (dataChannelObject_ == nullptr || channel == nullptr) {
270 IMSA_HILOGD("dataChannelObject_ already nullptr.");
271 return;
272 }
273 if (dataChannelObject_.GetRefPtr() == channel.GetRefPtr()) {
274 dataChannelObject_ = nullptr;
275 dataChannelProxy_ = nullptr;
276 IMSA_HILOGD("end.");
277 }
278 }
279
StopInput(sptr<IRemoteObject> channelObject)280 int32_t InputMethodAbility::StopInput(sptr<IRemoteObject> channelObject)
281 {
282 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
283 int32_t cmdCount = ++cmdId_;
284 IMSA_HILOGI("IMA");
285 HideKeyboardImplWithoutLock(cmdCount, false);
286 ClearDataChannel(channelObject);
287 ClearInputAttribute();
288 ClearInputType();
289 if (imeListener_ != nullptr) {
290 imeListener_->OnInputFinish();
291 }
292 return ErrorCode::NO_ERROR;
293 }
294
DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> &keyEvent, sptr<KeyEventConsumerProxy> &consumer)295 int32_t InputMethodAbility::DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> &keyEvent,
296 sptr<KeyEventConsumerProxy> &consumer)
297 {
298 if (keyEvent == nullptr) {
299 IMSA_HILOGE("keyEvent is nullptr!");
300 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
301 }
302 if (kdListener_ == nullptr) {
303 IMSA_HILOGE("kdListener_ is nullptr!");
304 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
305 }
306 IMSA_HILOGD("InputMethodAbility, start.");
307
308 if (!kdListener_->OnDealKeyEvent(keyEvent, consumer)) {
309 IMSA_HILOGE("keyEvent not deal!");
310 return ErrorCode::ERROR_DISPATCH_KEY_EVENT;
311 }
312 return ErrorCode::NO_ERROR;
313 }
314
SetCallingWindow(uint32_t windowId)315 void InputMethodAbility::SetCallingWindow(uint32_t windowId)
316 {
317 IMSA_HILOGD("InputMethodAbility windowId: %{public}d.", windowId);
318 panels_.ForEach([windowId](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
319 panel->SetCallingWindow(windowId);
320 return false;
321 });
322 if (imeListener_ == nullptr) {
323 IMSA_HILOGD("imeListener_ is nullptr!");
324 return;
325 }
326 imeListener_->OnSetCallingWindow(windowId);
327 }
328
OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height)329 void InputMethodAbility::OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height)
330 {
331 if (kdListener_ == nullptr) {
332 IMSA_HILOGE("kdListener_ is nullptr!");
333 return;
334 }
335 IMSA_HILOGD("x: %{public}d, y: %{public}d, height: %{public}d.", positionX, positionY, height);
336 kdListener_->OnCursorUpdate(positionX, positionY, height);
337 }
338
OnSelectionChange( std::u16string text, int32_t oldBegin, int32_t oldEnd, int32_t newBegin, int32_t newEnd)339 void InputMethodAbility::OnSelectionChange(
340 std::u16string text, int32_t oldBegin, int32_t oldEnd, int32_t newBegin, int32_t newEnd)
341 {
342 if (kdListener_ == nullptr) {
343 IMSA_HILOGE("kdListener_ is nullptr!");
344 return;
345 }
346 kdListener_->OnTextChange(Str16ToStr8(text));
347 kdListener_->OnSelectionChange(oldBegin, oldEnd, newBegin, newEnd);
348 }
349
OnAttributeChange(InputAttribute attribute)350 void InputMethodAbility::OnAttributeChange(InputAttribute attribute)
351 {
352 if (kdListener_ == nullptr) {
353 IMSA_HILOGE("kdListener_ is nullptr!");
354 return;
355 }
356 IMSA_HILOGD("enterKeyType: %{public}d, inputPattern: %{public}d.", attribute.enterKeyType,
357 attribute.inputPattern);
358 SetInputAttribute(attribute);
359 // add for mod inputPattern when panel show
360 auto panel = GetSoftKeyboardPanel();
361 if (panel != nullptr) {
362 auto keyboardSize = panel->GetKeyboardSize();
363 SysPanelStatus sysPanelStatus = { inputType_, panel->GetPanelFlag(), keyboardSize.width, keyboardSize.height };
364 NotifyPanelStatus(panel, sysPanelStatus);
365 }
366 kdListener_->OnEditorAttributeChange(attribute);
367 }
368
OnStopInputService(bool isTerminateIme)369 int32_t InputMethodAbility::OnStopInputService(bool isTerminateIme)
370 {
371 IMSA_HILOGI("isTerminateIme: %{public}d.", isTerminateIme);
372 isBound_.store(false);
373 auto imeListener = GetImeListener();
374 if (imeListener == nullptr) {
375 return ErrorCode::ERROR_IME_NOT_STARTED;
376 }
377 if (isTerminateIme) {
378 isImeTerminating.store(true);
379 return imeListener->OnInputStop();
380 }
381 return ErrorCode::NO_ERROR;
382 }
383
HideKeyboard(bool isForce)384 int32_t InputMethodAbility::HideKeyboard(bool isForce)
385 {
386 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
387 int32_t cmdCount = ++cmdId_;
388 return HideKeyboardImplWithoutLock(cmdCount, isForce);
389 }
390
HideKeyboardImplWithoutLock(int32_t cmdId, bool isForce)391 int32_t InputMethodAbility::HideKeyboardImplWithoutLock(int32_t cmdId, bool isForce)
392 {
393 if (cmdId != cmdId_) {
394 IMSA_HILOGE("current is not last cmd cur: %{public}d, cmdId_: %{public}d!", cmdId, cmdId_);
395 return ErrorCode::NO_ERROR;
396 }
397 return HideKeyboard(Trigger::IMF, isForce);
398 }
399
ShowKeyboard()400 int32_t InputMethodAbility::ShowKeyboard()
401 {
402 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
403 int32_t cmdCount = ++cmdId_;
404 return ShowKeyboardImplWithoutLock(cmdCount);
405 }
406
ShowKeyboardImplWithLock(int32_t cmdId)407 int32_t InputMethodAbility::ShowKeyboardImplWithLock(int32_t cmdId)
408 {
409 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
410 return ShowKeyboardImplWithoutLock(cmdId);
411 }
412
ShowKeyboardImplWithoutLock(int32_t cmdId)413 int32_t InputMethodAbility::ShowKeyboardImplWithoutLock(int32_t cmdId)
414 {
415 if (cmdId != cmdId_) {
416 IMSA_HILOGE("current is not last cmd cur: %{public}d, cmdId_: %{public}d!", cmdId, cmdId_);
417 return ErrorCode::NO_ERROR;
418 }
419 if (imeListener_ == nullptr) {
420 IMSA_HILOGE("imeListener is nullptr!");
421 return ErrorCode::ERROR_IME;
422 }
423 IMSA_HILOGI("IMA start.");
424 if (panels_.Contains(SOFT_KEYBOARD)) {
425 auto panel = GetSoftKeyboardPanel();
426 if (panel == nullptr) {
427 IMSA_HILOGE("panel is nullptr!");
428 return ErrorCode::ERROR_IME;
429 }
430 auto flag = panel->GetPanelFlag();
431 imeListener_->OnKeyboardStatus(true);
432 if (flag == FLG_CANDIDATE_COLUMN) {
433 IMSA_HILOGI("panel flag is candidate, no need to show.");
434 NotifyKeyboardHeight(0, flag);
435 return ErrorCode::NO_ERROR;
436 }
437 return ShowPanel(panel, flag, Trigger::IMF);
438 }
439 IMSA_HILOGI("panel not create.");
440 auto channel = GetInputDataChannelProxy();
441 if (channel != nullptr) {
442 channel->SendKeyboardStatus(KeyboardStatus::SHOW);
443 }
444 imeListener_->OnKeyboardStatus(true);
445 return ErrorCode::NO_ERROR;
446 }
447
NotifyPanelStatusInfo(const PanelStatusInfo &info)448 void InputMethodAbility::NotifyPanelStatusInfo(const PanelStatusInfo &info)
449 {
450 // CANDIDATE_COLUMN not notify
451 auto channel = GetInputDataChannelProxy();
452 NotifyPanelStatusInfo(info, channel);
453 }
454
InvokeStartInputCallback(bool isNotifyInputStart)455 int32_t InputMethodAbility::InvokeStartInputCallback(bool isNotifyInputStart)
456 {
457 TextTotalConfig textConfig = {};
458 int32_t ret = GetTextConfig(textConfig);
459 if (ret == ErrorCode::NO_ERROR) {
460 return InvokeStartInputCallback(textConfig, isNotifyInputStart);
461 }
462 IMSA_HILOGW("failed to get text config, ret: %{public}d.", ret);
463 if (imeListener_ == nullptr) {
464 IMSA_HILOGE("imeListener_ is nullptr!");
465 return ErrorCode::ERROR_IME;
466 }
467 if (isNotifyInputStart) {
468 imeListener_->OnInputStart();
469 }
470 return ErrorCode::NO_ERROR;
471 }
472
InvokeStartInputCallback(const TextTotalConfig &textConfig, bool isNotifyInputStart)473 int32_t InputMethodAbility::InvokeStartInputCallback(const TextTotalConfig &textConfig, bool isNotifyInputStart)
474 {
475 if (imeListener_ == nullptr) {
476 IMSA_HILOGE("imeListener_ is nullptr!");
477 return ErrorCode::ERROR_IME;
478 }
479 positionY_ = textConfig.positionY;
480 height_ = textConfig.height;
481 SetInputAttribute(textConfig.inputAttribute);
482 if (kdListener_ != nullptr) {
483 kdListener_->OnEditorAttributeChange(textConfig.inputAttribute);
484 }
485 if (TextConfig::IsPrivateCommandValid(textConfig.privateCommand) && IsDefaultIme()) {
486 IMSA_HILOGI("notify privateCommand.");
487 imeListener_->ReceivePrivateCommand(textConfig.privateCommand);
488 }
489 if (isNotifyInputStart) {
490 imeListener_->OnInputStart();
491 }
492 if (kdListener_ != nullptr) {
493 if (textConfig.cursorInfo.left != INVALID_CURSOR_VALUE) {
494 kdListener_->OnCursorUpdate(textConfig.cursorInfo.left, textConfig.cursorInfo.top,
495 textConfig.cursorInfo.height);
496 }
497 if (textConfig.textSelection.newBegin == INVALID_SELECTION_VALUE
498 || (textConfig.textSelection.newBegin == textConfig.textSelection.oldBegin
499 && textConfig.textSelection.newEnd == textConfig.textSelection.oldEnd)) {
500 IMSA_HILOGD("invalid selection or no selection change");
501 } else {
502 kdListener_->OnSelectionChange(textConfig.textSelection.oldBegin, textConfig.textSelection.oldEnd,
503 textConfig.textSelection.newBegin, textConfig.textSelection.newEnd);
504 }
505 }
506 auto task = [this, textConfig]() {
507 panels_.ForEach([&textConfig](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
508 panel->SetCallingWindow(textConfig.windowId);
509 return false;
510 });
511 };
512 imeListener_->PostTaskToEventHandler(task, "SetCallingWindow");
513 if (textConfig.windowId != INVALID_WINDOW_ID) {
514 imeListener_->OnSetCallingWindow(textConfig.windowId);
515 }
516 return ErrorCode::NO_ERROR;
517 }
518
InsertText(const std::string text)519 int32_t InputMethodAbility::InsertText(const std::string text)
520 {
521 InputMethodSyncTrace tracer("IMA_InsertText");
522 IMSA_HILOGD("InputMethodAbility start.");
523 auto channel = GetInputDataChannelProxy();
524 if (channel == nullptr) {
525 IMSA_HILOGE("channel is nullptr!");
526 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
527 }
528 return channel->InsertText(Str8ToStr16(text));
529 }
530
DeleteForward(int32_t length)531 int32_t InputMethodAbility::DeleteForward(int32_t length)
532 {
533 InputMethodSyncTrace tracer("IMA_DeleteForward");
534 IMSA_HILOGD("InputMethodAbility start, length: %{public}d.", length);
535 auto channel = GetInputDataChannelProxy();
536 if (channel == nullptr) {
537 IMSA_HILOGE("channel is nullptr!");
538 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
539 }
540 return channel->DeleteForward(length);
541 }
542
DeleteBackward(int32_t length)543 int32_t InputMethodAbility::DeleteBackward(int32_t length)
544 {
545 IMSA_HILOGD("InputMethodAbility start, length: %{public}d.", length);
546 auto channel = GetInputDataChannelProxy();
547 if (channel == nullptr) {
548 IMSA_HILOGE("channel is nullptr!");
549 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
550 }
551 return channel->DeleteBackward(length);
552 }
553
SendFunctionKey(int32_t funcKey)554 int32_t InputMethodAbility::SendFunctionKey(int32_t funcKey)
555 {
556 auto channel = GetInputDataChannelProxy();
557 if (channel == nullptr) {
558 IMSA_HILOGE("channel is nullptr!");
559 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
560 }
561 return channel->SendFunctionKey(funcKey);
562 }
563
HideKeyboardSelf()564 int32_t InputMethodAbility::HideKeyboardSelf()
565 {
566 // Current Ime is exiting, hide softkeyboard will cause the TextFiled to lose focus.
567 if (isImeTerminating.load()) {
568 IMSA_HILOGI("Current Ime is terminating, no need to hide keyboard.");
569 return ErrorCode::NO_ERROR;
570 }
571 InputMethodSyncTrace tracer("IMA_HideKeyboardSelf start.");
572 auto ret = HideKeyboard(Trigger::IME_APP, false);
573 if (ret == ErrorCode::NO_ERROR) {
574 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_SELF);
575 }
576 return ret == ErrorCode::ERROR_CLIENT_NULL_POINTER ? ret : ErrorCode::NO_ERROR;
577 }
578
SendExtendAction(int32_t action)579 int32_t InputMethodAbility::SendExtendAction(int32_t action)
580 {
581 IMSA_HILOGD("InputMethodAbility, action: %{public}d.", action);
582 auto channel = GetInputDataChannelProxy();
583 if (channel == nullptr) {
584 IMSA_HILOGE("channel is nullptr!");
585 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
586 }
587 return channel->HandleExtendAction(action);
588 }
589
GetTextBeforeCursor(int32_t number, std::u16string &text)590 int32_t InputMethodAbility::GetTextBeforeCursor(int32_t number, std::u16string &text)
591 {
592 InputMethodSyncTrace tracer("IMA_GetForward");
593 IMSA_HILOGD("InputMethodAbility, number: %{public}d.", number);
594 auto channel = GetInputDataChannelProxy();
595 if (channel == nullptr) {
596 IMSA_HILOGE("channel is nullptr!");
597 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
598 }
599 return channel->GetTextBeforeCursor(number, text);
600 }
601
GetTextAfterCursor(int32_t number, std::u16string &text)602 int32_t InputMethodAbility::GetTextAfterCursor(int32_t number, std::u16string &text)
603 {
604 InputMethodSyncTrace tracer("IMA_GetTextAfterCursor");
605 IMSA_HILOGD("InputMethodAbility, number: %{public}d.", number);
606 auto channel = GetInputDataChannelProxy();
607 if (channel == nullptr) {
608 IMSA_HILOGE("channel is nullptr!");
609 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
610 }
611 return channel->GetTextAfterCursor(number, text);
612 }
613
MoveCursor(int32_t keyCode)614 int32_t InputMethodAbility::MoveCursor(int32_t keyCode)
615 {
616 IMSA_HILOGD("InputMethodAbility, keyCode: %{public}d.", keyCode);
617 auto channel = GetInputDataChannelProxy();
618 if (channel == nullptr) {
619 IMSA_HILOGE("channel is nullptr!");
620 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
621 }
622 return channel->MoveCursor(keyCode);
623 }
624
SelectByRange(int32_t start, int32_t end)625 int32_t InputMethodAbility::SelectByRange(int32_t start, int32_t end)
626 {
627 IMSA_HILOGD("InputMethodAbility, start: %{public}d, end: %{public}d", start, end);
628 if (start < 0 || end < 0) {
629 IMSA_HILOGE("check parameter failed, start: %{public}d, end: %{public}d!", start, end);
630 return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
631 }
632 auto dataChannel = GetInputDataChannelProxy();
633 if (dataChannel == nullptr) {
634 IMSA_HILOGE("datachannel is nullptr!");
635 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
636 }
637 return dataChannel->SelectByRange(start, end);
638 }
639
SelectByMovement(int32_t direction)640 int32_t InputMethodAbility::SelectByMovement(int32_t direction)
641 {
642 IMSA_HILOGD("InputMethodAbility, direction: %{public}d.", direction);
643 auto dataChannel = GetInputDataChannelProxy();
644 if (dataChannel == nullptr) {
645 IMSA_HILOGE("datachannel is nullptr!");
646 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
647 }
648 return dataChannel->SelectByMovement(direction, 0);
649 }
650
GetEnterKeyType(int32_t &keyType)651 int32_t InputMethodAbility::GetEnterKeyType(int32_t &keyType)
652 {
653 IMSA_HILOGD("InputMethodAbility start.");
654 auto channel = GetInputDataChannelProxy();
655 if (channel == nullptr) {
656 IMSA_HILOGE("channel is nullptr!");
657 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
658 }
659 return channel->GetEnterKeyType(keyType);
660 }
661
GetInputPattern(int32_t &inputPattern)662 int32_t InputMethodAbility::GetInputPattern(int32_t &inputPattern)
663 {
664 IMSA_HILOGD("InputMethodAbility start.");
665 auto channel = GetInputDataChannelProxy();
666 if (channel == nullptr) {
667 IMSA_HILOGE("channel is nullptr!");
668 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
669 }
670 return channel->GetInputPattern(inputPattern);
671 }
672
GetTextIndexAtCursor(int32_t &index)673 int32_t InputMethodAbility::GetTextIndexAtCursor(int32_t &index)
674 {
675 IMSA_HILOGD("InputMethodAbility start.");
676 auto channel = GetInputDataChannelProxy();
677 if (channel == nullptr) {
678 IMSA_HILOGE("channel is nullptr!");
679 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
680 }
681 return channel->GetTextIndexAtCursor(index);
682 }
683
GetTextConfig(TextTotalConfig &textConfig)684 int32_t InputMethodAbility::GetTextConfig(TextTotalConfig &textConfig)
685 {
686 IMSA_HILOGD("InputMethodAbility start.");
687 auto channel = GetInputDataChannelProxy();
688 if (channel == nullptr) {
689 IMSA_HILOGE("channel is nullptr!");
690 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
691 }
692 return channel->GetTextConfig(textConfig);
693 }
694
SetInputDataChannel(const sptr<IRemoteObject> &object)695 void InputMethodAbility::SetInputDataChannel(const sptr<IRemoteObject> &object)
696 {
697 IMSA_HILOGD("SetInputDataChannel start.");
698 std::lock_guard<std::mutex> lock(dataChannelLock_);
699 auto channelProxy = std::make_shared<InputDataChannelProxy>(object);
700 if (channelProxy == nullptr) {
701 IMSA_HILOGE("failed to create channel proxy!");
702 return;
703 }
704 dataChannelObject_ = object;
705 dataChannelProxy_ = channelProxy;
706 }
707
GetInputDataChannelProxy()708 std::shared_ptr<InputDataChannelProxy> InputMethodAbility::GetInputDataChannelProxy()
709 {
710 std::lock_guard<std::mutex> lock(dataChannelLock_);
711 return dataChannelProxy_;
712 }
713
SetInputControlChannel(sptr<IRemoteObject> &object)714 void InputMethodAbility::SetInputControlChannel(sptr<IRemoteObject> &object)
715 {
716 IMSA_HILOGD("SetInputControlChannel start.");
717 std::lock_guard<std::mutex> lock(controlChannelLock_);
718 std::shared_ptr<InputControlChannelProxy> channelProxy = std::make_shared<InputControlChannelProxy>(object);
719 if (channelProxy == nullptr) {
720 IMSA_HILOGD("channelProxy is nullptr!");
721 return;
722 }
723 controlChannel_ = channelProxy;
724 }
725
ClearInputControlChannel()726 void InputMethodAbility::ClearInputControlChannel()
727 {
728 std::lock_guard<std::mutex> lock(controlChannelLock_);
729 controlChannel_ = nullptr;
730 }
731
GetInputControlChannel()732 std::shared_ptr<InputControlChannelProxy> InputMethodAbility::GetInputControlChannel()
733 {
734 std::lock_guard<std::mutex> lock(controlChannelLock_);
735 return controlChannel_;
736 }
737
OnRemoteSaDied(const wptr<IRemoteObject> &object)738 void InputMethodAbility::OnRemoteSaDied(const wptr<IRemoteObject> &object)
739 {
740 IMSA_HILOGI("input method service died.");
741 isBound_.store(false);
742 ClearInputControlChannel();
743 ClearSystemCmdChannel();
744 {
745 std::lock_guard<std::mutex> lock(abilityLock_);
746 abilityManager_ = nullptr;
747 }
748 if (imeListener_ != nullptr) {
749 imeListener_->OnInputStop();
750 }
751 }
752
GetSecurityMode(int32_t &security)753 int32_t InputMethodAbility::GetSecurityMode(int32_t &security)
754 {
755 IMSA_HILOGI("InputMethodAbility start.");
756 auto proxy = GetImsaProxy();
757 if (proxy == nullptr) {
758 IMSA_HILOGE("failed to get imsa proxy!");
759 return false;
760 }
761 return proxy->GetSecurityMode(security);
762 }
763
ClearSystemCmdChannel()764 void InputMethodAbility::ClearSystemCmdChannel()
765 {
766 std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
767 if (systemCmdChannelProxy_ == nullptr) {
768 IMSA_HILOGD("systemCmdChannelProxy_ already nullptr.");
769 return;
770 }
771 systemCmdChannelProxy_ = nullptr;
772 IMSA_HILOGD("end.");
773 }
774
GetSystemCmdChannelProxy()775 sptr<SystemCmdChannelProxy> InputMethodAbility::GetSystemCmdChannelProxy()
776 {
777 std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
778 return systemCmdChannelProxy_;
779 }
780
OnConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)781 int32_t InputMethodAbility::OnConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)
782 {
783 IMSA_HILOGD("InputMethodAbility start.");
784 std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
785 systemCmdChannelProxy_ = new (std::nothrow) SystemCmdChannelProxy(channel);
786 if (systemCmdChannelProxy_ == nullptr) {
787 IMSA_HILOGE("failed to create channel proxy!");
788 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
789 }
790 systemAgentStub_ = new (std::nothrow) InputMethodAgentStub();
791 if (systemAgentStub_ == nullptr) {
792 IMSA_HILOGE("failed to create agent!");
793 systemCmdChannelProxy_ = nullptr;
794 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
795 }
796 agent = systemAgentStub_->AsObject();
797 return ErrorCode::NO_ERROR;
798 }
799
OnSecurityChange(int32_t security)800 int32_t InputMethodAbility::OnSecurityChange(int32_t security)
801 {
802 IMSA_HILOGI("InputMethodAbility start.");
803 if (imeListener_ == nullptr) {
804 IMSA_HILOGE("imeListener_ is nullptr!");
805 return ErrorCode::ERROR_BAD_PARAMETERS;
806 }
807 imeListener_->OnSecurityChange(security);
808 return ErrorCode::NO_ERROR;
809 }
810
CreatePanel(const std::shared_ptr<AbilityRuntime::Context> &context, const PanelInfo &panelInfo, std::shared_ptr<InputMethodPanel> &inputMethodPanel)811 int32_t InputMethodAbility::CreatePanel(const std::shared_ptr<AbilityRuntime::Context> &context,
812 const PanelInfo &panelInfo, std::shared_ptr<InputMethodPanel> &inputMethodPanel)
813 {
814 IMSA_HILOGI("InputMethodAbility start.");
815 auto panelHeightCallback = [this](uint32_t panelHeight, PanelFlag panelFlag) {
816 NotifyKeyboardHeight(panelHeight, panelFlag);
817 };
818 auto flag = panels_.ComputeIfAbsent(
819 panelInfo.panelType, [panelHeightCallback, &panelInfo, &context, &inputMethodPanel](
820 const PanelType &panelType, std::shared_ptr<InputMethodPanel> &panel) {
821 inputMethodPanel = std::make_shared<InputMethodPanel>();
822 inputMethodPanel->SetPanelHeightCallback(panelHeightCallback);
823 auto ret = inputMethodPanel->CreatePanel(context, panelInfo);
824 if (ret == ErrorCode::NO_ERROR) {
825 panel = inputMethodPanel;
826 return true;
827 }
828 inputMethodPanel = nullptr;
829 return false;
830 });
831 return flag ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL;
832 }
833
DestroyPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)834 int32_t InputMethodAbility::DestroyPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
835 {
836 IMSA_HILOGI("InputMethodAbility start.");
837 if (inputMethodPanel == nullptr) {
838 IMSA_HILOGE("panel is nullptr!");
839 return ErrorCode::ERROR_BAD_PARAMETERS;
840 }
841 auto ret = inputMethodPanel->DestroyPanel();
842 if (ret == ErrorCode::NO_ERROR) {
843 PanelType panelType = inputMethodPanel->GetPanelType();
844 panels_.Erase(panelType);
845 }
846 return ret;
847 }
848
ShowPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)849 int32_t InputMethodAbility::ShowPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
850 {
851 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
852 if (inputMethodPanel == nullptr) {
853 return ErrorCode::ERROR_BAD_PARAMETERS;
854 }
855 return ShowPanel(inputMethodPanel, inputMethodPanel->GetPanelFlag(), Trigger::IME_APP);
856 }
857
HidePanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)858 int32_t InputMethodAbility::HidePanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
859 {
860 if (inputMethodPanel == nullptr) {
861 return ErrorCode::ERROR_BAD_PARAMETERS;
862 }
863 // Current Ime is exiting, hide softkeyboard will cause the TextFiled to lose focus.
864 if (isImeTerminating.load() && inputMethodPanel->GetPanelType() == PanelType::SOFT_KEYBOARD) {
865 IMSA_HILOGI("Current Ime is terminating, no need to hide keyboard.");
866 return ErrorCode::NO_ERROR;
867 }
868
869 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
870 return HidePanel(inputMethodPanel, inputMethodPanel->GetPanelFlag(), Trigger::IME_APP, false);
871 }
872
ShowPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel, PanelFlag flag, Trigger trigger)873 int32_t InputMethodAbility::ShowPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel, PanelFlag flag,
874 Trigger trigger)
875 {
876 if (inputMethodPanel == nullptr) {
877 return ErrorCode::ERROR_BAD_PARAMETERS;
878 }
879 if (trigger == Trigger::IME_APP && GetInputDataChannelProxy() == nullptr) {
880 IMSA_HILOGE("channel is nullptr!");
881 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
882 }
883 if (flag == FLG_FIXED && inputMethodPanel->GetPanelType() == SOFT_KEYBOARD) {
884 auto ret = inputMethodPanel->SetTextFieldAvoidInfo(positionY_, height_);
885 if (ret != ErrorCode::NO_ERROR) {
886 IMSA_HILOGE("failed to set keyBoard, ret: %{public}d!", ret);
887 }
888 }
889 auto keyboardSize = inputMethodPanel->GetKeyboardSize();
890 SysPanelStatus sysPanelStatus = { inputType_, flag, keyboardSize.width, keyboardSize.height };
891 NotifyPanelStatus(inputMethodPanel, sysPanelStatus);
892 auto ret = inputMethodPanel->ShowPanel();
893 if (ret == ErrorCode::NO_ERROR) {
894 NotifyPanelStatusInfo({ { inputMethodPanel->GetPanelType(), flag }, true, trigger });
895 }
896 return ret;
897 }
898
HidePanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel, PanelFlag flag, Trigger trigger, bool isForce)899 int32_t InputMethodAbility::HidePanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel, PanelFlag flag,
900 Trigger trigger, bool isForce)
901 {
902 if (inputMethodPanel == nullptr) {
903 return ErrorCode::ERROR_BAD_PARAMETERS;
904 }
905 auto ret = inputMethodPanel->HidePanel(isForce);
906 if (ret != ErrorCode::NO_ERROR) {
907 IMSA_HILOGD("failed, ret: %{public}d", ret);
908 return ret;
909 }
910 NotifyPanelStatusInfo({ { inputMethodPanel->GetPanelType(), flag }, false, trigger });
911 return ErrorCode::NO_ERROR;
912 }
913
NotifyPanelStatus( const std::shared_ptr<InputMethodPanel> &inputMethodPanel, SysPanelStatus &sysPanelStatus)914 int32_t InputMethodAbility::NotifyPanelStatus(
915 const std::shared_ptr<InputMethodPanel> &inputMethodPanel, SysPanelStatus &sysPanelStatus)
916 {
917 if (inputMethodPanel->GetPanelType() != SOFT_KEYBOARD) {
918 return ErrorCode::NO_ERROR;
919 }
920 // If it is not binding, do not need to notify the panel
921 auto channel = GetInputDataChannelProxy();
922 if (channel == nullptr) {
923 return ErrorCode::NO_ERROR;
924 }
925 sysPanelStatus.inputType = inputType_;
926 auto systemChannel = GetSystemCmdChannelProxy();
927 if (systemChannel == nullptr) {
928 IMSA_HILOGE("channel is nullptr!");
929 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
930 }
931 return systemChannel->NotifyPanelStatus(sysPanelStatus);
932 }
933
SetInputAttribute(const InputAttribute &inputAttribute)934 void InputMethodAbility::SetInputAttribute(const InputAttribute &inputAttribute)
935 {
936 std::lock_guard<std::mutex> lock(inputAttrLock_);
937 inputAttribute_ = inputAttribute;
938 }
939
ClearInputAttribute()940 void InputMethodAbility::ClearInputAttribute()
941 {
942 std::lock_guard<std::mutex> lock(inputAttrLock_);
943 inputAttribute_ = {};
944 }
945
GetInputAttribute()946 InputAttribute InputMethodAbility::GetInputAttribute()
947 {
948 std::lock_guard<std::mutex> lock(inputAttrLock_);
949 return inputAttribute_;
950 }
951
HideKeyboard(Trigger trigger, bool isForce)952 int32_t InputMethodAbility::HideKeyboard(Trigger trigger, bool isForce)
953 {
954 InputMethodSyncTrace tracer("IMA_HideKeyboard");
955 if (imeListener_ == nullptr) {
956 IMSA_HILOGE("imeListener_ is nullptr!");
957 return ErrorCode::ERROR_IME;
958 }
959 IMSA_HILOGD("IMA, trigger: %{public}d.", static_cast<int32_t>(trigger));
960 if (panels_.Contains(SOFT_KEYBOARD)) {
961 auto panel = GetSoftKeyboardPanel();
962 if (panel == nullptr) {
963 IMSA_HILOGE("panel is nullptr!");
964 return ErrorCode::ERROR_IME;
965 }
966 auto flag = panel->GetPanelFlag();
967 imeListener_->OnKeyboardStatus(false);
968 if (flag == FLG_CANDIDATE_COLUMN) {
969 IMSA_HILOGI("panel flag is candidate, no need to hide.");
970 return ErrorCode::NO_ERROR;
971 }
972 return HidePanel(panel, flag, trigger, isForce);
973 }
974 IMSA_HILOGI("panel is not created.");
975 imeListener_->OnKeyboardStatus(false);
976 auto channel = GetInputDataChannelProxy();
977 if (channel != nullptr) {
978 channel->SendKeyboardStatus(KeyboardStatus::HIDE);
979 }
980 auto controlChannel = GetInputControlChannel();
981 if (controlChannel != nullptr && trigger == Trigger::IME_APP) {
982 controlChannel->HideKeyboardSelf();
983 }
984 return ErrorCode::NO_ERROR;
985 }
986
GetSoftKeyboardPanel()987 std::shared_ptr<InputMethodPanel> InputMethodAbility::GetSoftKeyboardPanel()
988 {
989 auto result = panels_.Find(SOFT_KEYBOARD);
990 if (!result.first) {
991 return nullptr;
992 }
993 auto panel = result.second;
994 if (!BlockRetry(FIND_PANEL_RETRY_INTERVAL, MAX_RETRY_TIMES, [panel]() -> bool {
995 return panel != nullptr && panel->windowId_ != InputMethodPanel::INVALID_WINDOW_ID;
996 })) {
997 return nullptr;
998 }
999 return panel;
1000 }
1001
IsCurrentIme()1002 bool InputMethodAbility::IsCurrentIme()
1003 {
1004 IMSA_HILOGD("InputMethodAbility start.");
1005 if (isCurrentIme_) {
1006 return true;
1007 }
1008 std::lock_guard<std::mutex> lock(imeCheckMutex_);
1009 if (isCurrentIme_) {
1010 return true;
1011 }
1012 auto proxy = GetImsaProxy();
1013 if (proxy == nullptr) {
1014 IMSA_HILOGE("failed to get imsa proxy!");
1015 return false;
1016 }
1017 if (proxy->IsCurrentIme()) {
1018 isCurrentIme_ = true;
1019 return true;
1020 }
1021 return false;
1022 }
1023
IsDefaultIme()1024 bool InputMethodAbility::IsDefaultIme()
1025 {
1026 IMSA_HILOGD("InputMethodAbility start");
1027 if (isDefaultIme_) {
1028 return true;
1029 }
1030 std::lock_guard<std::mutex> lock(defaultImeCheckMutex_);
1031 if (isDefaultIme_) {
1032 return true;
1033 }
1034 auto proxy = GetImsaProxy();
1035 if (proxy == nullptr) {
1036 IMSA_HILOGE("failed to get imsa proxy!");
1037 return false;
1038 }
1039 auto ret = proxy->IsDefaultIme();
1040 if (ret == ErrorCode::NO_ERROR) {
1041 isDefaultIme_ = true;
1042 return true;
1043 }
1044 IMSA_HILOGE("call IsDefaultIme failed, ret: %{public}d!", ret);
1045 return false;
1046 }
1047
IsEnable()1048 bool InputMethodAbility::IsEnable()
1049 {
1050 if (imeListener_ == nullptr) {
1051 return false;
1052 }
1053 return imeListener_->IsEnable();
1054 }
1055
ExitCurrentInputType()1056 int32_t InputMethodAbility::ExitCurrentInputType()
1057 {
1058 IMSA_HILOGD("InputMethodAbility start.");
1059 ClearInputType();
1060 auto panel = GetSoftKeyboardPanel();
1061 if (panel != nullptr) {
1062 auto keyboardSize = panel->GetKeyboardSize();
1063 SysPanelStatus sysPanelStatus = { inputType_, panel->GetPanelFlag(), keyboardSize.width, keyboardSize.height };
1064 NotifyPanelStatus(panel, sysPanelStatus);
1065 }
1066 auto proxy = GetImsaProxy();
1067 if (proxy == nullptr) {
1068 IMSA_HILOGE("failed to get imsa proxy!");
1069 return false;
1070 }
1071 return proxy->ExitCurrentInputType();
1072 }
1073
ClearInputType()1074 void InputMethodAbility::ClearInputType()
1075 {
1076 std::lock_guard<std::mutex> lock(inputTypeLock_);
1077 inputType_ = InputType::NONE;
1078 }
1079
IsPanelShown(const PanelInfo &panelInfo, bool &isShown)1080 int32_t InputMethodAbility::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
1081 {
1082 isShown = false;
1083 auto result = panels_.Find(panelInfo.panelType);
1084 if (!result.first) {
1085 IMSA_HILOGI("panel type: %{public}d not found.", static_cast<int32_t>(panelInfo.panelType));
1086 return ErrorCode::NO_ERROR;
1087 }
1088 auto panel = result.second;
1089 if (panel->GetPanelType() == PanelType::SOFT_KEYBOARD && panel->GetPanelFlag() != panelInfo.panelFlag) {
1090 IMSA_HILOGI("queried flag: %{public}d, current flag: %{public}d, panel not found.",
1091 static_cast<int32_t>(panelInfo.panelFlag), static_cast<int32_t>(panel->GetPanelFlag()));
1092 return ErrorCode::NO_ERROR;
1093 }
1094 isShown = panel->IsShowing();
1095 IMSA_HILOGI("type: %{public}d, flag: %{public}d, result: %{public}d.", static_cast<int32_t>(panelInfo.panelType),
1096 static_cast<int32_t>(panelInfo.panelFlag), isShown);
1097 return ErrorCode::NO_ERROR;
1098 }
1099
OnClientInactive(const sptr<IRemoteObject> &channel)1100 void InputMethodAbility::OnClientInactive(const sptr<IRemoteObject> &channel)
1101 {
1102 IMSA_HILOGI("client inactive.");
1103 if (imeListener_ != nullptr) {
1104 imeListener_->OnInputFinish();
1105 }
1106 auto channelProxy = std::make_shared<InputDataChannelProxy>(channel);
1107 if (channelProxy == nullptr) {
1108 IMSA_HILOGE("failed to create channel proxy!");
1109 return;
1110 }
1111 auto panel = GetSoftKeyboardPanel();
1112 if (imeListener_ != nullptr && panel != nullptr && panel->GetPanelFlag() != PanelFlag::FLG_FIXED) {
1113 imeListener_->OnKeyboardStatus(false);
1114 }
1115 panels_.ForEach([this, &channelProxy](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
1116 if (panelType != PanelType::SOFT_KEYBOARD || panel->GetPanelFlag() != PanelFlag::FLG_FIXED) {
1117 auto ret = panel->HidePanel(false);
1118 if (ret != ErrorCode::NO_ERROR) {
1119 IMSA_HILOGE("failed, ret: %{public}d", ret);
1120 return false;
1121 }
1122 NotifyPanelStatusInfo({ { panel->GetPanelType(), panel->GetPanelFlag() }, false, Trigger::IME_APP },
1123 channelProxy);
1124 // finish previewing text when soft keyboard hides
1125 if (panel->GetPanelType() == PanelType::SOFT_KEYBOARD) {
1126 FinishTextPreview(true);
1127 }
1128 }
1129 return false;
1130 });
1131 ClearDataChannel(channel);
1132 }
1133
NotifyKeyboardHeight(uint32_t panelHeight, PanelFlag panelFlag)1134 void InputMethodAbility::NotifyKeyboardHeight(uint32_t panelHeight, PanelFlag panelFlag)
1135 {
1136 auto channel = GetInputDataChannelProxy();
1137 if (channel == nullptr) {
1138 IMSA_HILOGE("channel is nullptr!");
1139 return;
1140 }
1141 IMSA_HILOGD("notify panel height: %{public}u, flag: %{public}d.", panelHeight, static_cast<int32_t>(panelFlag));
1142 if (panelFlag != PanelFlag::FLG_FIXED) {
1143 channel->NotifyKeyboardHeight(0);
1144 return;
1145 }
1146 channel->NotifyKeyboardHeight(panelHeight);
1147 }
1148
SendPrivateCommand(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)1149 int32_t InputMethodAbility::SendPrivateCommand(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1150 {
1151 if (!IsDefaultIme()) {
1152 IMSA_HILOGE("current is not default ime!");
1153 return ErrorCode::ERROR_NOT_DEFAULT_IME;
1154 }
1155 if (!TextConfig::IsPrivateCommandValid(privateCommand)) {
1156 IMSA_HILOGE("privateCommand is limit 32KB, count limit 5!");
1157 return ErrorCode::ERROR_INVALID_PRIVATE_COMMAND_SIZE;
1158 }
1159 if (TextConfig::IsSystemPrivateCommand(privateCommand)) {
1160 auto systemChannel = GetSystemCmdChannelProxy();
1161 if (systemChannel == nullptr) {
1162 IMSA_HILOGE("channel is nullptr!");
1163 return ErrorCode::ERROR_SYSTEM_CMD_CHANNEL_ERROR;
1164 }
1165 return systemChannel->SendPrivateCommand(privateCommand);
1166 } else {
1167 auto channel = GetInputDataChannelProxy();
1168 if (channel == nullptr) {
1169 IMSA_HILOGE("channel is nullptr!");
1170 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1171 }
1172 return channel->SendPrivateCommand(privateCommand);
1173 }
1174 }
1175
ReceivePrivateCommand( const std::unordered_map<std::string, PrivateDataValue> &privateCommand)1176 int32_t InputMethodAbility::ReceivePrivateCommand(
1177 const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1178 {
1179 if (!IsDefaultIme()) {
1180 IMSA_HILOGE("current is not default ime!");
1181 return ErrorCode::ERROR_NOT_DEFAULT_IME;
1182 }
1183 if (imeListener_ == nullptr) {
1184 IMSA_HILOGE("imeListener is nullptr!");
1185 return ErrorCode::ERROR_IME;
1186 }
1187 imeListener_->ReceivePrivateCommand(privateCommand);
1188 return ErrorCode::NO_ERROR;
1189 }
1190
SetPreviewText(const std::string &text, const Range &range)1191 int32_t InputMethodAbility::SetPreviewText(const std::string &text, const Range &range)
1192 {
1193 InputMethodSyncTrace tracer("IMA_SetPreviewText");
1194 auto dataChannel = GetInputDataChannelProxy();
1195 if (dataChannel == nullptr) {
1196 IMSA_HILOGE("dataChannel is nullptr!");
1197 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1198 }
1199 return dataChannel->SetPreviewText(text, range);
1200 }
1201
FinishTextPreview(bool isAsync)1202 int32_t InputMethodAbility::FinishTextPreview(bool isAsync)
1203 {
1204 InputMethodSyncTrace tracer("IMA_FinishTextPreview");
1205 auto dataChannel = GetInputDataChannelProxy();
1206 if (dataChannel == nullptr) {
1207 IMSA_HILOGE("dataChannel is nullptr!");
1208 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1209 }
1210 return dataChannel->FinishTextPreview(isAsync);
1211 }
1212
GetCallingWindowInfo(CallingWindowInfo &windowInfo)1213 int32_t InputMethodAbility::GetCallingWindowInfo(CallingWindowInfo &windowInfo)
1214 {
1215 IMSA_HILOGD("IMA start.");
1216 auto channel = GetInputDataChannelProxy();
1217 if (channel == nullptr) {
1218 IMSA_HILOGE("channel is nullptr!");
1219 return ErrorCode::ERROR_CLIENT_NOT_FOUND;
1220 }
1221 auto panel = GetSoftKeyboardPanel();
1222 if (panel == nullptr) {
1223 IMSA_HILOGE("panel not found!");
1224 return ErrorCode::ERROR_PANEL_NOT_FOUND;
1225 }
1226 TextTotalConfig textConfig;
1227 int32_t ret = GetTextConfig(textConfig);
1228 if (ret != ErrorCode::NO_ERROR) {
1229 IMSA_HILOGE("failed to get window id, ret: %{public}d!", ret);
1230 return ErrorCode::ERROR_GET_TEXT_CONFIG;
1231 }
1232 ret = panel->SetCallingWindow(textConfig.windowId);
1233 if (ret != ErrorCode::NO_ERROR) {
1234 IMSA_HILOGE("failed to set calling window, ret: %{public}d!", ret);
1235 return ret;
1236 }
1237 ret = panel->GetCallingWindowInfo(windowInfo);
1238 if (ret != ErrorCode::NO_ERROR) {
1239 IMSA_HILOGE("failed to get calling window, ret: %{public}d", ret);
1240 }
1241 return ret;
1242 }
1243
NotifyPanelStatusInfo( const PanelStatusInfo &info, std::shared_ptr<InputDataChannelProxy> &channelProxy)1244 void InputMethodAbility::NotifyPanelStatusInfo(
1245 const PanelStatusInfo &info, std::shared_ptr<InputDataChannelProxy> &channelProxy)
1246 {
1247 // CANDIDATE_COLUMN not notify
1248 if (info.panelInfo.panelFlag == PanelFlag::FLG_CANDIDATE_COLUMN) {
1249 return;
1250 }
1251 if (channelProxy != nullptr) {
1252 channelProxy->NotifyPanelStatusInfo(info);
1253 }
1254
1255 auto controlChannel = GetInputControlChannel();
1256 if (controlChannel != nullptr && info.trigger == Trigger::IME_APP && !info.visible) {
1257 controlChannel->HideKeyboardSelf();
1258 }
1259 }
1260 } // namespace MiscServices
1261 } // namespace OHOS