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
20 #include "global.h"
21 #include "input_method_agent_proxy.h"
22 #include "input_method_agent_stub.h"
23 #include "input_method_core_proxy.h"
24 #include "input_method_core_stub.h"
25 #include "input_method_utils.h"
26 #include "inputmethod_sysevent.h"
27 #include "iservice_registry.h"
28 #include "itypes_util.h"
29 #include "message_parcel.h"
30 #include "string_ex.h"
31 #include "sys/prctl.h"
32 #include "system_ability_definition.h"
33
34 namespace OHOS {
35 namespace MiscServices {
36 class MessageHandler;
37 using namespace MessageID;
38 sptr<InputMethodAbility> InputMethodAbility::instance_;
39 std::mutex InputMethodAbility::instanceLock_;
40 constexpr double INVALID_CURSOR_VALUE = -1.0;
41 constexpr int32_t INVALID_SELECTION_VALUE = -1;
InputMethodAbility()42 InputMethodAbility::InputMethodAbility() : msgHandler(nullptr), stop_(false) {}
43
~InputMethodAbility()44 InputMethodAbility::~InputMethodAbility()
45 {
46 IMSA_HILOGI("InputMethodAbility::~InputMethodAbility");
47 QuitWorkThread();
48 if (msgHandler != nullptr) {
49 delete msgHandler;
50 msgHandler = nullptr;
51 }
52 }
53
GetInstance()54 sptr<InputMethodAbility> InputMethodAbility::GetInstance()
55 {
56 if (instance_ == nullptr) {
57 std::lock_guard<std::mutex> autoLock(instanceLock_);
58 if (instance_ == nullptr) {
59 IMSA_HILOGI("InputMethodAbility::GetInstance need new IMA");
60 instance_ = new (std::nothrow) InputMethodAbility();
61 if (instance_ == nullptr) {
62 IMSA_HILOGI("instance is nullptr.");
63 return instance_;
64 }
65 instance_->Initialize();
66 }
67 }
68 return instance_;
69 }
70
GetImsaProxy()71 sptr<InputMethodSystemAbilityProxy> InputMethodAbility::GetImsaProxy()
72 {
73 IMSA_HILOGI("InputMethodAbility::GetImsaProxy");
74 sptr<ISystemAbilityManager> systemAbilityManager =
75 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
76 if (systemAbilityManager == nullptr) {
77 IMSA_HILOGI("InputMethodAbility::GetImsaProxy systemAbilityManager is nullptr");
78 return nullptr;
79 }
80
81 auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, "");
82 if (systemAbility == nullptr) {
83 IMSA_HILOGI("InputMethodAbility::GetImsaProxy systemAbility is nullptr");
84 return nullptr;
85 }
86 if (deathRecipientPtr_ == nullptr) {
87 deathRecipientPtr_ = new (std::nothrow) ServiceDeathRecipient();
88 if (deathRecipientPtr_ == nullptr) {
89 IMSA_HILOGE("new ServiceDeathRecipient failed");
90 return nullptr;
91 }
92 }
93 if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipientPtr_))) {
94 IMSA_HILOGE("failed to add death recipient.");
95 }
96
97 sptr<InputMethodSystemAbilityProxy> iface = new InputMethodSystemAbilityProxy(systemAbility);
98 return iface;
99 }
100
SetCoreAndAgent()101 int32_t InputMethodAbility::SetCoreAndAgent()
102 {
103 IMSA_HILOGD("InputMethodAbility, run in");
104 if (isBound_.load()) {
105 IMSA_HILOGD("already bound");
106 return ErrorCode::NO_ERROR;
107 }
108 mImms = GetImsaProxy();
109 if (mImms == nullptr) {
110 IMSA_HILOGI("InputMethodAbility mImms is nullptr");
111 return ErrorCode::ERROR_NULL_POINTER;
112 }
113 sptr<InputMethodCoreStub> stub = new InputMethodCoreStub(0);
114 stub->SetMessageHandler(msgHandler);
115
116 sptr<InputMethodAgentStub> inputMethodAgentStub(new InputMethodAgentStub());
117 inputMethodAgentStub->SetMessageHandler(msgHandler);
118 sptr<IInputMethodAgent> inputMethodAgent = sptr(new InputMethodAgentProxy(inputMethodAgentStub));
119 int32_t ret = mImms->SetCoreAndAgent(stub, inputMethodAgent);
120 if (ret != ErrorCode::NO_ERROR) {
121 IMSA_HILOGE("set failed, ret: %{public}d", ret);
122 return ret;
123 }
124 isBound_.store(true);
125 IMSA_HILOGD("set successfully");
126 return ErrorCode::NO_ERROR;
127 }
128
Initialize()129 void InputMethodAbility::Initialize()
130 {
131 IMSA_HILOGI("InputMethodAbility::Initialize");
132 msgHandler = new MessageHandler();
133 workThreadHandler = std::thread([this] { WorkThread(); });
134 }
135
SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)136 void InputMethodAbility::SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener)
137 {
138 IMSA_HILOGI("InputMethodAbility.");
139 if (imeListener_ == nullptr) {
140 imeListener_ = std::move(imeListener);
141 }
142 if (deathRecipientPtr_ != nullptr && deathRecipientPtr_->listener == nullptr) {
143 deathRecipientPtr_->listener = imeListener_;
144 }
145 }
146
OnImeReady()147 void InputMethodAbility::OnImeReady()
148 {
149 isImeReady_ = true;
150 if (!notifier_.isNotify) {
151 IMSA_HILOGI("InputMethodAbility::Ime Ready, don't need to notify");
152 return;
153 }
154 IMSA_HILOGI("InputMethodAbility::Ime Ready, notify InputStart");
155 TextTotalConfig textConfig{};
156 int32_t ret = GetTextConfig(textConfig);
157 IMSA_HILOGI("InputMethodAbility, get text config failed, ret is %{public}d", ret);
158 OnTextConfigChange(textConfig);
159 ShowInputWindow(notifier_.isShowKeyboard);
160 }
161
SetKdListener(std::shared_ptr<KeyboardListener> kdListener)162 void InputMethodAbility::SetKdListener(std::shared_ptr<KeyboardListener> kdListener)
163 {
164 IMSA_HILOGI("InputMethodAbility.");
165 if (kdListener_ == nullptr) {
166 kdListener_ = kdListener;
167 }
168 }
169
WorkThread()170 void InputMethodAbility::WorkThread()
171 {
172 prctl(PR_SET_NAME, "IMAWorkThread");
173 while (!stop_) {
174 Message *msg = msgHandler->GetMessage();
175 switch (msg->msgId_) {
176 case MSG_ID_INIT_INPUT_CONTROL_CHANNEL: {
177 OnInitInputControlChannel(msg);
178 break;
179 }
180 case MSG_ID_ON_CURSOR_UPDATE: {
181 OnCursorUpdate(msg);
182 break;
183 }
184 case MSG_ID_ON_SELECTION_CHANGE: {
185 OnSelectionChange(msg);
186 break;
187 }
188 case MSG_ID_ON_CONFIGURATION_CHANGE: {
189 OnConfigurationChange(msg);
190 break;
191 }
192 case MSG_ID_STOP_INPUT_SERVICE: {
193 MessageParcel *data = msg->msgContent_;
194 std::string imeId = Str16ToStr8(data->ReadString16());
195 if (imeListener_ != nullptr) {
196 imeListener_->OnInputStop(imeId);
197 }
198 isBound_.store(false);
199 break;
200 }
201 case MSG_ID_SET_SUBTYPE: {
202 OnSetSubtype(msg);
203 break;
204 }
205 default: {
206 IMSA_HILOGD("the message is %{public}d.", msg->msgId_);
207 break;
208 }
209 }
210 delete msg;
211 msg = nullptr;
212 }
213 }
214
OnInitInputControlChannel(Message * msg)215 void InputMethodAbility::OnInitInputControlChannel(Message *msg)
216 {
217 IMSA_HILOGI("InputMethodAbility::OnInitInputControlChannel");
218 MessageParcel *data = msg->msgContent_;
219 sptr<IRemoteObject> channelObject = data->ReadRemoteObject();
220 if (channelObject == nullptr) {
221 IMSA_HILOGI("InputMethodAbility::OnInitInputControlChannel channelObject is nullptr");
222 return;
223 }
224 if (deathRecipientPtr_ != nullptr) {
225 deathRecipientPtr_->currentIme_ = data->ReadString();
226 }
227 SetInputControlChannel(channelObject);
228 }
229
ShowKeyboard(const sptr<IRemoteObject> & channelObject,bool isShowKeyboard,bool attachFlag)230 int32_t InputMethodAbility::ShowKeyboard(const sptr<IRemoteObject> &channelObject, bool isShowKeyboard, bool attachFlag)
231 {
232 IMSA_HILOGI("InputMethodAbility::ShowKeyboard");
233 if (channelObject == nullptr) {
234 IMSA_HILOGE("InputMethodAbility::ShowKeyboard channelObject is nullptr");
235 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
236 }
237 SetInputDataChannel(channelObject);
238 if (attachFlag) {
239 TextTotalConfig textConfig = {};
240 int32_t ret = GetTextConfig(textConfig);
241 if (ret != ErrorCode::NO_ERROR) {
242 IMSA_HILOGE("InputMethodAbility, get text config failed, ret is %{public}d", ret);
243 return ret;
244 }
245 OnTextConfigChange(textConfig);
246 }
247 return ShowInputWindow(isShowKeyboard);
248 }
249
OnSetSubtype(Message * msg)250 void InputMethodAbility::OnSetSubtype(Message *msg)
251 {
252 IMSA_HILOGI("InputMethodAbility::OnSetSubtype");
253 auto data = msg->msgContent_;
254 SubProperty subProperty;
255 if (!ITypesUtil::Unmarshal(*data, subProperty)) {
256 IMSA_HILOGE("read message parcel failed");
257 return;
258 }
259 if (imeListener_ == nullptr) {
260 IMSA_HILOGI("InputMethodAbility::OnSetSubtype imeListener_ is nullptr");
261 return;
262 }
263 imeListener_->OnSetSubtype(subProperty);
264 }
265
ClearDataChannel(const sptr<IRemoteObject> & channel)266 void InputMethodAbility::ClearDataChannel(const sptr<IRemoteObject> &channel)
267 {
268 IMSA_HILOGI("run in");
269 std::lock_guard<std::mutex> lock(dataChannelLock_);
270 if (dataChannelObject_ == nullptr || channel == nullptr) {
271 return;
272 }
273 if (dataChannelObject_.GetRefPtr() == channel.GetRefPtr()) {
274 IMSA_HILOGI("clear data channel");
275 dataChannelObject_ = nullptr;
276 dataChannelProxy_ = nullptr;
277 }
278 }
279
DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)280 bool InputMethodAbility::DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> &keyEvent)
281 {
282 IMSA_HILOGD("InputMethodAbility, run in");
283 if (keyEvent == nullptr) {
284 IMSA_HILOGE("keyEvent is nullptr");
285 return false;
286 }
287 if (kdListener_ == nullptr) {
288 IMSA_HILOGI("kdListener_ is nullptr");
289 return false;
290 }
291 bool isFullKeyEventConsumed = kdListener_->OnKeyEvent(keyEvent);
292 bool isKeyEventConsumed = kdListener_->OnKeyEvent(keyEvent->GetKeyCode(), keyEvent->GetKeyAction());
293 return isFullKeyEventConsumed || isKeyEventConsumed;
294 }
295
SetCallingWindow(uint32_t windowId)296 void InputMethodAbility::SetCallingWindow(uint32_t windowId)
297 {
298 IMSA_HILOGI("InputMethodAbility::SetCallingWindow");
299
300 if (imeListener_ == nullptr) {
301 IMSA_HILOGI("InputMethodAbility::SetCallingWindow imeListener_ is nullptr");
302 return;
303 }
304 panels_.ForEach([windowId](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
305 panel->SetCallingWindow(windowId);
306 return false;
307 });
308 imeListener_->OnSetCallingWindow(windowId);
309 }
310
OnCursorUpdate(Message * msg)311 void InputMethodAbility::OnCursorUpdate(Message *msg)
312 {
313 IMSA_HILOGD("InputMethodAbility::OnCursorUpdate");
314 MessageParcel *data = msg->msgContent_;
315 int32_t positionX = data->ReadInt32();
316 int32_t positionY = data->ReadInt32();
317 int32_t height = data->ReadInt32();
318 if (kdListener_ == nullptr) {
319 IMSA_HILOGE("InputMethodAbility::OnCursorUpdate kdListener_ is nullptr");
320 return;
321 }
322 kdListener_->OnCursorUpdate(positionX, positionY, height);
323 }
324
OnSelectionChange(Message * msg)325 void InputMethodAbility::OnSelectionChange(Message *msg)
326 {
327 IMSA_HILOGD("InputMethodAbility::OnSelectionChange");
328 MessageParcel *data = msg->msgContent_;
329 std::string text = Str16ToStr8(data->ReadString16());
330 int32_t oldBegin = data->ReadInt32();
331 int32_t oldEnd = data->ReadInt32();
332 int32_t newBegin = data->ReadInt32();
333 int32_t newEnd = data->ReadInt32();
334
335 if (kdListener_ == nullptr) {
336 IMSA_HILOGE("InputMethodAbility::OnSelectionChange kdListener_ is nullptr");
337 return;
338 }
339 kdListener_->OnTextChange(text);
340
341 kdListener_->OnSelectionChange(oldBegin, oldEnd, newBegin, newEnd);
342 }
343
OnConfigurationChange(Message * msg)344 void InputMethodAbility::OnConfigurationChange(Message *msg)
345 {
346 IMSA_HILOGD("InputMethodAbility in.");
347 if (kdListener_ == nullptr) {
348 IMSA_HILOGE("InputMethodAbility in, kdListener_ is nullptr");
349 return;
350 }
351 MessageParcel *data = msg->msgContent_;
352 InputAttribute attribute;
353 attribute.enterKeyType = data->ReadInt32();
354 attribute.inputPattern = data->ReadInt32();
355 kdListener_->OnEditorAttributeChange(attribute);
356 }
357
ShowInputWindow(bool isShowKeyboard)358 int32_t InputMethodAbility::ShowInputWindow(bool isShowKeyboard)
359 {
360 IMSA_HILOGI("InputMethodAbility::ShowInputWindow");
361 if (!isImeReady_) {
362 IMSA_HILOGE("InputMethodAbility::ime is unready, store notifier_");
363 notifier_.isNotify = true;
364 notifier_.isShowKeyboard = isShowKeyboard;
365 return ErrorCode::ERROR_IME_NOT_READY;
366 }
367 if (imeListener_ == nullptr) {
368 IMSA_HILOGE("InputMethodAbility, imeListener is nullptr");
369 return ErrorCode::ERROR_IME;
370 }
371 imeListener_->OnInputStart();
372 if (!isShowKeyboard) {
373 IMSA_HILOGI("InputMethodAbility::ShowInputWindow will not show keyboard");
374 return ErrorCode::NO_ERROR;
375 }
376 imeListener_->OnKeyboardStatus(true);
377 auto channel = GetInputDataChannelProxy();
378 if (channel == nullptr) {
379 IMSA_HILOGE("InputMethodAbility::ShowInputWindow channel is nullptr");
380 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
381 }
382 channel->SendKeyboardStatus(KEYBOARD_SHOW);
383 auto result = panels_.Find(SOFT_KEYBOARD);
384 if (result.first) {
385 IMSA_HILOGI("find SOFT_KEYBOARD panel.");
386 auto panel = result.second;
387 if (panel->GetPanelFlag() == PanelFlag::FLG_CANDIDATE_COLUMN) {
388 IMSA_HILOGD("panel flag is candidate, not need to show.");
389 return ErrorCode::NO_ERROR;
390 }
391 auto ret = panel->ShowPanel();
392 if (ret != ErrorCode::NO_ERROR) {
393 IMSA_HILOGE("Show panel failed, ret = %{public}d.", ret);
394 }
395 return ret;
396 }
397 return ErrorCode::NO_ERROR;
398 }
399
OnTextConfigChange(const TextTotalConfig & textConfig)400 void InputMethodAbility::OnTextConfigChange(const TextTotalConfig &textConfig)
401 {
402 IMSA_HILOGI("InputMethodAbility run in.");
403 if (kdListener_ == nullptr) {
404 IMSA_HILOGE("kdListener_ is nullptr.");
405 } else {
406 IMSA_HILOGI("send on('editorAttributeChanged') callback.");
407 kdListener_->OnEditorAttributeChange(textConfig.inputAttribute);
408 if (textConfig.cursorInfo.left != INVALID_CURSOR_VALUE) {
409 IMSA_HILOGI("send on('cursorUpdate') callback.");
410 kdListener_->OnCursorUpdate(
411 textConfig.cursorInfo.left, textConfig.cursorInfo.top, textConfig.cursorInfo.height);
412 }
413 if (textConfig.textSelection.newBegin != INVALID_SELECTION_VALUE) {
414 IMSA_HILOGI("send on('selectionChange') callback.");
415 kdListener_->OnSelectionChange(textConfig.textSelection.oldBegin, textConfig.textSelection.oldEnd,
416 textConfig.textSelection.newBegin, textConfig.textSelection.newEnd);
417 }
418 }
419 if (textConfig.windowId == INVALID_WINDOW_ID) {
420 return;
421 }
422 panels_.ForEach([&textConfig](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
423 panel->SetCallingWindow(textConfig.windowId);
424 return false;
425 });
426 if (imeListener_ == nullptr) {
427 IMSA_HILOGE("imeListener_ is nullptr, do not need to send callback of setCallingWindow.");
428 return;
429 }
430 imeListener_->OnSetCallingWindow(textConfig.windowId);
431 IMSA_HILOGD("setCallingWindow end.");
432 }
433
HideKeyboard()434 int32_t InputMethodAbility::HideKeyboard()
435 {
436 IMSA_HILOGI("InputMethodAbility::HideKeyboard");
437 if (imeListener_ == nullptr) {
438 IMSA_HILOGE("InputMethodAbility::HideKeyboard imeListener_ is nullptr");
439 return ErrorCode::ERROR_IME;
440 }
441 imeListener_->OnKeyboardStatus(false);
442 auto channel = GetInputDataChannelProxy();
443 if (channel == nullptr) {
444 IMSA_HILOGE("InputMethodAbility::HideKeyboard channel is nullptr");
445 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
446 }
447 channel->SendKeyboardStatus(KEYBOARD_HIDE);
448 auto result = panels_.Find(SOFT_KEYBOARD);
449 if (!result.first) {
450 IMSA_HILOGE("Not find SOFT_KEYBOARD panel.");
451 return ErrorCode::NO_ERROR;
452 }
453 auto panel = result.second;
454 if (panel->GetPanelFlag() == PanelFlag::FLG_CANDIDATE_COLUMN) {
455 IMSA_HILOGD("panel flag is candidate, not need to hide.");
456 return ErrorCode::NO_ERROR;
457 }
458 auto ret = panel->HidePanel();
459 IMSA_HILOGD("Hide panel, ret = %{public}d.", ret);
460 return ret;
461 }
462
InsertText(const std::string text)463 int32_t InputMethodAbility::InsertText(const std::string text)
464 {
465 IMSA_HILOGD("InputMethodAbility, in");
466 auto channel = GetInputDataChannelProxy();
467 if (channel == nullptr) {
468 IMSA_HILOGI("InputMethodAbility::InsertText channel is nullptr");
469 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
470 }
471 return channel->InsertText(Str8ToStr16(text));
472 }
473
DeleteForward(int32_t length)474 int32_t InputMethodAbility::DeleteForward(int32_t length)
475 {
476 IMSA_HILOGD("InputMethodAbility, length = %{public}d", length);
477 auto channel = GetInputDataChannelProxy();
478 if (channel == nullptr) {
479 IMSA_HILOGE("InputMethodAbility, channel is nullptr");
480 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
481 }
482 return channel->DeleteForward(length);
483 }
484
DeleteBackward(int32_t length)485 int32_t InputMethodAbility::DeleteBackward(int32_t length)
486 {
487 IMSA_HILOGD("InputMethodAbility, length = %{public}d", length);
488 auto channel = GetInputDataChannelProxy();
489 if (channel == nullptr) {
490 IMSA_HILOGE("InputMethodAbility, channel is nullptr");
491 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
492 }
493 return channel->DeleteBackward(length);
494 }
495
SendFunctionKey(int32_t funcKey)496 int32_t InputMethodAbility::SendFunctionKey(int32_t funcKey)
497 {
498 auto channel = GetInputDataChannelProxy();
499 if (channel == nullptr) {
500 IMSA_HILOGE("InputMethodAbility::SendFunctionKey channel is nullptr");
501 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
502 }
503 return channel->SendFunctionKey(funcKey);
504 }
505
HideKeyboardSelf()506 int32_t InputMethodAbility::HideKeyboardSelf()
507 {
508 auto controlChannel = GetInputControlChannel();
509 if (controlChannel == nullptr) {
510 IMSA_HILOGE("InputMethodAbility::HideKeyboardSelf controlChannel is nullptr");
511 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
512 }
513 InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_SELF);
514 return controlChannel->HideKeyboardSelf();
515 }
516
SendExtendAction(int32_t action)517 int32_t InputMethodAbility::SendExtendAction(int32_t action)
518 {
519 auto channel = GetInputDataChannelProxy();
520 if (channel == nullptr) {
521 IMSA_HILOGI("InputMethodAbility::SendExtendAction channel is nullptr");
522 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
523 }
524 return channel->HandleExtendAction(action);
525 }
526
GetTextBeforeCursor(int32_t number,std::u16string & text)527 int32_t InputMethodAbility::GetTextBeforeCursor(int32_t number, std::u16string &text)
528 {
529 auto channel = GetInputDataChannelProxy();
530 if (channel == nullptr) {
531 IMSA_HILOGE("InputMethodAbility::GetTextBeforeCursor channel is nullptr");
532 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
533 }
534 return channel->GetTextBeforeCursor(number, text);
535 }
536
GetTextAfterCursor(int32_t number,std::u16string & text)537 int32_t InputMethodAbility::GetTextAfterCursor(int32_t number, std::u16string &text)
538 {
539 auto channel = GetInputDataChannelProxy();
540 if (channel == nullptr) {
541 IMSA_HILOGE("InputMethodAbility::GetTextAfterCursor channel is nullptr");
542 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
543 }
544 return channel->GetTextAfterCursor(number, text);
545 }
546
MoveCursor(int32_t keyCode)547 int32_t InputMethodAbility::MoveCursor(int32_t keyCode)
548 {
549 IMSA_HILOGD("InputMethodAbility, keyCode = %{public}d", keyCode);
550 auto channel = GetInputDataChannelProxy();
551 if (channel == nullptr) {
552 IMSA_HILOGE("InputMethodAbility::MoveCursor channel is nullptr");
553 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
554 }
555
556 return channel->MoveCursor(keyCode);
557 }
558
SelectByRange(int32_t start,int32_t end)559 int32_t InputMethodAbility::SelectByRange(int32_t start, int32_t end)
560 {
561 IMSA_HILOGD("InputMethodAbility, start = %{public}d, end = %{public}d", start, end);
562 if (start < 0 || end < 0) {
563 IMSA_HILOGE("check parameter failed, start: %{public}d, end: %{public}d", start, end);
564 return ErrorCode::ERROR_BAD_PARAMETERS;
565 }
566 auto dataChannel = GetInputDataChannelProxy();
567 if (dataChannel == nullptr) {
568 IMSA_HILOGE("datachannel is nullptr");
569 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
570 }
571 return dataChannel->SelectByRange(start, end);
572 }
573
SelectByMovement(int32_t direction)574 int32_t InputMethodAbility::SelectByMovement(int32_t direction)
575 {
576 IMSA_HILOGD("InputMethodAbility, direction = %{public}d", direction);
577 auto dataChannel = GetInputDataChannelProxy();
578 if (dataChannel == nullptr) {
579 IMSA_HILOGE("datachannel is nullptr");
580 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
581 }
582 return dataChannel->SelectByMovement(direction, 0);
583 }
584
GetEnterKeyType(int32_t & keyType)585 int32_t InputMethodAbility::GetEnterKeyType(int32_t &keyType)
586 {
587 auto channel = GetInputDataChannelProxy();
588 if (channel == nullptr) {
589 IMSA_HILOGE("InputMethodAbility::GetEnterKeyType channel is nullptr");
590 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
591 }
592 return channel->GetEnterKeyType(keyType);
593 }
594
GetInputPattern(int32_t & inputPattern)595 int32_t InputMethodAbility::GetInputPattern(int32_t &inputPattern)
596 {
597 auto channel = GetInputDataChannelProxy();
598 if (channel == nullptr) {
599 IMSA_HILOGE("InputMethodAbility::GetInputPattern channel is nullptr");
600 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
601 }
602 return channel->GetInputPattern(inputPattern);
603 }
604
GetTextIndexAtCursor(int32_t & index)605 int32_t InputMethodAbility::GetTextIndexAtCursor(int32_t &index)
606 {
607 auto channel = GetInputDataChannelProxy();
608 if (channel == nullptr) {
609 IMSA_HILOGE("InputMethodAbility::channel is nullptr");
610 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
611 }
612 return channel->GetTextIndexAtCursor(index);
613 }
614
GetTextConfig(TextTotalConfig & textConfig)615 int32_t InputMethodAbility::GetTextConfig(TextTotalConfig &textConfig)
616 {
617 IMSA_HILOGD("InputMethodAbility, run in.");
618 auto channel = GetInputDataChannelProxy();
619 if (channel == nullptr) {
620 IMSA_HILOGE("InputMethodAbility::channel is nullptr");
621 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
622 }
623 return channel->GetTextConfig(textConfig);
624 }
625
SetInputDataChannel(const sptr<IRemoteObject> & object)626 void InputMethodAbility::SetInputDataChannel(const sptr<IRemoteObject> &object)
627 {
628 IMSA_HILOGD("run in SetInputDataChannel");
629 std::lock_guard<std::mutex> lock(dataChannelLock_);
630 auto channelProxy = std::make_shared<InputDataChannelProxy>(object);
631 if (channelProxy == nullptr) {
632 IMSA_HILOGE("failed to new data channel proxy");
633 return;
634 }
635 dataChannelObject_ = object;
636 dataChannelProxy_ = channelProxy;
637 }
638
GetInputDataChannelProxy()639 std::shared_ptr<InputDataChannelProxy> InputMethodAbility::GetInputDataChannelProxy()
640 {
641 std::lock_guard<std::mutex> lock(dataChannelLock_);
642 return dataChannelProxy_;
643 }
644
SetInputControlChannel(sptr<IRemoteObject> & object)645 void InputMethodAbility::SetInputControlChannel(sptr<IRemoteObject> &object)
646 {
647 IMSA_HILOGI("run in SetInputControlChannel");
648 std::lock_guard<std::mutex> lock(controlChannelLock_);
649 std::shared_ptr<InputControlChannelProxy> channelProxy = std::make_shared<InputControlChannelProxy>(object);
650 if (channelProxy == nullptr) {
651 IMSA_HILOGI("InputMethodAbility::SetInputControlChannel inputDataChannel is nullptr");
652 return;
653 }
654 controlChannel_ = channelProxy;
655 }
656
GetInputControlChannel()657 std::shared_ptr<InputControlChannelProxy> InputMethodAbility::GetInputControlChannel()
658 {
659 std::lock_guard<std::mutex> lock(controlChannelLock_);
660 return controlChannel_;
661 }
662
OnRemoteDied(const wptr<IRemoteObject> & object)663 void InputMethodAbility::ServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
664 {
665 IMSA_HILOGI("ServiceDeathRecipient::OnRemoteDied");
666 if (listener != nullptr) {
667 listener->OnInputStop(currentIme_);
668 }
669 }
670
QuitWorkThread()671 void InputMethodAbility::QuitWorkThread()
672 {
673 stop_ = true;
674 Message *msg = new Message(MessageID::MSG_ID_QUIT_WORKER_THREAD, nullptr);
675 msgHandler->SendMessage(msg);
676 if (workThreadHandler.joinable()) {
677 workThreadHandler.join();
678 }
679 }
680
CreatePanel(const std::shared_ptr<AbilityRuntime::Context> & context,const PanelInfo & panelInfo,std::shared_ptr<InputMethodPanel> & inputMethodPanel)681 int32_t InputMethodAbility::CreatePanel(const std::shared_ptr<AbilityRuntime::Context> &context,
682 const PanelInfo &panelInfo, std::shared_ptr<InputMethodPanel> &inputMethodPanel)
683 {
684 IMSA_HILOGI("InputMethodAbility::CreatePanel start.");
685 auto result = panels_.Find(panelInfo.panelType);
686 if (result.first) {
687 IMSA_HILOGE(" type of %{public}d panel already created, can not create another", panelInfo.panelType);
688 return ErrorCode::ERROR_OPERATE_PANEL;
689 }
690 inputMethodPanel = std::make_shared<InputMethodPanel>();
691 auto ret = inputMethodPanel->CreatePanel(context, panelInfo);
692 if (ret != ErrorCode::NO_ERROR) {
693 IMSA_HILOGE("CreatePanel failed, ret = %{public}d", ret);
694 return ret;
695 }
696 IMSA_HILOGI("InputMethodAbility::CreatePanel ret = 0, success.");
697 if (!panels_.Insert(panelInfo.panelType, inputMethodPanel)) {
698 IMSA_HILOGE("insert inputMethodPanel fail.");
699 return ErrorCode::ERROR_OPERATE_PANEL;
700 }
701 return ErrorCode::NO_ERROR;
702 }
703
DestroyPanel(const std::shared_ptr<InputMethodPanel> & inputMethodPanel)704 int32_t InputMethodAbility::DestroyPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel)
705 {
706 IMSA_HILOGI("InputMethodAbility, in.");
707 if (inputMethodPanel == nullptr) {
708 return ErrorCode::ERROR_BAD_PARAMETERS;
709 }
710 PanelType panelType = inputMethodPanel->GetPanelType();
711 auto ret = inputMethodPanel->DestroyPanel();
712 if (ret == ErrorCode::NO_ERROR) {
713 panels_.Erase(panelType);
714 }
715 return ret;
716 }
717 } // namespace MiscServices
718 } // namespace OHOS
719