1 /* 2 * Copyright (C) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "input_method_controller.h" 17 18 #include "global.h" 19 #include "input_client_stub.h" 20 #include "input_data_channel_stub.h" 21 #include "input_method_agent_proxy.h" 22 #include "input_method_property.h" 23 #include "input_method_status.h" 24 #include "input_method_system_ability_proxy.h" 25 #include "inputmethod_sysevent.h" 26 #include "inputmethod_trace.h" 27 #include "iservice_registry.h" 28 #include "string_ex.h" 29 #include "system_ability_definition.h" 30 #include "utils.h" 31 32 namespace OHOS { 33 namespace MiscServices { 34 using namespace MessageID; 35 sptr<InputMethodController> InputMethodController::instance_; 36 std::mutex InputMethodController::instanceLock_; 37 constexpr int32_t WAIT_TIME = 100; 38 constexpr int32_t KEYBOARD_SHOW = 2; InputMethodController()39 InputMethodController::InputMethodController() : stop_(false) 40 { 41 IMSA_HILOGI("InputMethodController structure"); 42 Initialize(); 43 } 44 ~InputMethodController()45 InputMethodController::~InputMethodController() 46 { 47 QuitWorkThread(); 48 delete msgHandler; 49 msgHandler = nullptr; 50 } 51 GetInstance()52 sptr<InputMethodController> InputMethodController::GetInstance() 53 { 54 if (!instance_) { 55 std::lock_guard<std::mutex> autoLock(instanceLock_); 56 if (!instance_) { 57 IMSA_HILOGI("InputMethodController::GetInstance instance_ is nullptr"); 58 instance_ = new InputMethodController(); 59 } 60 } 61 return instance_; 62 } 63 setImeListener(std::shared_ptr<InputMethodSettingListener> imeListener)64 void InputMethodController::setImeListener(std::shared_ptr<InputMethodSettingListener> imeListener) 65 { 66 IMSA_HILOGI("InputMethodController::setImeListener"); 67 if (imeListener_ == nullptr) { 68 imeListener_ = imeListener; 69 } 70 } 71 Initialize()72 bool InputMethodController::Initialize() 73 { 74 msgHandler = new MessageHandler(); 75 76 InputClientStub *client = new (std::nothrow) InputClientStub(); 77 if (client == nullptr) { 78 IMSA_HILOGE("InputMethodController::Initialize client is nullptr"); 79 return false; 80 } 81 client->SetHandler(msgHandler); 82 mClient = client; 83 84 InputDataChannelStub *channel = new (std::nothrow) InputDataChannelStub(); 85 if (channel == nullptr) { 86 IMSA_HILOGE("InputMethodController::Initialize channel is nullptr"); 87 return false; 88 } 89 channel->SetHandler(msgHandler); 90 mInputDataChannel = channel; 91 92 workThreadHandler = std::thread([this] { WorkThread(); }); 93 mAttribute.inputPattern = InputAttribute::PATTERN_TEXT; 94 { 95 std::lock_guard<std::mutex> lock(textListenerLock_); 96 textListener = nullptr; 97 } 98 IMSA_HILOGI("InputMethodController::Initialize textListener is nullptr"); 99 PrepareInput(0, mClient, mInputDataChannel, mAttribute); 100 return true; 101 } 102 GetSystemAbilityProxy()103 sptr<IInputMethodSystemAbility> InputMethodController::GetSystemAbilityProxy() 104 { 105 std::lock_guard<std::mutex> lock(abilityLock_); 106 if (abilityManager_ != nullptr) { 107 return abilityManager_; 108 } 109 IMSA_HILOGI("get input method service proxy"); 110 sptr<ISystemAbilityManager> systemAbilityManager = 111 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 112 if (systemAbilityManager == nullptr) { 113 IMSA_HILOGI("system ability manager is nullptr"); 114 return nullptr; 115 } 116 auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, ""); 117 if (systemAbility == nullptr) { 118 IMSA_HILOGI("system ability is nullptr"); 119 return nullptr; 120 } 121 if (deathRecipient_ == nullptr) { 122 deathRecipient_ = new (std::nothrow)ImsaDeathRecipient(); 123 if (deathRecipient_ == nullptr) { 124 IMSA_HILOGE("new death recipient failed"); 125 return nullptr; 126 } 127 } 128 if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipient_))) { 129 IMSA_HILOGE("failed to add death recipient."); 130 return nullptr; 131 } 132 abilityManager_ = iface_cast<IInputMethodSystemAbility>(systemAbility); 133 return abilityManager_; 134 } 135 WorkThread()136 void InputMethodController::WorkThread() 137 { 138 while (!stop_) { 139 Message *msg = msgHandler->GetMessage(); 140 switch (msg->msgId_) { 141 case MSG_ID_INSERT_CHAR: { 142 MessageParcel *data = msg->msgContent_; 143 std::u16string text = data->ReadString16(); 144 IMSA_HILOGI("InputMethodController::WorkThread InsertText"); 145 std::lock_guard<std::mutex> lock(textListenerLock_); 146 if (textListener) { 147 textListener->InsertText(text); 148 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 149 textFieldReplyCount_++; 150 } 151 break; 152 } 153 154 case MSG_ID_DELETE_FORWARD: { 155 MessageParcel *data = msg->msgContent_; 156 int32_t length = data->ReadInt32(); 157 IMSA_HILOGI("InputMethodController::WorkThread DeleteForward"); 158 std::lock_guard<std::mutex> lock(textListenerLock_); 159 if (textListener) { 160 textListener->DeleteForward(length); 161 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 162 textFieldReplyCount_++; 163 } 164 break; 165 } 166 case MSG_ID_DELETE_BACKWARD: { 167 MessageParcel *data = msg->msgContent_; 168 int32_t length = data->ReadInt32(); 169 IMSA_HILOGI("InputMethodController::WorkThread DeleteBackward"); 170 std::lock_guard<std::mutex> lock(textListenerLock_); 171 if (textListener) { 172 textListener->DeleteBackward(length); 173 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 174 textFieldReplyCount_++; 175 } 176 break; 177 } 178 case MSG_ID_ON_INPUT_READY: { 179 MessageParcel *data = msg->msgContent_; 180 sptr<IRemoteObject> object = data->ReadRemoteObject(); 181 if (object) { 182 SetInputMethodAgent(object); 183 } 184 break; 185 } 186 case MSG_ID_SEND_KEYBOARD_STATUS: { 187 MessageParcel *data = msg->msgContent_; 188 int32_t ret = data->ReadInt32(); 189 KeyboardInfo *info = new KeyboardInfo(); 190 info->SetKeyboardStatus(ret); 191 IMSA_HILOGI("InputMethodController::WorkThread SendKeyboardInfo"); 192 std::lock_guard<std::mutex> lock(textListenerLock_); 193 if (textListener) { 194 textListener->SendKeyboardInfo(*info); 195 DoIncrease(ret); 196 } 197 delete info; 198 break; 199 } 200 case MSG_ID_SEND_FUNCTION_KEY: { 201 MessageParcel *data = msg->msgContent_; 202 int32_t ret = data->ReadInt32(); 203 KeyboardInfo *info = new KeyboardInfo(); 204 info->SetFunctionKey(ret); 205 IMSA_HILOGI("InputMethodController::WorkThread SendKeyboardInfo"); 206 std::lock_guard<std::mutex> lock(textListenerLock_); 207 if (textListener) { 208 textListener->SendKeyboardInfo(*info); 209 } 210 delete info; 211 break; 212 } 213 case MSG_ID_MOVE_CURSOR: { 214 MessageParcel *data = msg->msgContent_; 215 int32_t ret = data->ReadInt32(); 216 IMSA_HILOGI("InputMethodController::WorkThread MoveCursor"); 217 std::lock_guard<std::mutex> lock(textListenerLock_); 218 if (textListener) { 219 Direction direction = static_cast<Direction>(ret); 220 textListener->MoveCursor(direction); 221 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 222 textFieldReplyCount_++; 223 } 224 break; 225 } 226 case MSG_ID_ON_SWITCH_INPUT: { 227 auto data = msg->msgContent_; 228 Property property; 229 SubProperty subProperty; 230 if (!ITypesUtil::Unmarshal(*data, property, subProperty)) { 231 IMSA_HILOGE("read property from message parcel failed"); 232 break; 233 } 234 OnSwitchInput(property, subProperty); 235 break; 236 } 237 case MSG_ID_HANDLE_SET_SELECTION: { 238 MessageParcel *data = msg->msgContent_; 239 int32_t start = data->ReadInt32(); 240 int32_t end = data->ReadInt32(); 241 IMSA_HILOGI("InputMethodController::WorkThread HandleSetSelection"); 242 if (textListener) { 243 textListener->HandleSetSelection(start, end); 244 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 245 textFieldReplyCount_++; 246 } 247 break; 248 } 249 case MSG_ID_HANDLE_EXTEND_ACTION: { 250 MessageParcel *data = msg->msgContent_; 251 int32_t action = data->ReadInt32(); 252 IMSA_HILOGI("InputMethodController::WorkThread HandleExtendAction"); 253 if (textListener) { 254 textListener->HandleExtendAction(action); 255 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 256 textFieldReplyCount_++; 257 } 258 break; 259 } 260 case MSG_ID_HANDLE_SELECT: { 261 MessageParcel *data = msg->msgContent_; 262 int32_t keyCode = data->ReadInt32(); 263 int32_t cursorMoveSkip = data->ReadInt32(); 264 IMSA_HILOGI("InputMethodController::WorkThread HandleSelect"); 265 if (textListener) { 266 textListener->HandleSelect(keyCode, cursorMoveSkip); 267 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 268 textFieldReplyCount_++; 269 } 270 break; 271 } 272 case MSG_ID_GET_TEXT_BEFORE_CURSOR: 273 case MSG_ID_GET_TEXT_AFTER_CURSOR: { 274 IMSA_HILOGI("InputMethodController::WorkThread HandleGetOperation, msgId: %{public}d", msg->msgId_); 275 HandleGetOperation(); 276 break; 277 } 278 default: { 279 IMSA_HILOGD("the message is %{public}d.", msg->msgId_); 280 break; 281 } 282 } 283 delete msg; 284 msg = nullptr; 285 } 286 } 287 DoIncrease(int32_t status)288 void InputMethodController::DoIncrease(int32_t status) 289 { 290 if (status == KEYBOARD_SHOW) { 291 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 292 textFieldReplyCount_++; 293 } 294 } 295 QuitWorkThread()296 void InputMethodController::QuitWorkThread() 297 { 298 stop_ = true; 299 Message *msg = new Message(MessageID::MSG_ID_QUIT_WORKER_THREAD, nullptr); 300 msgHandler->SendMessage(msg); 301 if (workThreadHandler.joinable()) { 302 workThreadHandler.join(); 303 } 304 } 305 OnSwitchInput(const Property & property,const SubProperty & subProperty)306 void InputMethodController::OnSwitchInput(const Property &property, const SubProperty &subProperty) 307 { 308 IMSA_HILOGE("InputMethodController::OnSwitchInput"); 309 if (imeListener_ == nullptr) { 310 IMSA_HILOGE("imeListener_ is nullptr"); 311 return; 312 } 313 imeListener_->OnImeChange(property, subProperty); 314 } 315 Attach(sptr<OnTextChangedListener> & listener)316 void InputMethodController::Attach(sptr<OnTextChangedListener> &listener) 317 { 318 Attach(listener, true); 319 } 320 Attach(sptr<OnTextChangedListener> & listener,bool isShowKeyboard)321 void InputMethodController::Attach(sptr<OnTextChangedListener> &listener, bool isShowKeyboard) 322 { 323 InputAttribute attribute; 324 attribute.inputPattern = InputAttribute::PATTERN_TEXT; 325 Attach(listener, isShowKeyboard, attribute); 326 } 327 Attach(sptr<OnTextChangedListener> & listener,bool isShowKeyboard,InputAttribute & attribute)328 void InputMethodController::Attach( 329 sptr<OnTextChangedListener> &listener, bool isShowKeyboard, InputAttribute &attribute) 330 { 331 { 332 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 333 textFieldReplyCount_ = 0; 334 } 335 { 336 std::lock_guard<std::mutex> lock(textListenerLock_); 337 textListener = listener; 338 } 339 IMSA_HILOGI("InputMethodController::Attach"); 340 InputmethodTrace tracer("InputMethodController Attach trace."); 341 IMSA_HILOGI("InputMethodController::Attach isShowKeyboard %{public}s", isShowKeyboard ? "true" : "false"); 342 mAttribute = attribute; 343 PrepareInput(0, mClient, mInputDataChannel, mAttribute); 344 StartInput(mClient, isShowKeyboard); 345 } 346 ShowTextInput()347 void InputMethodController::ShowTextInput() 348 { 349 IMSA_HILOGI("InputMethodController::ShowTextInput"); 350 StartInput(mClient, true); 351 } 352 HideTextInput()353 void InputMethodController::HideTextInput() 354 { 355 IMSA_HILOGD("InputMethodController::HideTextInput"); 356 StopInput(mClient); 357 } 358 HideCurrentInput()359 int32_t InputMethodController::HideCurrentInput() 360 { 361 IMSA_HILOGD("InputMethodController::HideCurrentInput"); 362 auto proxy = GetSystemAbilityProxy(); 363 if (proxy == nullptr) { 364 IMSA_HILOGE("proxy is nullptr"); 365 return ErrorCode::ERROR_EX_NULL_POINTER; 366 } 367 return proxy->HideCurrentInputDeprecated(); 368 } 369 ShowCurrentInput()370 int32_t InputMethodController::ShowCurrentInput() 371 { 372 IMSA_HILOGI("InputMethodController::ShowCurrentInput"); 373 auto proxy = GetSystemAbilityProxy(); 374 if (proxy == nullptr) { 375 IMSA_HILOGE("proxy is nullptr"); 376 return ErrorCode::ERROR_EX_NULL_POINTER; 377 } 378 return proxy->ShowCurrentInputDeprecated(); 379 } 380 Close()381 void InputMethodController::Close() 382 { 383 ReleaseInput(mClient); 384 InputmethodTrace tracer("InputMethodController Close trace."); 385 { 386 std::lock_guard<std::mutex> lock(textListenerLock_); 387 textListener = nullptr; 388 } 389 IMSA_HILOGI("InputMethodController::Close"); 390 } 391 PrepareInput(int32_t displayId,sptr<IInputClient> & client,sptr<IInputDataChannel> & channel,InputAttribute & attribute)392 void InputMethodController::PrepareInput(int32_t displayId, sptr<IInputClient> &client, 393 sptr<IInputDataChannel> &channel, InputAttribute &attribute) 394 { 395 IMSA_HILOGI("InputMethodController::PrepareInput"); 396 auto proxy = GetSystemAbilityProxy(); 397 if (proxy == nullptr) { 398 IMSA_HILOGE("proxy is nullptr"); 399 return; 400 } 401 proxy->PrepareInput(displayId, client, channel, attribute); 402 } 403 DisplayOptionalInputMethod()404 int32_t InputMethodController::DisplayOptionalInputMethod() 405 { 406 IMSA_HILOGI("InputMethodController::DisplayOptionalInputMethod"); 407 auto proxy = GetSystemAbilityProxy(); 408 if (proxy == nullptr) { 409 IMSA_HILOGE("proxy is nullptr"); 410 return ErrorCode::ERROR_EX_NULL_POINTER; 411 } 412 return proxy->DisplayOptionalInputMethodDeprecated(); 413 } 414 ListInputMethodCommon(InputMethodStatus status,std::vector<Property> & props)415 int32_t InputMethodController::ListInputMethodCommon(InputMethodStatus status, std::vector<Property> &props) 416 { 417 IMSA_HILOGI("InputMethodController::ListInputMethodCommon"); 418 auto proxy = GetSystemAbilityProxy(); 419 if (proxy == nullptr) { 420 IMSA_HILOGE("proxy is nullptr"); 421 return ErrorCode::ERROR_EX_NULL_POINTER; 422 } 423 return proxy->ListInputMethod(status, props); 424 } 425 ListInputMethod(std::vector<Property> & props)426 int32_t InputMethodController::ListInputMethod(std::vector<Property> &props) 427 { 428 IMSA_HILOGI("InputMethodController::listInputMethod"); 429 return ListInputMethodCommon(ALL, props); 430 } 431 ListInputMethod(bool enable,std::vector<Property> & props)432 int32_t InputMethodController::ListInputMethod(bool enable, std::vector<Property> &props) 433 { 434 IMSA_HILOGI("InputMethodController::listInputMethod enable = %{public}s", enable ? "ENABLE" : "DISABLE"); 435 return ListInputMethodCommon(enable ? ENABLE : DISABLE, props); 436 } 437 GetCurrentInputMethod()438 std::shared_ptr<Property> InputMethodController::GetCurrentInputMethod() 439 { 440 IMSA_HILOGD("InputMethodController::GetCurrentInputMethod"); 441 auto proxy = GetSystemAbilityProxy(); 442 if (proxy == nullptr) { 443 IMSA_HILOGE("proxy is nullptr"); 444 return nullptr; 445 } 446 auto property = proxy->GetCurrentInputMethod(); 447 if (property == nullptr) { 448 IMSA_HILOGE("InputMethodController::GetCurrentInputMethod property is nullptr"); 449 return nullptr; 450 } 451 return property; 452 } 453 GetCurrentInputMethodSubtype()454 std::shared_ptr<SubProperty> InputMethodController::GetCurrentInputMethodSubtype() 455 { 456 IMSA_HILOGD("InputMethodController::GetCurrentInputMethod"); 457 auto proxy = GetSystemAbilityProxy(); 458 if (proxy == nullptr) { 459 IMSA_HILOGE("proxy is nullptr"); 460 return nullptr; 461 } 462 auto property = proxy->GetCurrentInputMethodSubtype(); 463 if (property == nullptr) { 464 IMSA_HILOGE("InputMethodController::GetCurrentInputMethodSubtype property is nullptr"); 465 return nullptr; 466 } 467 return property; 468 } 469 StartInput(sptr<IInputClient> & client,bool isShowKeyboard)470 void InputMethodController::StartInput(sptr<IInputClient> &client, bool isShowKeyboard) 471 { 472 IMSA_HILOGI("InputMethodController::StartInput"); 473 isStopInput = false; 474 auto proxy = GetSystemAbilityProxy(); 475 if (proxy == nullptr) { 476 IMSA_HILOGE("proxy is nullptr"); 477 return; 478 } 479 proxy->StartInput(client, isShowKeyboard); 480 } 481 ReleaseInput(sptr<IInputClient> & client)482 void InputMethodController::ReleaseInput(sptr<IInputClient> &client) 483 { 484 IMSA_HILOGD("InputMethodController::ReleaseInput"); 485 isStopInput = true; 486 auto proxy = GetSystemAbilityProxy(); 487 if (proxy == nullptr) { 488 IMSA_HILOGE("proxy is nullptr"); 489 return; 490 } 491 proxy->ReleaseInput(client); 492 } 493 StopInput(sptr<IInputClient> & client)494 void InputMethodController::StopInput(sptr<IInputClient> &client) 495 { 496 IMSA_HILOGD("InputMethodController::StopInput"); 497 isStopInput = true; 498 auto proxy = GetSystemAbilityProxy(); 499 if (proxy == nullptr) { 500 IMSA_HILOGE("proxy is nullptr"); 501 return; 502 } 503 proxy->StopInput(client); 504 } 505 OnRemoteSaDied(const wptr<IRemoteObject> & remote)506 void InputMethodController::OnRemoteSaDied(const wptr<IRemoteObject> &remote) 507 { 508 IMSA_HILOGE("input method service death"); 509 std::lock_guard<std::mutex> lock(abilityLock_); 510 abilityManager_ = nullptr; 511 } 512 ImsaDeathRecipient()513 ImsaDeathRecipient::ImsaDeathRecipient() 514 { 515 } 516 OnRemoteDied(const wptr<IRemoteObject> & object)517 void ImsaDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object) 518 { 519 InputMethodController::GetInstance()->OnRemoteSaDied(object); 520 } 521 OnCursorUpdate(CursorInfo cursorInfo)522 void InputMethodController::OnCursorUpdate(CursorInfo cursorInfo) 523 { 524 if (isStopInput) { 525 IMSA_HILOGD("InputMethodController::OnCursorUpdate isStopInput"); 526 return; 527 } 528 std::shared_ptr<IInputMethodAgent> agent = GetInputMethodAgent(); 529 if (agent == nullptr) { 530 IMSA_HILOGI("InputMethodController::OnCursorUpdate agent is nullptr"); 531 return; 532 } 533 if (cursorInfo_.left == cursorInfo.left && cursorInfo_.top == cursorInfo.top 534 && cursorInfo_.height == cursorInfo.height) { 535 return; 536 } 537 cursorInfo_ = cursorInfo; 538 agent->OnCursorUpdate(cursorInfo.left, cursorInfo.top, cursorInfo.height); 539 } 540 OnSelectionChange(std::u16string text,int start,int end)541 void InputMethodController::OnSelectionChange(std::u16string text, int start, int end) 542 { 543 IMSA_HILOGI("size: %{public}zu, start: %{public}d, end: %{public}d, replyCount: %{public}d", text.size(), 544 start, end, textFieldReplyCount_); 545 if (isStopInput) { 546 IMSA_HILOGD("InputMethodController::OnSelectionChange isStopInput"); 547 return; 548 } 549 { 550 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 551 if (textFieldReplyCount_ > 0 552 && (text.size() != mTextString.size() || start != mSelectNewBegin || end != mSelectNewEnd)) { 553 textFieldReplyCount_--; 554 } 555 if (textFieldReplyCount_ == 0) { 556 textFieldReplyCountCv_.notify_one(); 557 } 558 } 559 if (mTextString == text && mSelectNewBegin == start && mSelectNewEnd == end) { 560 return; 561 } 562 mTextString = text; 563 mSelectOldBegin = mSelectNewBegin; 564 mSelectOldEnd = mSelectNewEnd; 565 mSelectNewBegin = start; 566 mSelectNewEnd = end; 567 std::shared_ptr<IInputMethodAgent> agent = GetInputMethodAgent(); 568 if (agent == nullptr) { 569 IMSA_HILOGI("InputMethodController::OnSelectionChange agent is nullptr"); 570 return; 571 } 572 agent->OnSelectionChange(mTextString, mSelectOldBegin, mSelectOldEnd, mSelectNewBegin, mSelectNewEnd); 573 } 574 OnConfigurationChange(Configuration info)575 void InputMethodController::OnConfigurationChange(Configuration info) 576 { 577 IMSA_HILOGI("InputMethodController::OnConfigurationChange"); 578 enterKeyType_ = static_cast<uint32_t>(info.GetEnterKeyType()); 579 inputPattern_ = static_cast<uint32_t>(info.GetTextInputType()); 580 } 581 HandleGetOperation()582 void InputMethodController::HandleGetOperation() 583 { 584 IMSA_HILOGI("InputMethodController::start"); 585 if (isStopInput) { 586 IMSA_HILOGE("InputMethodController::text filed is not Focused"); 587 mSelectNewEnd = -1; 588 mInputDataChannel->NotifyGetOperationCompletion(); 589 return; 590 } 591 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 592 auto ret = textFieldReplyCountCv_.wait_for( 593 numLock, std::chrono::milliseconds(WAIT_TIME), [this] { return textFieldReplyCount_ == 0; }); 594 if (!ret) { 595 IMSA_HILOGE("InputMethodController::timeout"); 596 // timeout,reset the waitOnSelectionChangeNum_ to eliminate the impact on subsequent processing 597 textFieldReplyCount_ = 0; 598 } 599 IMSA_HILOGI("InputMethodController::notify"); 600 mInputDataChannel->NotifyGetOperationCompletion(); 601 } 602 IsCorrectParam(int32_t number)603 bool InputMethodController::IsCorrectParam(int32_t number) 604 { 605 if (mTextString.size() > INT_MAX || number < 0 || mSelectNewEnd < 0 || mSelectNewBegin < 0) { 606 IMSA_HILOGE("InputMethodController::param error, number: %{public}d, begin: %{public}d, end: %{public}d", 607 number, mSelectNewBegin, mSelectNewEnd); 608 return false; 609 } 610 if (mSelectNewBegin > mSelectNewEnd) { 611 int32_t temp = mSelectNewEnd; 612 mSelectNewEnd = mSelectNewBegin; 613 mSelectNewBegin = temp; 614 } 615 if (static_cast<size_t>(mSelectNewEnd) > mTextString.size()) { 616 IMSA_HILOGE("InputMethodController::param error, end: %{public}d, size: %{public}zu", mSelectNewEnd, 617 mTextString.size()); 618 return false; 619 } 620 return true; 621 } 622 GetTextBeforeCursor(int32_t number,std::u16string & text)623 int32_t InputMethodController::GetTextBeforeCursor(int32_t number, std::u16string &text) 624 { 625 IMSA_HILOGI("InputMethodController::GetTextBeforeCursor"); 626 text = u""; 627 if (!IsCorrectParam(number)) { 628 return ErrorCode::ERROR_CONTROLLER_INVOKING_FAILED; 629 } 630 int32_t startPos = (number <= mSelectNewBegin ? (mSelectNewBegin - number) : 0); 631 int32_t length = (number <= mSelectNewBegin ? number : mSelectNewBegin); 632 text = mTextString.substr(startPos, length); 633 return ErrorCode::NO_ERROR; 634 } 635 GetTextAfterCursor(int32_t number,std::u16string & text)636 int32_t InputMethodController::GetTextAfterCursor(int32_t number, std::u16string &text) 637 { 638 IMSA_HILOGI("InputMethodController::GetTextAfterCursor"); 639 text = u""; 640 if (!IsCorrectParam(number)) { 641 return ErrorCode::ERROR_CONTROLLER_INVOKING_FAILED; 642 } 643 text = mTextString.substr(mSelectNewEnd, number); 644 return ErrorCode::NO_ERROR; 645 } 646 dispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent)647 bool InputMethodController::dispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) 648 { 649 IMSA_HILOGI("InputMethodController::start"); 650 if (isStopInput) { 651 IMSA_HILOGD("InputMethodController::dispatchKeyEvent isStopInput"); 652 return false; 653 } 654 std::shared_ptr<IInputMethodAgent> agent = GetInputMethodAgent(); 655 if (agent == nullptr) { 656 IMSA_HILOGI("InputMethodController::dispatchKeyEvent agent is nullptr"); 657 return false; 658 } 659 MessageParcel data; 660 if (!(data.WriteInterfaceToken(agent->GetDescriptor()) 661 && data.WriteInt32(keyEvent->GetKeyCode()) 662 && data.WriteInt32(keyEvent->GetKeyAction()))) { 663 return false; 664 } 665 666 return agent->DispatchKeyEvent(data); 667 } 668 GetEnterKeyType(int32_t & keyType)669 int32_t InputMethodController::GetEnterKeyType(int32_t &keyType) 670 { 671 IMSA_HILOGI("InputMethodController::GetEnterKeyType"); 672 keyType = enterKeyType_; 673 return ErrorCode::NO_ERROR; 674 } 675 GetInputPattern(int32_t & inputpattern)676 int32_t InputMethodController::GetInputPattern(int32_t &inputpattern) 677 { 678 IMSA_HILOGI("InputMethodController::GetInputPattern"); 679 inputpattern = inputPattern_; 680 return ErrorCode::NO_ERROR; 681 } 682 SetCallingWindow(uint32_t windowId)683 void InputMethodController::SetCallingWindow(uint32_t windowId) 684 { 685 if (isStopInput) { 686 IMSA_HILOGD("InputMethodController::SetCallingWindow isStopInput"); 687 return; 688 } 689 IMSA_HILOGI("InputMethodController::SetCallingWindow windowId = %{public}d", windowId); 690 std::shared_ptr<IInputMethodAgent> agent = GetInputMethodAgent(); 691 if (agent == nullptr) { 692 IMSA_HILOGI("InputMethodController::SetCallingWindow agent is nullptr"); 693 return; 694 } 695 agent->SetCallingWindow(windowId); 696 } 697 SetInputMethodAgent(sptr<IRemoteObject> & object)698 void InputMethodController::SetInputMethodAgent(sptr<IRemoteObject> &object) 699 { 700 IMSA_HILOGI("run in SetInputMethodAgent"); 701 std::lock_guard<std::mutex> lock(agentLock_); 702 std::shared_ptr<IInputMethodAgent> agent = std::make_shared<InputMethodAgentProxy>(object); 703 if (agent == nullptr) { 704 IMSA_HILOGI("InputMethodController::SetInputMethodAgent agent is nullptr"); 705 return; 706 } 707 mAgent = agent; 708 } 709 GetInputMethodAgent()710 std::shared_ptr<IInputMethodAgent> InputMethodController::GetInputMethodAgent() 711 { 712 std::lock_guard<std::mutex> lock(agentLock_); 713 return mAgent; 714 } 715 ShowSoftKeyboard()716 int32_t InputMethodController::ShowSoftKeyboard() 717 { 718 IMSA_HILOGI("InputMethodController ShowSoftKeyboard"); 719 auto proxy = GetSystemAbilityProxy(); 720 if (proxy == nullptr) { 721 IMSA_HILOGE("proxy is nullptr"); 722 return ErrorCode::ERROR_EX_NULL_POINTER; 723 } 724 return proxy->ShowCurrentInput(); 725 } 726 HideSoftKeyboard()727 int32_t InputMethodController::HideSoftKeyboard() 728 { 729 IMSA_HILOGI("InputMethodController HideSoftKeyboard"); 730 auto proxy = GetSystemAbilityProxy(); 731 if (proxy == nullptr) { 732 IMSA_HILOGE("proxy is nullptr"); 733 return ErrorCode::ERROR_EX_NULL_POINTER; 734 } 735 return proxy->HideCurrentInput(); 736 } 737 StopInputSession()738 int32_t InputMethodController::StopInputSession() 739 { 740 IMSA_HILOGI("InputMethodController HideSoftKeyboard"); 741 isStopInput = true; 742 auto proxy = GetSystemAbilityProxy(); 743 if (proxy == nullptr) { 744 IMSA_HILOGE("proxy is nullptr"); 745 return ErrorCode::ERROR_EX_NULL_POINTER; 746 } 747 return proxy->StopInputSession(); 748 } 749 ShowOptionalInputMethod()750 int32_t InputMethodController::ShowOptionalInputMethod() 751 { 752 IMSA_HILOGI("InputMethodController::ShowOptionalInputMethod"); 753 auto proxy = GetSystemAbilityProxy(); 754 if (proxy == nullptr) { 755 IMSA_HILOGE("proxy is nullptr"); 756 return ErrorCode::ERROR_EX_NULL_POINTER; 757 } 758 return proxy->DisplayOptionalInputMethod(); 759 } 760 ListInputMethodSubtype(const Property & property,std::vector<SubProperty> & subProps)761 int32_t InputMethodController::ListInputMethodSubtype(const Property &property, std::vector<SubProperty> &subProps) 762 { 763 IMSA_HILOGI("InputMethodController::ListInputMethodSubtype"); 764 auto proxy = GetSystemAbilityProxy(); 765 if (proxy == nullptr) { 766 IMSA_HILOGE("proxy is nullptr"); 767 return ErrorCode::ERROR_EX_NULL_POINTER; 768 } 769 return proxy->ListInputMethodSubtype(property.name, subProps); 770 } 771 ListCurrentInputMethodSubtype(std::vector<SubProperty> & subProps)772 int32_t InputMethodController::ListCurrentInputMethodSubtype(std::vector<SubProperty> &subProps) 773 { 774 IMSA_HILOGI("InputMethodController::ListCurrentInputMethodSubtype"); 775 auto proxy = GetSystemAbilityProxy(); 776 if (proxy == nullptr) { 777 IMSA_HILOGE("proxy is nullptr"); 778 return ErrorCode::ERROR_EX_NULL_POINTER; 779 } 780 return proxy->ListCurrentInputMethodSubtype(subProps); 781 } 782 SwitchInputMethod(const std::string & name,const std::string & subName)783 int32_t InputMethodController::SwitchInputMethod(const std::string &name, const std::string &subName) 784 { 785 IMSA_HILOGI("InputMethodController::SwitchInputMethod"); 786 auto proxy = GetSystemAbilityProxy(); 787 if (proxy == nullptr) { 788 IMSA_HILOGE("proxy is nullptr"); 789 return ErrorCode::ERROR_EX_NULL_POINTER; 790 } 791 return proxy->SwitchInputMethod(name, subName); 792 } 793 } // namespace MiscServices 794 } // namespace OHOS 795