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 "ima_hisysevent_reporter.h"
23 #include "input_method_agent_service_impl.h"
24 #include "input_method_core_service_impl.h"
25 #include "input_method_system_ability_proxy.h"
26 #include "input_method_utils.h"
27 #include "inputmethod_sysevent.h"
28 #include "inputmethod_trace.h"
29 #include "iservice_registry.h"
30 #include "itypes_util.h"
31 #include "message_parcel.h"
32 #include "on_demand_start_stop_sa.h"
33 #include "string_ex.h"
34 #include "sys/prctl.h"
35 #include "system_ability_definition.h"
36 #include "task_manager.h"
37 #include "tasks/task.h"
38 #include "tasks/task_imsa.h"
39 #include "input_method_tools.h"
40 #include "variant_util.h"
41
42 namespace OHOS {
43 namespace MiscServices {
44 using namespace MessageID;
45 using namespace std::chrono;
46 constexpr double INVALID_CURSOR_VALUE = -1.0;
47 constexpr int32_t INVALID_SELECTION_VALUE = -1;
48 constexpr uint32_t FIND_PANEL_RETRY_INTERVAL = 10;
49 constexpr uint32_t MAX_RETRY_TIMES = 100;
50 constexpr uint32_t START_INPUT_CALLBACK_TIMEOUT_MS = 1000;
51 constexpr uint32_t INVALID_SECURITY_MODE = -1;
52 constexpr uint32_t BASE_TEXT_OPERATION_TIMEOUT = 200;
53
InputMethodAbility()54 InputMethodAbility::InputMethodAbility()
55 {
56 Initialize();
57 }
58
~InputMethodAbility()59 InputMethodAbility::~InputMethodAbility()
60 {
61 IMSA_HILOGI("InputMethodAbility::~InputMethodAbility.");
62 }
63
GetInstance()64 InputMethodAbility &InputMethodAbility::GetInstance()
65 {
66 static InputMethodAbility instance;
67 return instance;
68 }
69
GetImsaProxy()70 sptr<IInputMethodSystemAbility> InputMethodAbility::GetImsaProxy()
71 {
72 std::lock_guard<std::mutex> lock(abilityLock_);
73 if (abilityManager_ != nullptr) {
74 return abilityManager_;
75 }
76 IMSA_HILOGI("InputMethodAbility get imsa proxy.");
77 auto systemAbility = OnDemandStartStopSa::GetInputMethodSystemAbility();
78 if (systemAbility == nullptr) {
79 IMSA_HILOGE("systemAbility is nullptr!");
80 return nullptr;
81 }
82 if (deathRecipient_ == nullptr) {
83 deathRecipient_ = new (std::nothrow) InputDeathRecipient();
84 if (deathRecipient_ == nullptr) {
85 IMSA_HILOGE("failed to new death recipient!");
86 return nullptr;
87 }
88 }
89 deathRecipient_->SetDeathRecipient([this](const wptr<IRemoteObject> &remote) {
90 OnRemoteSaDied(remote);
91 });
92 if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) {
93 IMSA_HILOGE("failed to add death recipient!");
94 return nullptr;
95 }
96 abilityManager_ = iface_cast<IInputMethodSystemAbility>(systemAbility);
97 return abilityManager_;
98 }
99
SetCoreAndAgent()100 int32_t InputMethodAbility::SetCoreAndAgent()
101 {
102 IMSA_HILOGD("InputMethodAbility, start.");
103 TaskManager::GetInstance().SetInited(true);
104
105 if (isBound_.load()) {
106 IMSA_HILOGD("already bound.");
107 return ErrorCode::NO_ERROR;
108 }
109 auto proxy = GetImsaProxy();
110 if (proxy == nullptr) {
111 IMSA_HILOGE("imsa proxy is nullptr!");
112 return ErrorCode::ERROR_NULL_POINTER;
113 }
114 int32_t ret = proxy->SetCoreAndAgent(coreStub_, agentStub_->AsObject());
115 if (ret != ErrorCode::NO_ERROR) {
116 IMSA_HILOGE("set failed, ret: %{public}d!", ret);
117 return ret;
118 }
119 isBound_.store(true);
120 IMSA_HILOGD("set successfully.");
121 return ErrorCode::NO_ERROR;
122 }
123
InitConnect()124 int32_t InputMethodAbility::InitConnect()
125 {
126 IMSA_HILOGD("InputMethodAbility, init connect.");
127 auto proxy = GetImsaProxy();
128 if (proxy == nullptr) {
129 IMSA_HILOGE("imsa proxy is nullptr!");
130 return ErrorCode::ERROR_NULL_POINTER;
131 }
132 int32_t ret = proxy->InitConnect();
133 if (ret != ErrorCode::NO_ERROR) {
134 IMSA_HILOGE("set failed, ret: %{public}d!", ret);
135 return ret;
136 }
137 return ErrorCode::NO_ERROR;
138 }
139
UnRegisteredProxyIme(UnRegisteredType type)140 int32_t InputMethodAbility::UnRegisteredProxyIme(UnRegisteredType type)
141 {
142 IMSA_HILOGD("type %{public}d", type);
143 isBound_.store(false);
144 auto proxy = GetImsaProxy();
145 if (proxy == nullptr) {
146 IMSA_HILOGE("imsa proxy is nullptr!");
147 return ErrorCode::ERROR_NULL_POINTER;
148 }
149 return proxy->UnRegisteredProxyIme(static_cast<int32_t>(type), coreStub_);
150 }
151
RegisterProxyIme(uint64_t displayId)152 int32_t InputMethodAbility::RegisterProxyIme(uint64_t displayId)
153 {
154 IMSA_HILOGD("IMA, displayId: %{public}" PRIu64 "", displayId);
155 TaskManager::GetInstance().SetInited(true);
156
157 if (isBound_.load()) {
158 IMSA_HILOGD("already bound.");
159 return ErrorCode::NO_ERROR;
160 }
161 auto proxy = GetImsaProxy();
162 if (proxy == nullptr) {
163 IMSA_HILOGE("imsa proxy is nullptr!");
164 return ErrorCode::ERROR_SERVICE_START_FAILED;
165 }
166 if (agentStub_ == nullptr) {
167 IMSA_HILOGE("agent nullptr");
168 return ErrorCode::ERROR_NULL_POINTER;
169 }
170 int32_t ret = displayId == DEFAULT_DISPLAY_ID
171 ? proxy->SetCoreAndAgent(coreStub_, agentStub_->AsObject())
172 : proxy->RegisterProxyIme(displayId, coreStub_, agentStub_->AsObject());
173 if (ret != ErrorCode::NO_ERROR) {
174 IMSA_HILOGE("failed, displayId: %{public}" PRIu64 ", ret: %{public}d!", displayId, ret);
175 return ret;
176 }
177 isBound_.store(true);
178 isProxyIme_.store(displayId != DEFAULT_DISPLAY_ID);
179 IMSA_HILOGD("set successfully, displayId: %{public}" PRIu64 "", displayId);
180 return ErrorCode::NO_ERROR;
181 }
182
UnregisterProxyIme(uint64_t displayId)183 int32_t InputMethodAbility::UnregisterProxyIme(uint64_t displayId)
184 {
185 isBound_.store(false);
186 isProxyIme_.store(false);
187 auto proxy = GetImsaProxy();
188 if (proxy == nullptr) {
189 IMSA_HILOGE("imsa proxy is nullptr!");
190 return ErrorCode::ERROR_SERVICE_START_FAILED;
191 }
192 return proxy->UnregisterProxyIme(displayId);
193 }
194
BindImeMirror()195 int32_t InputMethodAbility::BindImeMirror()
196 {
197 TaskManager::GetInstance().SetInited(true);
198
199 if (isBound_.load()) {
200 IMSA_HILOGD("[ImeMirrorTag]already bound.");
201 return ErrorCode::NO_ERROR;
202 }
203 auto proxy = GetImsaProxy();
204 if (proxy == nullptr) {
205 IMSA_HILOGE("[ImeMirrorTag]imsa proxy is nullptr!");
206 return ErrorCode::ERROR_SERVICE_START_FAILED;
207 }
208 if (agentStub_ == nullptr) {
209 IMSA_HILOGE("[ImeMirrorTag]agent nullptr");
210 return ErrorCode::ERROR_NULL_POINTER;
211 }
212
213 auto ret = proxy->BindImeMirror(coreStub_, agentStub_->AsObject());
214 if (ret != ErrorCode::NO_ERROR) {
215 IMSA_HILOGE("[ImeMirrorTag]failed, ret: %{public}d!", ret);
216 return ret;
217 }
218 IMSA_HILOGD("[ImeMirrorTag]register imsa start event");
219 imeMirrorMgr_.SubscribeSaStart(
220 [this]() {
221 if (!imeMirrorMgr_.IsImeMirrorEnable()) {
222 IMSA_HILOGI("[ImeMirrorTag]imsa started, no need resume ime mirror");
223 return;
224 }
225 IMSA_HILOGI("[ImeMirrorTag]imsa started, resume ime mirror");
226 BindImeMirror();
227 },
228 INPUT_METHOD_SYSTEM_ABILITY_ID);
229 isBound_.store(true);
230 imeMirrorMgr_.SetImeMirrorEnable(true);
231 IMSA_HILOGI("[ImeMirrorTag]set successfully");
232 return ErrorCode::NO_ERROR;
233 }
234
UnbindImeMirror()235 int32_t InputMethodAbility::UnbindImeMirror()
236 {
237 isBound_.store(false);
238 imeMirrorMgr_.SetImeMirrorEnable(false);
239 imeMirrorMgr_.UnSubscribeSaStart(INPUT_METHOD_SYSTEM_ABILITY_ID);
240 auto proxy = GetImsaProxy();
241 if (proxy == nullptr) {
242 IMSA_HILOGE("[ImeMirrorTag]imsa proxy is nullptr!");
243 return ErrorCode::ERROR_SERVICE_START_FAILED;
244 }
245 return proxy->UnbindImeMirror();
246 }
247
Initialize()248 void InputMethodAbility::Initialize()
249 {
250 IMSA_HILOGD("IMA init.");
251 sptr<InputMethodCoreStub> coreStub = new (std::nothrow) InputMethodCoreServiceImpl();
252 if (coreStub == nullptr) {
253 IMSA_HILOGE("failed to create core!");
254 return;
255 }
256 sptr<InputMethodAgentStub> agentStub = new (std::nothrow) InputMethodAgentServiceImpl();
257 if (agentStub == nullptr) {
258 IMSA_HILOGE("failed to create agent!");
259 return;
260 }
261 agentStub_ = agentStub;
262 coreStub_ = coreStub;
263 }
264
SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)265 void InputMethodAbility::SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)
266 {
267 IMSA_HILOGD("InputMethodAbility start.");
268 if (imeListener_ == nullptr) {
269 imeListener_ = std::move(imeListener);
270 }
271 }
272
GetImeListener()273 std::shared_ptr<InputMethodEngineListener> InputMethodAbility::GetImeListener()
274 {
275 return imeListener_;
276 }
277
SetKdListener(std::shared_ptr<KeyboardListener> kdListener)278 void InputMethodAbility::SetKdListener(std::shared_ptr<KeyboardListener> kdListener)
279 {
280 IMSA_HILOGD("InputMethodAbility start.");
281 if (kdListener_ == nullptr) {
282 kdListener_ = std::move(kdListener);
283 }
284 }
285
SetTextInputClientListener(std::shared_ptr<TextInputClientListener> textInputClientListener)286 void InputMethodAbility::SetTextInputClientListener(std::shared_ptr<TextInputClientListener> textInputClientListener)
287 {
288 IMSA_HILOGD("InputMethodAbility start.");
289 if (textInputClientListener_ == nullptr) {
290 textInputClientListener_ = std::move(textInputClientListener);
291 }
292 }
293
OnInitInputControlChannel(sptr<IRemoteObject> channelObj)294 void InputMethodAbility::OnInitInputControlChannel(sptr<IRemoteObject> channelObj)
295 {
296 IMSA_HILOGD("InputMethodAbility::OnInitInputControlChannel start.");
297 SetInputControlChannel(channelObj);
298 }
299
StartInputInner(const InputClientInfo & clientInfo,bool isBindFromClient)300 int32_t InputMethodAbility::StartInputInner(const InputClientInfo &clientInfo, bool isBindFromClient)
301 {
302 SetBindClientInfo(clientInfo);
303 if (clientInfo.channel == nullptr) {
304 IMSA_HILOGE("channelObject is nullptr!");
305 return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
306 }
307 IMSA_HILOGI("IMA showKeyboard:%{public}d,bindFromClient:%{public}d.", clientInfo.isShowKeyboard, isBindFromClient);
308 SetInputDataChannel(clientInfo.channel);
309 auto attribute = GetInputAttribute();
310 if ((clientInfo.needHide && !isProxyIme_.load()) ||
311 IsDisplayChanged(attribute.callingDisplayId, clientInfo.config.inputAttribute.callingDisplayId)) {
312 IMSA_HILOGD("pwd or normal input pattern changed, need hide panel first.");
313 auto panel = GetSoftKeyboardPanel();
314 if (panel != nullptr) {
315 panel->HidePanel();
316 }
317 }
318 int32_t ret = isBindFromClient
319 ? InvokeStartInputCallback(clientInfo.config, clientInfo.isNotifyInputStart)
320 : InvokeStartInputCallbackWithInfoRestruct(clientInfo.config, clientInfo.isNotifyInputStart);
321 if (ret != ErrorCode::NO_ERROR) {
322 IMSA_HILOGE("failed to invoke callback, ret: %{public}d!", ret);
323 return ret;
324 }
325 auto time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
326 auto showPanel = [&, needShow = clientInfo.isShowKeyboard, startTime = time] {
327 auto endTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
328 int32_t ret = ErrorCode::NO_ERROR;
329 if (needShow) {
330 ret = ShowKeyboardImplWithoutLock(cmdId_);
331 }
332 ReportImeStartInput(
333 static_cast<int32_t>(IInputMethodCoreIpcCode::COMMAND_START_INPUT), ret, needShow, endTime - startTime);
334 isImeTerminating_.store(false);
335 };
336 uint64_t seqId = Task::GetNextSeqId();
337 if (imeListener_ == nullptr ||
338 !imeListener_->PostTaskToEventHandler([seqId] { TaskManager::GetInstance().Complete(seqId); },
339 "task_manager_complete")) {
340 showPanel();
341 return ErrorCode::NO_ERROR;
342 }
343 TaskManager::GetInstance().WaitExec(seqId, START_INPUT_CALLBACK_TIMEOUT_MS, showPanel);
344 return ErrorCode::NO_ERROR;
345 }
346
IsDisplayChanged(uint64_t oldDisplayId,uint64_t newDisplayId)347 bool InputMethodAbility::IsDisplayChanged(uint64_t oldDisplayId, uint64_t newDisplayId)
348 {
349 if (oldDisplayId == newDisplayId) {
350 IMSA_HILOGD("screen not changed!");
351 return false;
352 }
353 auto proxy = GetImsaProxy();
354 if (proxy == nullptr) {
355 IMSA_HILOGE("imsa proxy is nullptr!");
356 return false;
357 }
358 bool ret = false;
359 int32_t result = proxy->IsRestrictedDefaultImeByDisplay(oldDisplayId, ret);
360 if (result != ErrorCode::NO_ERROR) {
361 IMSA_HILOGE("failed to get oldDisplay info , result : %{public}d !", result);
362 return false;
363 }
364 if (!ret) {
365 result = proxy->IsRestrictedDefaultImeByDisplay(newDisplayId, ret);
366 if (result != ErrorCode::NO_ERROR) {
367 IMSA_HILOGE("failed to get newDisplay info , result : %{public}d !", result);
368 return false;
369 }
370 }
371 return ret;
372 }
373
OnSetSubtype(SubProperty subProperty)374 void InputMethodAbility::OnSetSubtype(SubProperty subProperty)
375 {
376 if (imeListener_ != nullptr) {
377 imeListener_->OnSetSubtype(subProperty);
378 }
379 }
380
OnSetInputType(InputType inputType)381 void InputMethodAbility::OnSetInputType(InputType inputType)
382 {
383 inputType_ = inputType;
384 IMSA_HILOGD("OnSetInputType, inputType = %{public}d", static_cast<int32_t>(inputType));
385 NotifyPanelStatus(false);
386 }
387
GetInputType()388 InputType InputMethodAbility::GetInputType()
389 {
390 return inputType_;
391 }
392
ClearDataChannel(const sptr<IRemoteObject> & channel)393 void InputMethodAbility::ClearDataChannel(const sptr<IRemoteObject> &channel)
394 {
395 std::lock_guard<std::mutex> lock(dataChannelLock_);
396 if (dataChannelObject_ == nullptr || channel == nullptr) {
397 IMSA_HILOGD("dataChannelObject_ already nullptr.");
398 return;
399 }
400 if (dataChannelObject_.GetRefPtr() == channel.GetRefPtr()) {
401 dataChannelObject_ = nullptr;
402 if (dataChannelProxyWrap_ != nullptr) {
403 dataChannelProxyWrap_->ClearRspHandlers();
404 }
405 dataChannelProxyWrap_ = nullptr;
406 IMSA_HILOGD("end.");
407 }
408 }
409
StopInput(sptr<IRemoteObject> channelObject,uint32_t sessionId)410 int32_t InputMethodAbility::StopInput(sptr<IRemoteObject> channelObject, uint32_t sessionId)
411 {
412 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
413 int32_t cmdCount = ++cmdId_;
414 IMSA_HILOGI("IMA");
415 HideKeyboardImplWithoutLock(cmdCount, sessionId);
416 ClearBindInfo(channelObject);
417 ClearInputType();
418 if (imeListener_ != nullptr) {
419 imeListener_->OnInputFinish();
420 }
421 return ErrorCode::NO_ERROR;
422 }
423
ClearBindInfo(const sptr<IRemoteObject> & channel)424 void InputMethodAbility::ClearBindInfo(const sptr<IRemoteObject> &channel)
425 {
426 ClearDataChannel(channel);
427 ClearInputAttribute();
428 ClearAttachOptions();
429 ClearBindClientInfo();
430 }
431
DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent,uint64_t cbId,const sptr<IRemoteObject> & channelObject)432 int32_t InputMethodAbility::DispatchKeyEvent(
433 const std::shared_ptr<MMI::KeyEvent> &keyEvent, uint64_t cbId, const sptr<IRemoteObject> &channelObject)
434 {
435 if (keyEvent == nullptr) {
436 IMSA_HILOGE("keyEvent is nullptr!");
437 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
438 }
439 if (kdListener_ == nullptr) {
440 IMSA_HILOGE("kdListener_ is nullptr!");
441 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
442 }
443 IMSA_HILOGD("InputMethodAbility, start.");
444
445 if (!kdListener_->OnDealKeyEvent(keyEvent, cbId, channelObject)) {
446 IMSA_HILOGE("keyEvent not deal!");
447 return ErrorCode::ERROR_DISPATCH_KEY_EVENT;
448 }
449 return ErrorCode::NO_ERROR;
450 }
451
SetCallingWindow(uint32_t windowId)452 void InputMethodAbility::SetCallingWindow(uint32_t windowId)
453 {
454 IMSA_HILOGD("InputMethodAbility windowId: %{public}d.", windowId);
455 {
456 std::lock_guard<std::mutex> lock(inputAttrLock_);
457 inputAttribute_.windowId = windowId;
458 }
459 panels_.ForEach([windowId](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
460 panel->SetCallingWindow(windowId);
461 return false;
462 });
463 if (imeListener_ == nullptr) {
464 IMSA_HILOGD("imeListener_ is nullptr!");
465 return;
466 }
467 imeListener_->OnSetCallingWindow(windowId);
468 }
469
OnCursorUpdate(int32_t positionX,int32_t positionY,int32_t height)470 void InputMethodAbility::OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height)
471 {
472 if (kdListener_ == nullptr) {
473 IMSA_HILOGE("kdListener_ is nullptr!");
474 return;
475 }
476 IMSA_HILOGD("x: %{public}d, y: %{public}d, height: %{public}d.", positionX, positionY, height);
477 kdListener_->OnCursorUpdate(positionX, positionY, height);
478 }
479
OnSelectionChange(std::u16string text,int32_t oldBegin,int32_t oldEnd,int32_t newBegin,int32_t newEnd)480 void InputMethodAbility::OnSelectionChange(
481 std::u16string text, int32_t oldBegin, int32_t oldEnd, int32_t newBegin, int32_t newEnd)
482 {
483 if (kdListener_ == nullptr) {
484 IMSA_HILOGE("kdListener_ is nullptr!");
485 return;
486 }
487 kdListener_->OnTextChange(Str16ToStr8(text));
488 kdListener_->OnSelectionChange(oldBegin, oldEnd, newBegin, newEnd);
489 }
490
OnAttributeChange(InputAttribute attribute)491 void InputMethodAbility::OnAttributeChange(InputAttribute attribute)
492 {
493 if (kdListener_ == nullptr) {
494 IMSA_HILOGE("kdListener_ is nullptr!");
495 return;
496 }
497 IMSA_HILOGD("enterKeyType: %{public}d, inputPattern: %{public}d.", attribute.enterKeyType, attribute.inputPattern);
498 attribute.bundleName = GetInputAttribute().bundleName;
499 attribute.windowId = GetInputAttribute().windowId;
500 attribute.callingDisplayId = GetInputAttribute().callingDisplayId;
501 SetInputAttribute(attribute);
502 // add for mod inputPattern when panel show
503 NotifyPanelStatus(false);
504 kdListener_->OnEditorAttributeChange(attribute);
505 }
506
OnFunctionKey(int32_t funcKey)507 void InputMethodAbility::OnFunctionKey(int32_t funcKey)
508 {
509 if (kdListener_ == nullptr) {
510 IMSA_HILOGE("kdListener_ is nullptr!");
511 return;
512 }
513 kdListener_->OnFunctionKey(funcKey);
514 }
515
OnStopInputService(bool isTerminateIme)516 int32_t InputMethodAbility::OnStopInputService(bool isTerminateIme)
517 {
518 IMSA_HILOGI("isTerminateIme: %{public}d.", isTerminateIme);
519 isBound_.store(false);
520 auto imeListener = GetImeListener();
521 if (imeListener == nullptr) {
522 return ErrorCode::ERROR_IME_NOT_STARTED;
523 }
524 if (isTerminateIme) {
525 isImeTerminating_.store(true);
526 return imeListener->OnInputStop();
527 }
528 return ErrorCode::NO_ERROR;
529 }
530
OnDiscardTypingText()531 int32_t InputMethodAbility::OnDiscardTypingText()
532 {
533 auto imeListener = GetImeListener();
534 if (imeListener == nullptr) {
535 IMSA_HILOGE("imeListener is nullptr!");
536 return ErrorCode::ERROR_IME_NOT_STARTED;
537 }
538 return imeListener_->OnDiscardTypingText();
539 }
540
HideKeyboard()541 int32_t InputMethodAbility::HideKeyboard()
542 {
543 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
544 int32_t cmdCount = ++cmdId_;
545 return HideKeyboardImplWithoutLock(cmdCount, 0);
546 }
547
HideKeyboardImplWithoutLock(int32_t cmdId,uint32_t sessionId)548 int32_t InputMethodAbility::HideKeyboardImplWithoutLock(int32_t cmdId, uint32_t sessionId)
549 {
550 if (cmdId != cmdId_) {
551 IMSA_HILOGE("current is not last cmd cur: %{public}d, cmdId_: %{public}d!", cmdId, cmdId_);
552 return ErrorCode::NO_ERROR;
553 }
554 return HideKeyboard(Trigger::IMF, sessionId);
555 }
556
ShowKeyboard(int32_t requestKeyboardReason)557 int32_t InputMethodAbility::ShowKeyboard(int32_t requestKeyboardReason)
558 {
559 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
560 int32_t cmdCount = ++cmdId_;
561 HandleRequestKeyboardReasonChanged(static_cast<RequestKeyboardReason>(requestKeyboardReason));
562 return ShowKeyboardImplWithoutLock(cmdCount);
563 }
564
ShowKeyboardImplWithLock(int32_t cmdId)565 int32_t InputMethodAbility::ShowKeyboardImplWithLock(int32_t cmdId)
566 {
567 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
568 return ShowKeyboardImplWithoutLock(cmdId);
569 }
570
ShowKeyboardImplWithoutLock(int32_t cmdId)571 int32_t InputMethodAbility::ShowKeyboardImplWithoutLock(int32_t cmdId)
572 {
573 if (cmdId != cmdId_) {
574 IMSA_HILOGE("current is not last cmd cur: %{public}d, cmdId_: %{public}d!", cmdId, cmdId_);
575 return ErrorCode::NO_ERROR;
576 }
577 if (imeListener_ == nullptr) {
578 IMSA_HILOGE("imeListener is nullptr!");
579 return ErrorCode::ERROR_IME;
580 }
581 IMSA_HILOGI("IMA start.");
582 if (panels_.Contains(SOFT_KEYBOARD)) {
583 auto panel = GetSoftKeyboardPanel();
584 if (panel == nullptr) {
585 IMSA_HILOGE("panel is nullptr!");
586 return ErrorCode::ERROR_IME;
587 }
588 auto flag = panel->GetPanelFlag();
589 imeListener_->OnKeyboardStatus(true);
590 if (flag == FLG_CANDIDATE_COLUMN) {
591 IMSA_HILOGI("panel flag is candidate, no need to show.");
592 NotifyKeyboardHeight(0, flag);
593 return ErrorCode::NO_ERROR;
594 }
595 return ShowPanel(panel, flag, Trigger::IMF);
596 }
597 isShowAfterCreate_.store(true);
598 IMSA_HILOGI("panel not create.");
599 auto channel = GetInputDataChannelProxy();
600 if (channel != nullptr) {
601 channel->SendKeyboardStatus(static_cast<int32_t>(KeyboardStatus::SHOW));
602 }
603 imeListener_->OnKeyboardStatus(true);
604 return ErrorCode::NO_ERROR;
605 }
606
NotifyPanelStatusInfo(const PanelStatusInfo & info)607 void InputMethodAbility::NotifyPanelStatusInfo(const PanelStatusInfo &info)
608 {
609 // CANDIDATE_COLUMN not notify
610 auto channel = GetInputDataChannelProxy();
611 NotifyPanelStatusInfo(info, channel);
612 }
613
InvokeStartInputCallbackWithInfoRestruct(const TextTotalConfig & textConfig,bool isNotifyInputStart)614 int32_t InputMethodAbility::InvokeStartInputCallbackWithInfoRestruct(
615 const TextTotalConfig &textConfig, bool isNotifyInputStart)
616 {
617 TextTotalConfig newTextConfig = {};
618 int32_t ret = GetTextConfig(newTextConfig);
619 if (ret == ErrorCode::NO_ERROR) {
620 newTextConfig.inputAttribute.bundleName = textConfig.inputAttribute.bundleName;
621 newTextConfig.inputAttribute.callingDisplayId = textConfig.inputAttribute.callingDisplayId;
622 newTextConfig.inputAttribute.windowId = textConfig.inputAttribute.windowId;
623 newTextConfig.isSimpleKeyboardEnabled = textConfig.isSimpleKeyboardEnabled;
624 return InvokeStartInputCallback(newTextConfig, isNotifyInputStart);
625 }
626 IMSA_HILOGW("failed to get text config, ret: %{public}d.", ret);
627 if (imeListener_ == nullptr) {
628 IMSA_HILOGE("imeListener_ is nullptr!");
629 return ErrorCode::ERROR_IME;
630 }
631 if (isNotifyInputStart) {
632 imeListener_->OnInputStart();
633 }
634 return ErrorCode::NO_ERROR;
635 }
636
InvokeStartInputCallback(const TextTotalConfig & textConfig,bool isNotifyInputStart)637 int32_t InputMethodAbility::InvokeStartInputCallback(const TextTotalConfig &textConfig, bool isNotifyInputStart)
638 {
639 if (imeListener_ == nullptr) {
640 IMSA_HILOGE("imeListener_ is nullptr!");
641 return ErrorCode::ERROR_IME;
642 }
643 positionY_ = textConfig.positionY;
644 height_ = textConfig.height;
645 NotifyInfoToWmsInStartInput(textConfig);
646 SetInputAttribute(textConfig.inputAttribute);
647 if (kdListener_ != nullptr) {
648 kdListener_->OnEditorAttributeChange(textConfig.inputAttribute);
649 }
650 AttachOptions options;
651 options.requestKeyboardReason = textConfig.requestKeyboardReason;
652 options.isSimpleKeyboardEnabled = textConfig.isSimpleKeyboardEnabled;
653 InvokeAttachOptionsCallback(options, isNotifyInputStart || !isInputStartNotified_);
654 if (isNotifyInputStart || !isInputStartNotified_) {
655 isInputStartNotified_ = true;
656 IMSA_HILOGD("OnInputStart begin");
657 imeListener_->OnInputStart();
658 }
659 if (TextConfig::IsPrivateCommandValid(textConfig.privateCommand) && IsDefaultIme()) {
660 IMSA_HILOGD("notify privateCommand.");
661 imeListener_->ReceivePrivateCommand(textConfig.privateCommand);
662 }
663 if (kdListener_ != nullptr) {
664 if (textConfig.cursorInfo.left != INVALID_CURSOR_VALUE) {
665 kdListener_->OnCursorUpdate(
666 textConfig.cursorInfo.left, textConfig.cursorInfo.top, textConfig.cursorInfo.height);
667 }
668 if (textConfig.textSelection.newBegin == INVALID_SELECTION_VALUE ||
669 (textConfig.textSelection.newBegin == textConfig.textSelection.oldBegin &&
670 textConfig.textSelection.newEnd == textConfig.textSelection.oldEnd)) {
671 IMSA_HILOGD("invalid selection or no selection change");
672 } else {
673 kdListener_->OnSelectionChange(textConfig.textSelection.oldBegin, textConfig.textSelection.oldEnd,
674 textConfig.textSelection.newBegin, textConfig.textSelection.newEnd);
675 }
676 }
677 if (textConfig.windowId != INVALID_WINDOW_ID) {
678 imeListener_->OnSetCallingWindow(textConfig.windowId);
679 }
680 return ErrorCode::NO_ERROR;
681 }
682
HandleRequestKeyboardReasonChanged(const RequestKeyboardReason & requestKeyboardReason)683 void InputMethodAbility::HandleRequestKeyboardReasonChanged(const RequestKeyboardReason &requestKeyboardReason)
684 {
685 AttachOptions options;
686 options.requestKeyboardReason = requestKeyboardReason;
687 options.isSimpleKeyboardEnabled = GetAttachOptions().isSimpleKeyboardEnabled;
688 InvokeAttachOptionsCallback(options);
689 }
690
InvokeAttachOptionsCallback(const AttachOptions & options,bool isFirstNotify)691 void InputMethodAbility::InvokeAttachOptionsCallback(const AttachOptions &options, bool isFirstNotify)
692 {
693 auto oldOptions = GetAttachOptions();
694 if (!isFirstNotify && oldOptions.isSimpleKeyboardEnabled == options.isSimpleKeyboardEnabled
695 && options.requestKeyboardReason == oldOptions.requestKeyboardReason) {
696 return;
697 }
698 SetAttachOptions(options);
699 if (textInputClientListener_ != nullptr) {
700 textInputClientListener_->OnAttachOptionsChanged(options);
701 }
702 }
703
SetAttachOptions(const AttachOptions & options)704 void InputMethodAbility::SetAttachOptions(const AttachOptions &options)
705 {
706 std::lock_guard<std::mutex> lock(attachOptionsLock_);
707 attachOptions_ = options;
708 }
709
ClearAttachOptions()710 void InputMethodAbility::ClearAttachOptions()
711 {
712 std::lock_guard<std::mutex> lock(attachOptionsLock_);
713 attachOptions_ = {};
714 }
715
GetAttachOptions()716 AttachOptions InputMethodAbility::GetAttachOptions()
717 {
718 std::lock_guard<std::mutex> lock(attachOptionsLock_);
719 return attachOptions_;
720 }
721
InsertTextInner(const std::string & text,const AsyncIpcCallBack & callback)722 int32_t InputMethodAbility::InsertTextInner(const std::string &text, const AsyncIpcCallBack &callback)
723 {
724 InputMethodSyncTrace tracer("IMA_InsertText");
725 IMSA_HILOGD("InputMethodAbility start.");
726 auto channel = GetInputDataChannelProxyWrap();
727 if (channel == nullptr) {
728 IMSA_HILOGE("channel is nullptr!");
729 return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
730 }
731
732 return channel->InsertText(text, callback);
733 }
734
DeleteForwardInner(int32_t length,const AsyncIpcCallBack & callback)735 int32_t InputMethodAbility::DeleteForwardInner(int32_t length, const AsyncIpcCallBack &callback)
736 {
737 InputMethodSyncTrace tracer("IMA_DeleteForward");
738 IMSA_HILOGD("InputMethodAbility start, length: %{public}d.", length);
739 auto channel = GetInputDataChannelProxyWrap();
740 if (channel == nullptr) {
741 IMSA_HILOGE("channel is nullptr!");
742 return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
743 }
744 return channel->DeleteForward(length, callback);
745 }
746
DeleteBackwardInner(int32_t length,const AsyncIpcCallBack & callback)747 int32_t InputMethodAbility::DeleteBackwardInner(int32_t length, const AsyncIpcCallBack &callback)
748 {
749 IMSA_HILOGD("InputMethodAbility start, length: %{public}d.", length);
750 auto channel = GetInputDataChannelProxyWrap();
751 if (channel == nullptr) {
752 IMSA_HILOGE("channel is nullptr!");
753 return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
754 }
755 return channel->DeleteBackward(length, callback);
756 }
757
SendFunctionKey(int32_t funcKey,const AsyncIpcCallBack & callback)758 int32_t InputMethodAbility::SendFunctionKey(int32_t funcKey, const AsyncIpcCallBack &callback)
759 {
760 auto channel = GetInputDataChannelProxyWrap();
761 if (channel == nullptr) {
762 IMSA_HILOGE("channel is nullptr!");
763 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
764 }
765 return channel->SendFunctionKey(funcKey, callback);
766 }
767
HideKeyboardSelf()768 int32_t InputMethodAbility::HideKeyboardSelf()
769 {
770 // Current Ime is exiting, hide softkeyboard will cause the TextFiled to lose focus.
771 if (isImeTerminating_.load()) {
772 IMSA_HILOGI("Current Ime is terminating, no need to hide keyboard.");
773 return ErrorCode::NO_ERROR;
774 }
775 InputMethodSyncTrace tracer("IMA_HideKeyboardSelf start.");
776 auto ret = HideKeyboard(Trigger::IME_APP, 0);
777 if (ret == ErrorCode::NO_ERROR) {
778 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_SELF);
779 }
780 return ret == ErrorCode::ERROR_CLIENT_NULL_POINTER ? ret : ErrorCode::NO_ERROR;
781 }
782
SendExtendAction(int32_t action,const AsyncIpcCallBack & callback)783 int32_t InputMethodAbility::SendExtendAction(int32_t action, const AsyncIpcCallBack &callback)
784 {
785 IMSA_HILOGD("InputMethodAbility, action: %{public}d.", action);
786 auto channel = GetInputDataChannelProxyWrap();
787 if (channel == nullptr) {
788 IMSA_HILOGE("channel is nullptr!");
789 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
790 }
791 return channel->HandleExtendAction(action, callback);
792 }
793
GetTextBeforeCursorInner(int32_t number,std::u16string & text,const AsyncIpcCallBack & callback)794 int32_t InputMethodAbility::GetTextBeforeCursorInner(
795 int32_t number, std::u16string &text, const AsyncIpcCallBack &callback)
796 {
797 InputMethodSyncTrace tracer("IMA_GetForward");
798 IMSA_HILOGD("InputMethodAbility, number: %{public}d.", number);
799 auto channel = GetInputDataChannelProxyWrap();
800 if (channel == nullptr) {
801 IMSA_HILOGE("channel is nullptr!");
802 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
803 }
804 std::string textu8 = "";
805 auto ret = channel->GetTextBeforeCursor(number, textu8, callback);
806 text = Str8ToStr16(textu8);
807 return ret;
808 }
809
GetTextAfterCursorInner(int32_t number,std::u16string & text,const AsyncIpcCallBack & callback)810 int32_t InputMethodAbility::GetTextAfterCursorInner(
811 int32_t number, std::u16string &text, const AsyncIpcCallBack &callback)
812 {
813 InputMethodSyncTrace tracer("IMA_GetTextAfterCursor");
814 IMSA_HILOGD("InputMethodAbility, number: %{public}d.", number);
815 auto channel = GetInputDataChannelProxyWrap();
816 if (channel == nullptr) {
817 IMSA_HILOGE("channel is nullptr!");
818 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
819 }
820 std::string textu8 = "";
821 auto ret = channel->GetTextAfterCursor(number, textu8, callback);
822 text = Str8ToStr16(textu8);
823 return ret;
824 }
825
MoveCursor(int32_t keyCode,const AsyncIpcCallBack & callback)826 int32_t InputMethodAbility::MoveCursor(int32_t keyCode, const AsyncIpcCallBack &callback)
827 {
828 IMSA_HILOGD("InputMethodAbility, keyCode: %{public}d.", keyCode);
829 auto channel = GetInputDataChannelProxyWrap();
830 if (channel == nullptr) {
831 IMSA_HILOGE("channel is nullptr!");
832 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
833 }
834 return channel->MoveCursor(keyCode, callback);
835 }
836
SelectByRange(int32_t start,int32_t end,const AsyncIpcCallBack & callback)837 int32_t InputMethodAbility::SelectByRange(int32_t start, int32_t end, const AsyncIpcCallBack &callback)
838 {
839 IMSA_HILOGD("InputMethodAbility, start: %{public}d, end: %{public}d", start, end);
840 if (start < 0 || end < 0) {
841 IMSA_HILOGE("check parameter failed, start: %{public}d, end: %{public}d!", start, end);
842 return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
843 }
844 auto dataChannel = GetInputDataChannelProxyWrap();
845 if (dataChannel == nullptr) {
846 IMSA_HILOGE("datachannel is nullptr!");
847 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
848 }
849 return dataChannel->SelectByRange(start, end, callback);
850 }
851
SelectByMovement(int32_t direction,const AsyncIpcCallBack & callback)852 int32_t InputMethodAbility::SelectByMovement(int32_t direction, const AsyncIpcCallBack &callback)
853 {
854 IMSA_HILOGD("InputMethodAbility, direction: %{public}d.", direction);
855 auto dataChannel = GetInputDataChannelProxyWrap();
856 if (dataChannel == nullptr) {
857 IMSA_HILOGE("datachannel is nullptr!");
858 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
859 }
860 return dataChannel->SelectByMovement(direction, 0, callback);
861 }
862
GetEnterKeyType(int32_t & keyType)863 int32_t InputMethodAbility::GetEnterKeyType(int32_t &keyType)
864 {
865 IMSA_HILOGD("InputMethodAbility start.");
866 auto channel = GetInputDataChannelProxy();
867 if (channel == nullptr) {
868 IMSA_HILOGE("channel is nullptr!");
869 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
870 }
871 return channel->GetEnterKeyType(keyType);
872 }
873
GetInputPattern(int32_t & inputPattern)874 int32_t InputMethodAbility::GetInputPattern(int32_t &inputPattern)
875 {
876 IMSA_HILOGD("InputMethodAbility start.");
877 auto channel = GetInputDataChannelProxy();
878 if (channel == nullptr) {
879 IMSA_HILOGE("channel is nullptr!");
880 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
881 }
882 return channel->GetInputPattern(inputPattern);
883 }
884
GetTextIndexAtCursorInner(int32_t & index,const AsyncIpcCallBack & callback)885 int32_t InputMethodAbility::GetTextIndexAtCursorInner(int32_t &index, const AsyncIpcCallBack &callback)
886 {
887 IMSA_HILOGD("InputMethodAbility start.");
888 auto channel = GetInputDataChannelProxyWrap();
889 if (channel == nullptr) {
890 IMSA_HILOGE("channel is nullptr!");
891 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
892 }
893 return channel->GetTextIndexAtCursor(index, callback);
894 }
895
GetTextConfig(TextTotalConfig & textConfig)896 int32_t InputMethodAbility::GetTextConfig(TextTotalConfig &textConfig)
897 {
898 IMSA_HILOGD("InputMethodAbility start.");
899 auto channel = GetInputDataChannelProxy();
900 if (channel == nullptr) {
901 IMSA_HILOGE("channel is nullptr!");
902 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
903 }
904 TextTotalConfigInner textConfigInner = InputMethodTools::GetInstance().TextTotalConfigToInner(textConfig);
905 auto ret = channel->GetTextConfig(textConfigInner);
906 if (ret == ErrorCode::NO_ERROR) {
907 textConfig = InputMethodTools::GetInstance().InnerToTextTotalConfig(textConfigInner);
908 textConfig.inputAttribute.bundleName = GetInputAttribute().bundleName;
909 textConfig.inputAttribute.callingDisplayId = GetInputAttribute().callingDisplayId;
910 textConfig.inputAttribute.windowId = GetInputAttribute().windowId;
911 }
912 return ret;
913 }
914
SetInputDataChannel(const sptr<IRemoteObject> & object)915 void InputMethodAbility::SetInputDataChannel(const sptr<IRemoteObject> &object)
916 {
917 IMSA_HILOGD("SetInputDataChannel start.");
918 std::lock_guard<std::mutex> lock(dataChannelLock_);
919 if (dataChannelObject_ != nullptr && object != nullptr && object.GetRefPtr() == dataChannelObject_.GetRefPtr()) {
920 IMSA_HILOGD("datachannel has already been set.");
921 return;
922 }
923 auto channelProxy = std::make_shared<InputDataChannelProxy>(object);
924 if (channelProxy == nullptr) {
925 IMSA_HILOGE("failed to create channel proxy!");
926 return;
927 }
928 sptr<IRemoteObject> agentObject = nullptr;
929 if (agentStub_ != nullptr) {
930 agentObject = agentStub_->AsObject();
931 }
932 auto channelWrap = std::make_shared<InputDataChannelProxyWrap>(channelProxy, agentObject);
933 if (channelWrap == nullptr) {
934 IMSA_HILOGE("failed to create channel wrap!");
935 return;
936 }
937 if (dataChannelProxyWrap_ != nullptr) {
938 dataChannelProxyWrap_->ClearRspHandlers();
939 }
940 dataChannelProxyWrap_ = channelWrap;
941 dataChannelObject_ = object;
942 }
943
NotifyInfoToWmsInStartInput(const TextTotalConfig & textConfig)944 bool InputMethodAbility::NotifyInfoToWmsInStartInput(const TextTotalConfig &textConfig)
945 {
946 auto imeListener = GetImeListener();
947 if (imeListener == nullptr) {
948 IMSA_HILOGE("imeListener is nullptr!");
949 return false;
950 }
951 auto task = [this, textConfig]() {
952 panels_.ForEach([&textConfig](const PanelType &type, const std::shared_ptr<InputMethodPanel> &panel) {
953 if (panel == nullptr) {
954 return false;
955 }
956 if (type == SOFT_KEYBOARD && panel->GetPanelFlag() == FLG_FIXED && panel->IsShowing()) {
957 panel->SetTextFieldAvoidInfo(textConfig.positionY, textConfig.height);
958 }
959 panel->SetCallingWindow(textConfig.windowId);
960 return false;
961 });
962 };
963 return imeListener->PostTaskToEventHandler(task, "NotifyInfoToWms");
964 }
965
GetInputDataChannelProxyWrap()966 std::shared_ptr<InputDataChannelProxyWrap> InputMethodAbility::GetInputDataChannelProxyWrap()
967 {
968 if (imeMirrorMgr_.IsImeMirrorEnable()) {
969 IMSA_HILOGW("[ImeMirrorTag] not allow send to data channel");
970 return nullptr;
971 }
972 std::lock_guard<std::mutex> lock(dataChannelLock_);
973 return dataChannelProxyWrap_;
974 }
975
GetInputDataChannelProxy()976 std::shared_ptr<InputDataChannelProxy> InputMethodAbility::GetInputDataChannelProxy()
977 {
978 auto channel = GetInputDataChannelProxyWrap();
979 if (channel == nullptr) {
980 return nullptr;
981 }
982 return channel->GetDataChannel();
983 }
984
SetInputControlChannel(sptr<IRemoteObject> & object)985 void InputMethodAbility::SetInputControlChannel(sptr<IRemoteObject> &object)
986 {
987 IMSA_HILOGD("SetInputControlChannel start.");
988 std::lock_guard<std::mutex> lock(controlChannelLock_);
989 std::shared_ptr<InputControlChannelProxy> channelProxy = std::make_shared<InputControlChannelProxy>(object);
990 if (channelProxy == nullptr) {
991 IMSA_HILOGD("channelProxy is nullptr!");
992 return;
993 }
994 controlChannel_ = channelProxy;
995 }
996
ClearInputControlChannel()997 void InputMethodAbility::ClearInputControlChannel()
998 {
999 std::lock_guard<std::mutex> lock(controlChannelLock_);
1000 controlChannel_ = nullptr;
1001 }
1002
GetInputControlChannel()1003 std::shared_ptr<InputControlChannelProxy> InputMethodAbility::GetInputControlChannel()
1004 {
1005 std::lock_guard<std::mutex> lock(controlChannelLock_);
1006 return controlChannel_;
1007 }
1008
OnRemoteSaDied(const wptr<IRemoteObject> & object)1009 void InputMethodAbility::OnRemoteSaDied(const wptr<IRemoteObject> &object)
1010 {
1011 IMSA_HILOGI("input method service died.");
1012 isBound_.store(false);
1013 ClearDataChannel(dataChannelObject_);
1014 ClearInputControlChannel();
1015 ClearSystemCmdChannel();
1016 {
1017 std::lock_guard<std::mutex> lock(abilityLock_);
1018 abilityManager_ = nullptr;
1019 }
1020 if (imeListener_ != nullptr) {
1021 imeListener_->OnInputStop();
1022 }
1023 }
1024
GetSecurityMode(int32_t & security)1025 int32_t InputMethodAbility::GetSecurityMode(int32_t &security)
1026 {
1027 IMSA_HILOGI("InputMethodAbility start.");
1028 int32_t securityMode = securityMode_.load();
1029 if (securityMode != static_cast<int32_t>(INVALID_SECURITY_MODE)) {
1030 IMSA_HILOGD("Get cache security mode: %{public}d.", securityMode);
1031 security = securityMode;
1032 return ErrorCode::NO_ERROR;
1033 }
1034 auto proxy = GetImsaProxy();
1035 if (proxy == nullptr) {
1036 IMSA_HILOGE("Imsa proxy is nullptr!");
1037 return ErrorCode::ERROR_NULL_POINTER;
1038 }
1039 auto ret = proxy->GetSecurityMode(security);
1040 if (ret == ErrorCode::NO_ERROR) {
1041 securityMode_.store(security);
1042 }
1043 return ret;
1044 }
1045
ClearSystemCmdChannel()1046 void InputMethodAbility::ClearSystemCmdChannel()
1047 {
1048 std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
1049 if (systemCmdChannelProxy_ == nullptr) {
1050 IMSA_HILOGD("systemCmdChannelProxy_ already nullptr.");
1051 return;
1052 }
1053 systemCmdChannelProxy_ = nullptr;
1054 IMSA_HILOGD("end.");
1055 }
1056
GetSystemCmdChannelProxy()1057 sptr<SystemCmdChannelProxy> InputMethodAbility::GetSystemCmdChannelProxy()
1058 {
1059 std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
1060 return systemCmdChannelProxy_;
1061 }
1062
OnConnectSystemCmd(const sptr<IRemoteObject> & channel,sptr<IRemoteObject> & agent)1063 int32_t InputMethodAbility::OnConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)
1064 {
1065 IMSA_HILOGD("InputMethodAbility start.");
1066 sptr<InputMethodAgentServiceImpl> agentImpl = new (std::nothrow) InputMethodAgentServiceImpl();
1067 if (agentImpl == nullptr) {
1068 IMSA_HILOGE("failed to create agent!");
1069 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1070 }
1071 sptr<SystemCmdChannelProxy> cmdChannel = new (std::nothrow) SystemCmdChannelProxy(channel);
1072 if (cmdChannel == nullptr) {
1073 IMSA_HILOGE("failed to create channel proxy!");
1074 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1075 }
1076 {
1077 std::lock_guard<std::mutex> lock(systemCmdChannelLock_);
1078 systemCmdChannelProxy_ = cmdChannel;
1079 systemAgentStub_ = agentImpl;
1080 }
1081 agent = agentImpl->AsObject();
1082 auto panel = GetSoftKeyboardPanel();
1083 if (panel != nullptr) {
1084 auto flag = panel->GetPanelFlag();
1085 if (flag != FLG_CANDIDATE_COLUMN) {
1086 NotifyPanelStatus(false);
1087 }
1088 }
1089 return ErrorCode::NO_ERROR;
1090 }
1091
OnSecurityChange(int32_t security)1092 int32_t InputMethodAbility::OnSecurityChange(int32_t security)
1093 {
1094 IMSA_HILOGI("InputMethodAbility start.");
1095 securityMode_.store(security);
1096 if (imeListener_ == nullptr) {
1097 IMSA_HILOGE("imeListener_ is nullptr!");
1098 return ErrorCode::ERROR_BAD_PARAMETERS;
1099 }
1100 imeListener_->OnSecurityChange(security);
1101 return ErrorCode::NO_ERROR;
1102 }
1103
AdjustKeyboard()1104 int32_t InputMethodAbility::AdjustKeyboard()
1105 {
1106 if (panels_.Contains(SOFT_KEYBOARD)) {
1107 auto panel = GetSoftKeyboardPanel();
1108 if (panel == nullptr) {
1109 IMSA_HILOGE("panel is nullptr!");
1110 return ErrorCode::ERROR_IME;
1111 }
1112 auto flag = panel->GetPanelFlag();
1113 if (flag != FLG_FIXED) {
1114 IMSA_HILOGI("panel flag is not fix, no need to adjust.");
1115 return ErrorCode::NO_ERROR;
1116 }
1117 return panel->AdjustKeyboard();
1118 }
1119 return ErrorCode::NO_ERROR;
1120 }
1121
CreatePanel(const std::shared_ptr<AbilityRuntime::Context> & context,const PanelInfo & panelInfo,std::shared_ptr<InputMethodPanel> & inputMethodPanel)1122 int32_t InputMethodAbility::CreatePanel(const std::shared_ptr<AbilityRuntime::Context> &context,
1123 const PanelInfo &panelInfo, std::shared_ptr<InputMethodPanel> &inputMethodPanel)
1124 {
1125 IMSA_HILOGI("InputMethodAbility start.");
1126 auto panelHeightCallback = [this](uint32_t panelHeight, PanelFlag panelFlag) {
1127 NotifyKeyboardHeight(panelHeight, panelFlag);
1128 };
1129 auto flag = panels_.ComputeIfAbsent(panelInfo.panelType,
1130 [panelHeightCallback, &panelInfo, &context, &inputMethodPanel](
1131 const PanelType &panelType, std::shared_ptr<InputMethodPanel> &panel) {
1132 inputMethodPanel = std::make_shared<InputMethodPanel>();
1133 inputMethodPanel->SetPanelHeightCallback(panelHeightCallback);
1134 auto ret = inputMethodPanel->CreatePanel(context, panelInfo);
1135 if (ret == ErrorCode::NO_ERROR) {
1136 panel = inputMethodPanel;
1137 return true;
1138 }
1139 inputMethodPanel = nullptr;
1140 return false;
1141 });
1142 if (flag && isShowAfterCreate_.load() && panelInfo.panelType == SOFT_KEYBOARD
1143 && panelInfo.panelFlag != FLG_CANDIDATE_COLUMN) {
1144 isShowAfterCreate_.store(false);
1145 auto task = std::make_shared<TaskImsaShowKeyboard>();
1146 TaskManager::GetInstance().PostTask(task);
1147 }
1148 return flag ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL;
1149 }
1150
DestroyPanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel)1151 int32_t InputMethodAbility::DestroyPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
1152 {
1153 IMSA_HILOGI("InputMethodAbility start.");
1154 if (inputMethodPanel == nullptr) {
1155 IMSA_HILOGE("panel is nullptr!");
1156 return ErrorCode::ERROR_BAD_PARAMETERS;
1157 }
1158 auto ret = inputMethodPanel->DestroyPanel();
1159 if (ret == ErrorCode::NO_ERROR) {
1160 PanelType panelType = inputMethodPanel->GetPanelType();
1161 panels_.Erase(panelType);
1162 }
1163 return ret;
1164 }
1165
ShowPanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel)1166 int32_t InputMethodAbility::ShowPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
1167 {
1168 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
1169 if (inputMethodPanel == nullptr) {
1170 return ErrorCode::ERROR_BAD_PARAMETERS;
1171 }
1172 return ShowPanel(inputMethodPanel, inputMethodPanel->GetPanelFlag(), Trigger::IME_APP);
1173 }
1174
HidePanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel)1175 int32_t InputMethodAbility::HidePanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
1176 {
1177 if (inputMethodPanel == nullptr) {
1178 return ErrorCode::ERROR_BAD_PARAMETERS;
1179 }
1180 // Current Ime is exiting, hide softkeyboard will cause the TextFiled to lose focus.
1181 if (isImeTerminating_.load() && inputMethodPanel->GetPanelType() == PanelType::SOFT_KEYBOARD) {
1182 IMSA_HILOGI("Current Ime is terminating, no need to hide keyboard.");
1183 return ErrorCode::NO_ERROR;
1184 }
1185 if (isShowAfterCreate_.load() && inputMethodPanel->GetPanelType() == PanelType::SOFT_KEYBOARD
1186 && inputMethodPanel->GetPanelFlag() != PanelFlag::FLG_CANDIDATE_COLUMN) {
1187 isShowAfterCreate_.store(false);
1188 }
1189 std::lock_guard<std::recursive_mutex> lock(keyboardCmdLock_);
1190 return HidePanel(inputMethodPanel, inputMethodPanel->GetPanelFlag(), Trigger::IME_APP, 0);
1191 }
1192
ShowPanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel,PanelFlag flag,Trigger trigger)1193 int32_t InputMethodAbility::ShowPanel(
1194 const std::shared_ptr<InputMethodPanel> &inputMethodPanel, PanelFlag flag, Trigger trigger)
1195 {
1196 if (inputMethodPanel == nullptr) {
1197 return ErrorCode::ERROR_IMA_NULLPTR;
1198 }
1199 if (trigger == Trigger::IME_APP && GetInputDataChannelProxyWrap() == nullptr) {
1200 IMSA_HILOGE("channel is nullptr!");
1201 return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
1202 }
1203 if (flag == FLG_FIXED && inputMethodPanel->GetPanelType() == SOFT_KEYBOARD) {
1204 auto ret = inputMethodPanel->SetTextFieldAvoidInfo(positionY_, height_);
1205 if (ret != ErrorCode::NO_ERROR) {
1206 IMSA_HILOGE("failed to set keyBoard, ret: %{public}d!", ret);
1207 }
1208 }
1209 auto ret = inputMethodPanel->ShowPanel();
1210 if (ret == ErrorCode::NO_ERROR) {
1211 NotifyPanelStatus(false);
1212 PanelStatusInfo info;
1213 info.panelInfo.panelType = inputMethodPanel->GetPanelType();
1214 info.panelInfo.panelFlag = flag;
1215 info.visible = true;
1216 info.trigger = trigger;
1217 NotifyPanelStatusInfo(info);
1218 }
1219 return ret;
1220 }
1221
HidePanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel,PanelFlag flag,Trigger trigger,uint32_t sessionId)1222 int32_t InputMethodAbility::HidePanel(
1223 const std::shared_ptr<InputMethodPanel> &inputMethodPanel, PanelFlag flag, Trigger trigger, uint32_t sessionId)
1224 {
1225 if (inputMethodPanel == nullptr) {
1226 return ErrorCode::ERROR_BAD_PARAMETERS;
1227 }
1228 auto ret = inputMethodPanel->HidePanel();
1229 if (ret != ErrorCode::NO_ERROR) {
1230 IMSA_HILOGD("failed, ret: %{public}d", ret);
1231 return ret;
1232 }
1233 PanelStatusInfo info;
1234 info.panelInfo.panelType = inputMethodPanel->GetPanelType();
1235 info.panelInfo.panelFlag = flag;
1236 info.visible = false;
1237 info.trigger = trigger;
1238 info.sessionId = sessionId;
1239 NotifyPanelStatusInfo(info);
1240 if (trigger == Trigger::IMF && inputMethodPanel->GetPanelType() == PanelType::SOFT_KEYBOARD) {
1241 AsyncIpcCallBack callback = [](int32_t code, const ResponseData &data) {};
1242 FinishTextPreview(callback);
1243 }
1244 return ErrorCode::NO_ERROR;
1245 }
1246
NotifyPanelStatus(bool isUseParameterFlag,PanelFlag panelFlag)1247 int32_t InputMethodAbility::NotifyPanelStatus(bool isUseParameterFlag, PanelFlag panelFlag)
1248 {
1249 auto panel = GetSoftKeyboardPanel();
1250 if (panel == nullptr) {
1251 IMSA_HILOGE("panel is null");
1252 return ErrorCode::ERROR_NULL_POINTER;
1253 }
1254 auto keyboardSize = panel->GetKeyboardSize();
1255 PanelFlag curPanelFlag = isUseParameterFlag ? panelFlag : panel->GetPanelFlag();
1256 SysPanelStatus sysPanelStatus = { inputType_, curPanelFlag, keyboardSize.width, keyboardSize.height };
1257 if (!panel->IsInMainDisplay()) {
1258 sysPanelStatus.isPanelRaised = false;
1259 sysPanelStatus.needFuncButton = false;
1260 }
1261 if (GetAttachOptions().isSimpleKeyboardEnabled && IsDefaultIme() && !GetInputAttribute().IsOneTimeCodeFlag()) {
1262 sysPanelStatus.needFuncButton = false;
1263 }
1264 auto systemChannel = GetSystemCmdChannelProxy();
1265 if (systemChannel == nullptr) {
1266 IMSA_HILOGE("channel is nullptr!");
1267 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1268 }
1269 return systemChannel->NotifyPanelStatus(sysPanelStatus);
1270 }
1271
SetInputAttribute(const InputAttribute & inputAttribute)1272 void InputMethodAbility::SetInputAttribute(const InputAttribute &inputAttribute)
1273 {
1274 std::lock_guard<std::mutex> lock(inputAttrLock_);
1275 inputAttribute_ = inputAttribute;
1276 }
1277
ClearInputAttribute()1278 void InputMethodAbility::ClearInputAttribute()
1279 {
1280 std::lock_guard<std::mutex> lock(inputAttrLock_);
1281 inputAttribute_ = {};
1282 }
1283
GetInputAttribute()1284 InputAttribute InputMethodAbility::GetInputAttribute()
1285 {
1286 std::lock_guard<std::mutex> lock(inputAttrLock_);
1287 return inputAttribute_;
1288 }
1289
HideKeyboard(Trigger trigger,uint32_t sessionId)1290 int32_t InputMethodAbility::HideKeyboard(Trigger trigger, uint32_t sessionId)
1291 {
1292 isShowAfterCreate_.store(false);
1293 InputMethodSyncTrace tracer("IMA_HideKeyboard");
1294 if (imeListener_ == nullptr) {
1295 IMSA_HILOGE("imeListener_ is nullptr!");
1296 return ErrorCode::ERROR_IME;
1297 }
1298 IMSA_HILOGD("IMA, trigger: %{public}d.", static_cast<int32_t>(trigger));
1299 if (panels_.Contains(SOFT_KEYBOARD)) {
1300 auto panel = GetSoftKeyboardPanel();
1301 if (panel == nullptr) {
1302 IMSA_HILOGE("panel is nullptr!");
1303 return ErrorCode::ERROR_IME;
1304 }
1305 auto flag = panel->GetPanelFlag();
1306 imeListener_->OnKeyboardStatus(false);
1307 if (flag == FLG_CANDIDATE_COLUMN) {
1308 IMSA_HILOGI("panel flag is candidate, no need to hide.");
1309 return ErrorCode::NO_ERROR;
1310 }
1311 return HidePanel(panel, flag, trigger, sessionId);
1312 }
1313 IMSA_HILOGI("panel is not created.");
1314 imeListener_->OnKeyboardStatus(false);
1315 auto channel = GetInputDataChannelProxy();
1316 if (channel != nullptr) {
1317 channel->SendKeyboardStatus(static_cast<int32_t>(KeyboardStatus::HIDE));
1318 }
1319 auto controlChannel = GetInputControlChannel();
1320 if (controlChannel != nullptr && trigger == Trigger::IME_APP) {
1321 controlChannel->HideKeyboardSelf();
1322 }
1323 return ErrorCode::NO_ERROR;
1324 }
1325
GetSoftKeyboardPanel()1326 std::shared_ptr<InputMethodPanel> InputMethodAbility::GetSoftKeyboardPanel()
1327 {
1328 auto result = panels_.Find(SOFT_KEYBOARD);
1329 if (!result.first) {
1330 return nullptr;
1331 }
1332 auto panel = result.second;
1333 if (!BlockRetry(FIND_PANEL_RETRY_INTERVAL, MAX_RETRY_TIMES, [panel]() -> bool {
1334 return panel != nullptr && panel->windowId_ != InputMethodPanel::INVALID_WINDOW_ID;
1335 })) {
1336 return nullptr;
1337 }
1338 return panel;
1339 }
1340
IsCurrentIme()1341 bool InputMethodAbility::IsCurrentIme()
1342 {
1343 IMSA_HILOGD("InputMethodAbility start.");
1344 if (isCurrentIme_) {
1345 return true;
1346 }
1347 std::lock_guard<std::mutex> lock(imeCheckMutex_);
1348 if (isCurrentIme_) {
1349 return true;
1350 }
1351 auto proxy = GetImsaProxy();
1352 if (proxy == nullptr) {
1353 IMSA_HILOGE("failed to get imsa proxy!");
1354 return false;
1355 }
1356
1357 bool ret = false;
1358 proxy->IsCurrentIme(ret);
1359 if (ret) {
1360 isCurrentIme_ = true;
1361 }
1362 return ret;
1363 }
1364
IsDefaultIme()1365 bool InputMethodAbility::IsDefaultIme()
1366 {
1367 IMSA_HILOGD("InputMethodAbility start");
1368 if (isDefaultIme_) {
1369 return true;
1370 }
1371 std::lock_guard<std::mutex> lock(defaultImeCheckMutex_);
1372 if (isDefaultIme_) {
1373 return true;
1374 }
1375 auto proxy = GetImsaProxy();
1376 if (proxy == nullptr) {
1377 IMSA_HILOGE("failed to get imsa proxy!");
1378 return false;
1379 }
1380 auto ret = proxy->IsDefaultIme();
1381 if (ret == ErrorCode::NO_ERROR) {
1382 isDefaultIme_ = true;
1383 return true;
1384 }
1385 IMSA_HILOGE("call IsDefaultIme failed, ret: %{public}d!", ret);
1386 return false;
1387 }
1388
IsEnable()1389 bool InputMethodAbility::IsEnable()
1390 {
1391 if (imeListener_ == nullptr) {
1392 return false;
1393 }
1394 return imeListener_->IsEnable();
1395 }
1396
IsCallbackRegistered(const std::string & type)1397 bool InputMethodAbility::IsCallbackRegistered(const std::string &type)
1398 {
1399 if (imeListener_ == nullptr) {
1400 return false;
1401 }
1402 return imeListener_->IsCallbackRegistered(type);
1403 }
1404
IsSystemApp()1405 bool InputMethodAbility::IsSystemApp()
1406 {
1407 IMSA_HILOGD("InputMethodAbility start");
1408 if (isSystemApp_) {
1409 return true;
1410 }
1411 std::lock_guard<std::mutex> lock(systemAppCheckMutex_);
1412 if (isSystemApp_) {
1413 return true;
1414 }
1415 auto proxy = GetImsaProxy();
1416 if (proxy == nullptr) {
1417 IMSA_HILOGE("failed to get imsa proxy!");
1418 return false;
1419 }
1420 bool ret = false;
1421 proxy->IsSystemApp(ret);
1422 if (ret) {
1423 isSystemApp_ = true;
1424 }
1425 return ret;
1426 }
1427
ExitCurrentInputType()1428 int32_t InputMethodAbility::ExitCurrentInputType()
1429 {
1430 IMSA_HILOGD("InputMethodAbility start.");
1431 ClearInputType();
1432 auto proxy = GetImsaProxy();
1433 if (proxy == nullptr) {
1434 IMSA_HILOGE("failed to get imsa proxy!");
1435 return false;
1436 }
1437 auto ret = proxy->ExitCurrentInputType();
1438 if (ret == ErrorCode::NO_ERROR) {
1439 NotifyPanelStatus(false);
1440 }
1441 return ret;
1442 }
1443
ClearInputType()1444 void InputMethodAbility::ClearInputType()
1445 {
1446 std::lock_guard<std::mutex> lock(inputTypeLock_);
1447 if (inputType_ != InputType::SECURITY_INPUT) {
1448 inputType_ = InputType::NONE;
1449 }
1450 }
1451
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)1452 int32_t InputMethodAbility::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
1453 {
1454 isShown = false;
1455 auto result = panels_.Find(panelInfo.panelType);
1456 if (!result.first) {
1457 IMSA_HILOGI("panel type: %{public}d not found.", static_cast<int32_t>(panelInfo.panelType));
1458 return ErrorCode::NO_ERROR;
1459 }
1460 auto panel = result.second;
1461 if (panel->GetPanelType() == PanelType::SOFT_KEYBOARD && panel->GetPanelFlag() != panelInfo.panelFlag) {
1462 IMSA_HILOGI("queried flag: %{public}d, current flag: %{public}d, panel not found.",
1463 static_cast<int32_t>(panelInfo.panelFlag), static_cast<int32_t>(panel->GetPanelFlag()));
1464 return ErrorCode::NO_ERROR;
1465 }
1466 isShown = panel->IsShowing();
1467 IMSA_HILOGI("type: %{public}d, flag: %{public}d, result: %{public}d.", static_cast<int32_t>(panelInfo.panelType),
1468 static_cast<int32_t>(panelInfo.panelFlag), isShown);
1469 return ErrorCode::NO_ERROR;
1470 }
1471
OnClientInactive(const sptr<IRemoteObject> & channel)1472 void InputMethodAbility::OnClientInactive(const sptr<IRemoteObject> &channel)
1473 {
1474 IMSA_HILOGI("client inactive.");
1475 if (imeListener_ != nullptr) {
1476 imeListener_->OnInputFinish();
1477 }
1478 auto channelProxy = std::make_shared<InputDataChannelProxy>(channel);
1479 if (channelProxy == nullptr) {
1480 IMSA_HILOGE("failed to create channel proxy!");
1481 return;
1482 }
1483 auto panel = GetSoftKeyboardPanel();
1484 if (imeListener_ != nullptr && panel != nullptr && panel->GetPanelFlag() != PanelFlag::FLG_FIXED) {
1485 imeListener_->OnKeyboardStatus(false);
1486 }
1487 panels_.ForEach([this, &channelProxy](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
1488 if (panelType == PanelType::SOFT_KEYBOARD && panel->GetPanelFlag() == PanelFlag::FLG_FIXED) {
1489 return false;
1490 }
1491 auto ret = panel->HidePanel();
1492 if (ret != ErrorCode::NO_ERROR) {
1493 IMSA_HILOGE("failed, ret: %{public}d", ret);
1494 return false;
1495 }
1496 PanelStatusInfo info;
1497 info.panelInfo.panelType = panel->GetPanelType();
1498 info.panelInfo.panelFlag = panel->GetPanelFlag();
1499 info.visible = false;
1500 info.trigger = Trigger::IME_APP;
1501 NotifyPanelStatusInfo(info, channelProxy);
1502 // finish previewing text when soft keyboard hides
1503 if (panel->GetPanelType() == PanelType::SOFT_KEYBOARD) {
1504 AsyncIpcCallBack callback = [](int32_t code, const ResponseData &data) {};
1505 FinishTextPreview(callback);
1506 }
1507 return false;
1508 });
1509 // cannot clear inputAttribute, otherwise it will affect hicar
1510 ClearDataChannel(channel);
1511 ClearAttachOptions();
1512 ClearBindClientInfo();
1513 }
1514
NotifyKeyboardHeight(uint32_t panelHeight,PanelFlag panelFlag)1515 void InputMethodAbility::NotifyKeyboardHeight(uint32_t panelHeight, PanelFlag panelFlag)
1516 {
1517 auto channel = GetInputDataChannelProxy();
1518 if (channel == nullptr) {
1519 IMSA_HILOGE("channel is nullptr!");
1520 return;
1521 }
1522 IMSA_HILOGD("notify panel height: %{public}u, flag: %{public}d.", panelHeight, static_cast<int32_t>(panelFlag));
1523 if (panelFlag != PanelFlag::FLG_FIXED) {
1524 channel->NotifyKeyboardHeight(0);
1525 return;
1526 }
1527 channel->NotifyKeyboardHeight(panelHeight);
1528 }
1529
SendPrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1530 int32_t InputMethodAbility::SendPrivateCommand(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1531 {
1532 if (!IsDefaultIme()) {
1533 IMSA_HILOGE("current is not default ime!");
1534 return ErrorCode::ERROR_NOT_DEFAULT_IME;
1535 }
1536 if (!TextConfig::IsPrivateCommandValid(privateCommand)) {
1537 IMSA_HILOGE("privateCommand is limit 32KB, count limit 5!");
1538 return ErrorCode::ERROR_INVALID_PRIVATE_COMMAND_SIZE;
1539 }
1540 if (TextConfig::IsSystemPrivateCommand(privateCommand)) {
1541 auto systemChannel = GetSystemCmdChannelProxy();
1542 if (systemChannel == nullptr) {
1543 IMSA_HILOGE("channel is nullptr!");
1544 return ErrorCode::ERROR_SYSTEM_CMD_CHANNEL_ERROR;
1545 }
1546 Value commandValueMap(privateCommand);
1547 return systemChannel->SendPrivateCommand(commandValueMap);
1548 } else {
1549 auto channel = GetInputDataChannelProxy();
1550 if (channel == nullptr) {
1551 IMSA_HILOGE("channel is nullptr!");
1552 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1553 }
1554 Value commandValueMap(privateCommand);
1555 return channel->SendPrivateCommand(commandValueMap);
1556 }
1557 }
1558
ReceivePrivateCommand(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1559 int32_t InputMethodAbility::ReceivePrivateCommand(
1560 const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1561 {
1562 if (imeListener_ == nullptr) {
1563 IMSA_HILOGE("imeListener is nullptr!");
1564 return ErrorCode::ERROR_IME;
1565 }
1566 imeListener_->ReceivePrivateCommand(privateCommand);
1567 return ErrorCode::NO_ERROR;
1568 }
1569
SetPreviewTextInner(const std::string & text,const Range & range,const AsyncIpcCallBack & callback)1570 int32_t InputMethodAbility::SetPreviewTextInner(
1571 const std::string &text, const Range &range, const AsyncIpcCallBack &callback)
1572 {
1573 InputMethodSyncTrace tracer("IMA_SetPreviewText");
1574 auto dataChannel = GetInputDataChannelProxyWrap();
1575 if (dataChannel == nullptr) {
1576 IMSA_HILOGE("dataChannel is nullptr!");
1577 return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
1578 }
1579 RangeInner rangeInner = InputMethodTools::GetInstance().RangeToInner(range);
1580 return dataChannel->SetPreviewText(text, rangeInner, callback);
1581 }
1582
FinishTextPreviewInner(const AsyncIpcCallBack & callback)1583 int32_t InputMethodAbility::FinishTextPreviewInner(const AsyncIpcCallBack &callback)
1584 {
1585 InputMethodSyncTrace tracer("IMA_FinishTextPreview");
1586 auto dataChannel = GetInputDataChannelProxyWrap();
1587 if (dataChannel == nullptr) {
1588 IMSA_HILOGE("dataChannel is nullptr!");
1589 return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
1590 }
1591 return dataChannel->FinishTextPreview(callback);
1592 }
1593
GetCallingWindowInfo(CallingWindowInfo & windowInfo)1594 int32_t InputMethodAbility::GetCallingWindowInfo(CallingWindowInfo &windowInfo)
1595 {
1596 IMSA_HILOGD("IMA start.");
1597 auto channel = GetInputDataChannelProxy();
1598 if (channel == nullptr) {
1599 IMSA_HILOGE("channel is nullptr!");
1600 return ErrorCode::ERROR_CLIENT_NOT_FOUND;
1601 }
1602 auto panel = GetSoftKeyboardPanel();
1603 if (panel == nullptr) {
1604 IMSA_HILOGE("panel not found!");
1605 return ErrorCode::ERROR_PANEL_NOT_FOUND;
1606 }
1607 TextTotalConfig textConfig;
1608 int32_t ret = GetTextConfig(textConfig);
1609 if (ret != ErrorCode::NO_ERROR) {
1610 IMSA_HILOGE("failed to get window id, ret: %{public}d!", ret);
1611 return ErrorCode::ERROR_GET_TEXT_CONFIG;
1612 }
1613 ret = panel->SetCallingWindow(textConfig.windowId);
1614 if (ret != ErrorCode::NO_ERROR) {
1615 IMSA_HILOGE("failed to set calling window, ret: %{public}d!", ret);
1616 return ret;
1617 }
1618 ret = panel->GetCallingWindowInfo(windowInfo);
1619 if (ret != ErrorCode::NO_ERROR) {
1620 IMSA_HILOGE("failed to get calling window, ret: %{public}d", ret);
1621 }
1622 return ret;
1623 }
1624
NotifyPanelStatusInfo(const PanelStatusInfo & info,std::shared_ptr<InputDataChannelProxy> & channelProxy)1625 void InputMethodAbility::NotifyPanelStatusInfo(
1626 const PanelStatusInfo &info, std::shared_ptr<InputDataChannelProxy> &channelProxy)
1627 {
1628 // CANDIDATE_COLUMN not notify
1629 if (info.panelInfo.panelFlag == PanelFlag::FLG_CANDIDATE_COLUMN) {
1630 return;
1631 }
1632 if (channelProxy != nullptr) {
1633 PanelStatusInfoInner inner = InputMethodTools::GetInstance().PanelStatusInfoToInner(info);
1634 channelProxy->NotifyPanelStatusInfo(inner);
1635 }
1636
1637 auto controlChannel = GetInputControlChannel();
1638 if (controlChannel != nullptr && info.trigger == Trigger::IME_APP && !info.visible && !isImeTerminating_.load()) {
1639 controlChannel->HideKeyboardSelf();
1640 }
1641 }
1642
SendMessage(const ArrayBuffer & arrayBuffer)1643 int32_t InputMethodAbility::SendMessage(const ArrayBuffer &arrayBuffer)
1644 {
1645 int32_t securityMode = INVALID_SECURITY_MODE;
1646 auto ret = GetSecurityMode(securityMode);
1647 if (ret != ErrorCode::NO_ERROR) {
1648 IMSA_HILOGE("Get security mode failed!");
1649 return ret;
1650 }
1651 if (!ArrayBuffer::IsSizeValid(arrayBuffer)) {
1652 IMSA_HILOGE("arrayBuffer size is invalid!");
1653 return ErrorCode::ERROR_INVALID_ARRAY_BUFFER_SIZE;
1654 }
1655 if (securityMode != static_cast<int32_t>(SecurityMode::FULL)) {
1656 IMSA_HILOGE("Security mode must be FULL!.");
1657 return ErrorCode::ERROR_SECURITY_MODE_OFF;
1658 }
1659 auto dataChannel = GetInputDataChannelProxy();
1660 if (dataChannel == nullptr) {
1661 IMSA_HILOGE("datachannel is nullptr.");
1662 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
1663 }
1664 return dataChannel->SendMessage(arrayBuffer);
1665 }
1666
RecvMessage(const ArrayBuffer & arrayBuffer)1667 int32_t InputMethodAbility::RecvMessage(const ArrayBuffer &arrayBuffer)
1668 {
1669 int32_t securityMode = -1;
1670 auto ret = GetSecurityMode(securityMode);
1671 if (ret != ErrorCode::NO_ERROR) {
1672 IMSA_HILOGE("Get security mode failed!");
1673 return ret;
1674 }
1675 if (securityMode != static_cast<int32_t>(SecurityMode::FULL)) {
1676 IMSA_HILOGE("Security mode must be FULL!.");
1677 return ErrorCode::ERROR_SECURITY_MODE_OFF;
1678 }
1679 auto msgHandlerCallback = GetMsgHandlerCallback();
1680 if (msgHandlerCallback == nullptr) {
1681 IMSA_HILOGW("Message handler was not regist!");
1682 return ErrorCode::ERROR_MSG_HANDLER_NOT_REGIST;
1683 }
1684 return msgHandlerCallback->OnMessage(arrayBuffer);
1685 }
1686
RegisterMsgHandler(const std::shared_ptr<MsgHandlerCallbackInterface> & msgHandler)1687 int32_t InputMethodAbility::RegisterMsgHandler(const std::shared_ptr<MsgHandlerCallbackInterface> &msgHandler)
1688 {
1689 IMSA_HILOGI("isRegist: %{public}d", msgHandler != nullptr);
1690 std::shared_ptr<MsgHandlerCallbackInterface> exMsgHandler = nullptr;
1691 {
1692 std::lock_guard<decltype(msgHandlerMutex_)> lock(msgHandlerMutex_);
1693 exMsgHandler = msgHandler_;
1694 msgHandler_ = msgHandler;
1695 }
1696 if (exMsgHandler != nullptr) {
1697 IMSA_HILOGI("Trigger exMessageHandler OnTerminated.");
1698 exMsgHandler->OnTerminated();
1699 }
1700 return ErrorCode::NO_ERROR;
1701 }
1702
GetMsgHandlerCallback()1703 std::shared_ptr<MsgHandlerCallbackInterface> InputMethodAbility::GetMsgHandlerCallback()
1704 {
1705 std::lock_guard<decltype(msgHandlerMutex_)> lock(msgHandlerMutex_);
1706 return msgHandler_;
1707 }
1708
StartInput(const InputClientInfo & clientInfo,bool isBindFromClient)1709 int32_t InputMethodAbility::StartInput(const InputClientInfo &clientInfo, bool isBindFromClient)
1710 {
1711 auto ret = StartInputInner(clientInfo, isBindFromClient);
1712 if (ret == ErrorCode::NO_ERROR) {
1713 return ret;
1714 }
1715 ReportImeStartInput(static_cast<int32_t>(IInputMethodCoreIpcCode::COMMAND_START_INPUT),
1716 ret, clientInfo.isShowKeyboard);
1717 return ret;
1718 }
1719
InsertText(const std::string & text,const AsyncIpcCallBack & callback)1720 int32_t InputMethodAbility::InsertText(const std::string &text, const AsyncIpcCallBack &callback)
1721 {
1722 int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1723 auto ret = InsertTextInner(text, callback);
1724 int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1725 ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_INSERT_TEXT), ret, end - start);
1726 return ret;
1727 }
1728
DeleteForward(int32_t length,const AsyncIpcCallBack & callback)1729 int32_t InputMethodAbility::DeleteForward(int32_t length, const AsyncIpcCallBack &callback)
1730 {
1731 int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1732 auto ret = DeleteForwardInner(length, callback);
1733 int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1734 ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_DELETE_FORWARD), ret, end - start);
1735 return ret;
1736 }
1737
DeleteBackward(int32_t length,const AsyncIpcCallBack & callback)1738 int32_t InputMethodAbility::DeleteBackward(int32_t length, const AsyncIpcCallBack &callback)
1739 {
1740 int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1741 auto ret = DeleteBackwardInner(length, callback);
1742 int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1743 ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_DELETE_BACKWARD), ret, end - start);
1744 return ret;
1745 }
1746
SetPreviewText(const std::string & text,const Range & range,const AsyncIpcCallBack & callback)1747 int32_t InputMethodAbility::SetPreviewText(
1748 const std::string &text, const Range &range, const AsyncIpcCallBack &callback)
1749 {
1750 int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1751 auto ret = SetPreviewTextInner(text, range, callback);
1752 int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1753 ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_SET_PREVIEW_TEXT), ret, end - start);
1754 return ret;
1755 }
1756
FinishTextPreview(const AsyncIpcCallBack & callback)1757 int32_t InputMethodAbility::FinishTextPreview(const AsyncIpcCallBack &callback)
1758 {
1759 int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1760 auto ret = FinishTextPreviewInner(callback);
1761 int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1762 ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_FINISH_TEXT_PREVIEW),
1763 ret, end - start);
1764 return ret;
1765 }
1766
GetTextBeforeCursor(int32_t number,std::u16string & text,const AsyncIpcCallBack & callback)1767 int32_t InputMethodAbility::GetTextBeforeCursor(int32_t number, std::u16string &text, const AsyncIpcCallBack &callback)
1768 {
1769 int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1770 auto ret = GetTextBeforeCursorInner(number, text, callback);
1771 int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1772 ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_GET_TEXT_BEFORE_CURSOR),
1773 ret, end - start);
1774 return ret;
1775 }
GetTextAfterCursor(int32_t number,std::u16string & text,const AsyncIpcCallBack & callback)1776 int32_t InputMethodAbility::GetTextAfterCursor(int32_t number, std::u16string &text, const AsyncIpcCallBack &callback)
1777 {
1778 int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1779 auto ret = GetTextAfterCursorInner(number, text, callback);
1780 int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1781 ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_GET_TEXT_AFTER_CURSOR),
1782 ret, end - start);
1783 return ret;
1784 }
GetTextIndexAtCursor(int32_t & index,const AsyncIpcCallBack & callback)1785 int32_t InputMethodAbility::GetTextIndexAtCursor(int32_t &index, const AsyncIpcCallBack &callback)
1786 {
1787 int64_t start = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1788 auto ret = GetTextIndexAtCursorInner(index, callback);
1789 int64_t end = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
1790 ReportBaseTextOperation(static_cast<int32_t>(IInputDataChannelIpcCode::COMMAND_GET_TEXT_INDEX_AT_CURSOR),
1791 ret, end - start);
1792 return ret;
1793 }
1794
SetBindClientInfo(const InputClientInfo & clientInfo)1795 void InputMethodAbility::SetBindClientInfo(const InputClientInfo &clientInfo)
1796 {
1797 std::lock_guard<std::mutex> lock(bindClientInfoLock_);
1798 bindClientInfo_ = { clientInfo.pid, clientInfo.type, clientInfo.name };
1799 }
1800
GetBindClientInfo()1801 HiSysEventClientInfo InputMethodAbility::GetBindClientInfo()
1802 {
1803 std::lock_guard<std::mutex> lock(bindClientInfoLock_);
1804 return bindClientInfo_;
1805 }
1806
ClearBindClientInfo()1807 void InputMethodAbility::ClearBindClientInfo()
1808 {
1809 std::lock_guard<std::mutex> lock(bindClientInfoLock_);
1810 bindClientInfo_ = {};
1811 }
1812
ReportImeStartInput(int32_t eventCode,int32_t errCode,bool isShowKeyboard,int64_t consumeTime)1813 void InputMethodAbility::ReportImeStartInput(
1814 int32_t eventCode, int32_t errCode, bool isShowKeyboard, int64_t consumeTime)
1815 {
1816 IMSA_HILOGD("HiSysEvent report start:[%{public}d, %{public}d]!", eventCode, errCode);
1817 auto clientInfo = GetBindClientInfo();
1818 auto evenInfo = HiSysOriginalInfo::Builder()
1819 .SetPeerName(clientInfo.name)
1820 .SetPeerPid(clientInfo.pid)
1821 .SetIsShowKeyboard(isShowKeyboard)
1822 .SetEventCode(eventCode)
1823 .SetErrCode(errCode)
1824 .SetImeCbTime(consumeTime)
1825 .Build();
1826 ImaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::IME_START_INPUT, *evenInfo);
1827 IMSA_HILOGD("HiSysEvent report end:[%{public}d, %{public}d]!", eventCode, errCode);
1828 }
1829
ReportBaseTextOperation(int32_t eventCode,int32_t errCode,int64_t consumeTime)1830 void InputMethodAbility::ReportBaseTextOperation(int32_t eventCode, int32_t errCode, int64_t consumeTime)
1831 {
1832 IMSA_HILOGD("HiSysEvent report start:[%{public}d, %{public}d]!", eventCode, errCode);
1833 auto clientInfo = GetBindClientInfo();
1834 if (errCode == ErrorCode::NO_ERROR && consumeTime > BASE_TEXT_OPERATION_TIMEOUT) {
1835 errCode = ErrorCode::ERROR_DEAL_TIMEOUT;
1836 }
1837 auto evenInfo = HiSysOriginalInfo::Builder()
1838 .SetPeerName(clientInfo.name)
1839 .SetPeerPid(clientInfo.pid)
1840 .SetClientType(clientInfo.type)
1841 .SetEventCode(eventCode)
1842 .SetErrCode(errCode)
1843 .SetBaseTextOperatorTime(consumeTime)
1844 .Build();
1845 ImaHiSysEventReporter::GetInstance().ReportEvent(ImfEventType::BASE_TEXT_OPERATOR, *evenInfo);
1846 IMSA_HILOGD("HiSysEvent report end:[%{public}d, %{public}d]!", eventCode, errCode);
1847 }
1848
OnCallingDisplayIdChanged(uint64_t displayId)1849 int32_t InputMethodAbility::OnCallingDisplayIdChanged(uint64_t displayId)
1850 {
1851 IMSA_HILOGD("InputMethodAbility calling display: %{public}" PRIu64 ".", displayId);
1852 if (imeListener_ == nullptr) {
1853 IMSA_HILOGD("imeListener_ is nullptr!");
1854 return ErrorCode::NO_ERROR;
1855 }
1856 auto windowId = GetInputAttribute().windowId;
1857 auto task = [this, windowId]() {
1858 panels_.ForEach([windowId](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
1859 if (panel != nullptr) {
1860 panel->SetCallingWindow(windowId);
1861 }
1862 return false;
1863 });
1864 };
1865 imeListener_->PostTaskToEventHandler(task, "SetCallingWindow");
1866 {
1867 std::lock_guard<std::mutex> lock(inputAttrLock_);
1868 inputAttribute_.callingDisplayId = displayId;
1869 }
1870 imeListener_->OnCallingDisplayIdChanged(displayId);
1871 return ErrorCode::NO_ERROR;
1872 }
1873
OnSendPrivateData(const std::unordered_map<std::string,PrivateDataValue> & privateCommand)1874 int32_t InputMethodAbility::OnSendPrivateData(const std::unordered_map<std::string, PrivateDataValue> &privateCommand)
1875 {
1876 auto ret = ReceivePrivateCommand(privateCommand);
1877 if (ret != ErrorCode::NO_ERROR) {
1878 IMSA_HILOGE("OnSendPrivateData failed!");
1879 }
1880 IMSA_HILOGD("InputMethodAbility ReceivePrivateCommand success.");
1881 return ret;
1882 }
1883
HandleUnconsumedKey(const std::shared_ptr<MMI::KeyEvent> & keyEvent)1884 bool InputMethodAbility::HandleUnconsumedKey(const std::shared_ptr<MMI::KeyEvent> &keyEvent)
1885 {
1886 if (keyEvent == nullptr) {
1887 IMSA_HILOGE("keyEvent nullptr");
1888 return false;
1889 }
1890 auto channel = GetInputDataChannelProxyWrap();
1891 if (channel == nullptr) {
1892 IMSA_HILOGD("channel is nullptr!");
1893 return false;
1894 }
1895 if (!GetInputAttribute().needAutoInputNumkey) {
1896 IMSA_HILOGD("no need");
1897 return false;
1898 }
1899 if (keyEvent->GetKeyAction() != MMI::KeyEvent::KEY_ACTION_DOWN) {
1900 IMSA_HILOGD("not down key");
1901 return false;
1902 }
1903 if (keyEvent->GetPressedKeys().size() > 1) {
1904 IMSA_HILOGD("only handle single key");
1905 return false;
1906 }
1907 int32_t keyCode = keyEvent->GetKeyCode();
1908 std::string inputNumber;
1909 AsyncIpcCallBack callback = [](int32_t code, const ResponseData &data) {};
1910 if (MMI::KeyEvent::KEYCODE_0 <= keyCode && keyCode <= MMI::KeyEvent::KEYCODE_9) {
1911 IMSA_HILOGI("auto input a number");
1912 channel->InsertText(std::to_string(keyCode - MMI::KeyEvent::KEYCODE_0), callback);
1913 return true;
1914 }
1915 if (!keyEvent->GetFunctionKey(MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY)) {
1916 IMSA_HILOGD("num lock off");
1917 return false;
1918 }
1919 if (MMI::KeyEvent::KEYCODE_NUMPAD_0 <= keyCode && keyCode <= MMI::KeyEvent::KEYCODE_NUMPAD_9) {
1920 IMSA_HILOGI("auto input a number");
1921 channel->InsertText(std::to_string(keyCode - MMI::KeyEvent::KEYCODE_NUMPAD_0), callback);
1922 return true;
1923 }
1924 return false;
1925 }
1926
OnResponse(uint64_t msgId,int32_t code,const ResponseData & data)1927 int32_t InputMethodAbility::OnResponse(uint64_t msgId, int32_t code, const ResponseData &data)
1928 {
1929 auto channel = GetInputDataChannelProxyWrap();
1930 if (channel != nullptr) {
1931 ResponseInfo rspInfo = { code, data };
1932 channel->HandleResponse(msgId, rspInfo);
1933 }
1934 return ErrorCode::NO_ERROR;
1935 }
1936
IsCapacitySupport(int32_t capacity,bool & isSupport)1937 int32_t InputMethodAbility::IsCapacitySupport(int32_t capacity, bool &isSupport)
1938 {
1939 auto proxy = GetImsaProxy();
1940 if (proxy == nullptr) {
1941 IMSA_HILOGE("failed to get imsa proxy!");
1942 return ErrorCode::ERROR_NULL_POINTER;
1943 }
1944
1945 return proxy->IsCapacitySupport(capacity, isSupport);
1946 }
1947
HandleKeyEventResult(uint64_t cbId,bool consumeResult,const sptr<IRemoteObject> & channelObject)1948 int32_t InputMethodAbility::HandleKeyEventResult(
1949 uint64_t cbId, bool consumeResult, const sptr<IRemoteObject> &channelObject)
1950 {
1951 IMSA_HILOGD("run in:%{public}" PRIu64 "/%{public}d.", cbId, consumeResult);
1952 if (channelObject == nullptr) {
1953 IMSA_HILOGE("channelObject is nullptr:%{public}" PRIu64 ".", cbId);
1954 return ErrorCode::ERROR_IMA_CHANNEL_NULLPTR;
1955 }
1956 auto channel = std::make_shared<InputDataChannelProxy>(channelObject);
1957 return channel->HandleKeyEventResult(cbId, consumeResult);
1958 }
1959
OnNotifyPreemption()1960 int32_t InputMethodAbility::OnNotifyPreemption()
1961 {
1962 IMSA_HILOGD("start.");
1963 StopInput(dataChannelObject_, 0);
1964 isBound_.store(false);
1965 auto imeListener = GetImeListener();
1966 if (imeListener == nullptr) {
1967 return ErrorCode::ERROR_IME_NOT_STARTED;
1968 }
1969 IMSA_HILOGD("notifyPreemption begin.");
1970 imeListener->NotifyPreemption();
1971 return ErrorCode::NO_ERROR;
1972 }
1973 } // namespace MiscServices
1974 } // namespace OHOS