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(sptr<OnTextChangedListener> &listener, bool isShowKeyboard, 329 InputAttribute &attribute) 330 { 331 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 332 textFieldReplyCount_ = 0; 333 { 334 std::lock_guard<std::mutex> lock(textListenerLock_); 335 textListener = listener; 336 } 337 IMSA_HILOGI("InputMethodController::Attach"); 338 InputmethodTrace tracer("InputMethodController Attach trace."); 339 IMSA_HILOGI("InputMethodController::Attach isShowKeyboard %{public}s", isShowKeyboard ? "true" : "false"); 340 mAttribute = attribute; 341 PrepareInput(0, mClient, mInputDataChannel, mAttribute); 342 StartInput(mClient, isShowKeyboard); 343 } 344 ShowTextInput()345 void InputMethodController::ShowTextInput() 346 { 347 IMSA_HILOGI("InputMethodController::ShowTextInput"); 348 StartInput(mClient, true); 349 } 350 HideTextInput()351 void InputMethodController::HideTextInput() 352 { 353 IMSA_HILOGD("InputMethodController::HideTextInput"); 354 StopInput(mClient); 355 } 356 HideCurrentInput()357 int32_t InputMethodController::HideCurrentInput() 358 { 359 IMSA_HILOGD("InputMethodController::HideCurrentInput"); 360 auto proxy = GetSystemAbilityProxy(); 361 if (proxy == nullptr) { 362 IMSA_HILOGE("proxy is nullptr"); 363 return ErrorCode::ERROR_EX_NULL_POINTER; 364 } 365 return proxy->HideCurrentInputDeprecated(); 366 } 367 ShowCurrentInput()368 int32_t InputMethodController::ShowCurrentInput() 369 { 370 IMSA_HILOGI("InputMethodController::ShowCurrentInput"); 371 auto proxy = GetSystemAbilityProxy(); 372 if (proxy == nullptr) { 373 IMSA_HILOGE("proxy is nullptr"); 374 return ErrorCode::ERROR_EX_NULL_POINTER; 375 } 376 return proxy->ShowCurrentInputDeprecated(); 377 } 378 Close()379 void InputMethodController::Close() 380 { 381 ReleaseInput(mClient); 382 InputmethodTrace tracer("InputMethodController Close trace."); 383 { 384 std::lock_guard<std::mutex> lock(textListenerLock_); 385 textListener = nullptr; 386 } 387 IMSA_HILOGI("InputMethodController::Close"); 388 } 389 PrepareInput(int32_t displayId,sptr<IInputClient> & client,sptr<IInputDataChannel> & channel,InputAttribute & attribute)390 void InputMethodController::PrepareInput(int32_t displayId, sptr<IInputClient> &client, 391 sptr<IInputDataChannel> &channel, InputAttribute &attribute) 392 { 393 IMSA_HILOGI("InputMethodController::PrepareInput"); 394 auto proxy = GetSystemAbilityProxy(); 395 if (proxy == nullptr) { 396 IMSA_HILOGE("proxy is nullptr"); 397 return; 398 } 399 proxy->PrepareInput(displayId, client, channel, attribute); 400 } 401 DisplayOptionalInputMethod()402 int32_t InputMethodController::DisplayOptionalInputMethod() 403 { 404 IMSA_HILOGI("InputMethodController::DisplayOptionalInputMethod"); 405 auto proxy = GetSystemAbilityProxy(); 406 if (proxy == nullptr) { 407 IMSA_HILOGE("proxy is nullptr"); 408 return ErrorCode::ERROR_EX_NULL_POINTER; 409 } 410 return proxy->DisplayOptionalInputMethodDeprecated(); 411 } 412 ListInputMethodCommon(InputMethodStatus status,std::vector<Property> & props)413 int32_t InputMethodController::ListInputMethodCommon(InputMethodStatus status, std::vector<Property> &props) 414 { 415 IMSA_HILOGI("InputMethodController::ListInputMethodCommon"); 416 auto proxy = GetSystemAbilityProxy(); 417 if (proxy == nullptr) { 418 IMSA_HILOGE("proxy is nullptr"); 419 return ErrorCode::ERROR_EX_NULL_POINTER; 420 } 421 return proxy->ListInputMethod(status, props); 422 } 423 ListInputMethod(std::vector<Property> & props)424 int32_t InputMethodController::ListInputMethod(std::vector<Property> &props) 425 { 426 IMSA_HILOGI("InputMethodController::listInputMethod"); 427 return ListInputMethodCommon(ALL, props); 428 } 429 ListInputMethod(bool enable,std::vector<Property> & props)430 int32_t InputMethodController::ListInputMethod(bool enable, std::vector<Property> &props) 431 { 432 IMSA_HILOGI("InputMethodController::listInputMethod enable = %{public}s", enable ? "ENABLE" : "DISABLE"); 433 return ListInputMethodCommon(enable ? ENABLE : DISABLE, props); 434 } 435 GetCurrentInputMethod()436 std::shared_ptr<Property> InputMethodController::GetCurrentInputMethod() 437 { 438 IMSA_HILOGD("InputMethodController::GetCurrentInputMethod"); 439 auto proxy = GetSystemAbilityProxy(); 440 if (proxy == nullptr) { 441 IMSA_HILOGE("proxy is nullptr"); 442 return nullptr; 443 } 444 auto property = proxy->GetCurrentInputMethod(); 445 if (property == nullptr) { 446 IMSA_HILOGE("InputMethodController::GetCurrentInputMethod property is nullptr"); 447 return nullptr; 448 } 449 return property; 450 } 451 GetCurrentInputMethodSubtype()452 std::shared_ptr<SubProperty> InputMethodController::GetCurrentInputMethodSubtype() 453 { 454 IMSA_HILOGD("InputMethodController::GetCurrentInputMethod"); 455 auto proxy = GetSystemAbilityProxy(); 456 if (proxy == nullptr) { 457 IMSA_HILOGE("proxy is nullptr"); 458 return nullptr; 459 } 460 auto property = proxy->GetCurrentInputMethodSubtype(); 461 if (property == nullptr) { 462 IMSA_HILOGE("InputMethodController::GetCurrentInputMethodSubtype property is nullptr"); 463 return nullptr; 464 } 465 return property; 466 } 467 StartInput(sptr<IInputClient> & client,bool isShowKeyboard)468 void InputMethodController::StartInput(sptr<IInputClient> &client, bool isShowKeyboard) 469 { 470 IMSA_HILOGI("InputMethodController::StartInput"); 471 isStopInput = false; 472 auto proxy = GetSystemAbilityProxy(); 473 if (proxy == nullptr) { 474 IMSA_HILOGE("proxy is nullptr"); 475 return; 476 } 477 proxy->StartInput(client, isShowKeyboard); 478 } 479 ReleaseInput(sptr<IInputClient> & client)480 void InputMethodController::ReleaseInput(sptr<IInputClient> &client) 481 { 482 IMSA_HILOGD("InputMethodController::ReleaseInput"); 483 isStopInput = true; 484 auto proxy = GetSystemAbilityProxy(); 485 if (proxy == nullptr) { 486 IMSA_HILOGE("proxy is nullptr"); 487 return; 488 } 489 proxy->ReleaseInput(client); 490 } 491 StopInput(sptr<IInputClient> & client)492 void InputMethodController::StopInput(sptr<IInputClient> &client) 493 { 494 IMSA_HILOGD("InputMethodController::StopInput"); 495 isStopInput = true; 496 auto proxy = GetSystemAbilityProxy(); 497 if (proxy == nullptr) { 498 IMSA_HILOGE("proxy is nullptr"); 499 return; 500 } 501 proxy->StopInput(client); 502 } 503 OnRemoteSaDied(const wptr<IRemoteObject> & remote)504 void InputMethodController::OnRemoteSaDied(const wptr<IRemoteObject> &remote) 505 { 506 IMSA_HILOGE("input method service death"); 507 std::lock_guard<std::mutex> lock(abilityLock_); 508 abilityManager_ = nullptr; 509 } 510 ImsaDeathRecipient()511 ImsaDeathRecipient::ImsaDeathRecipient() 512 { 513 } 514 OnRemoteDied(const wptr<IRemoteObject> & object)515 void ImsaDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object) 516 { 517 InputMethodController::GetInstance()->OnRemoteSaDied(object); 518 } 519 OnCursorUpdate(CursorInfo cursorInfo)520 void InputMethodController::OnCursorUpdate(CursorInfo cursorInfo) 521 { 522 if (isStopInput) { 523 IMSA_HILOGD("InputMethodController::OnCursorUpdate isStopInput"); 524 return; 525 } 526 std::shared_ptr<IInputMethodAgent> agent = GetInputMethodAgent(); 527 if (agent == nullptr) { 528 IMSA_HILOGI("InputMethodController::OnCursorUpdate agent is nullptr"); 529 return; 530 } 531 if (cursorInfo_.left == cursorInfo.left && cursorInfo_.top == cursorInfo.top 532 && cursorInfo_.height == cursorInfo.height) { 533 return; 534 } 535 cursorInfo_ = cursorInfo; 536 agent->OnCursorUpdate(cursorInfo.left, cursorInfo.top, cursorInfo.height); 537 } 538 OnSelectionChange(std::u16string text,int start,int end)539 void InputMethodController::OnSelectionChange(std::u16string text, int start, int end) 540 { 541 IMSA_HILOGI("size: %{public}zu, start: %{public}d, end: %{public}d, replyCount: %{public}d", text.size(), start, 542 end, textFieldReplyCount_); 543 if (isStopInput) { 544 IMSA_HILOGD("InputMethodController::OnSelectionChange isStopInput"); 545 return; 546 } 547 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 548 if (textFieldReplyCount_ > 0 549 && (text.size() != mTextString.size() || start != mSelectNewBegin || end != mSelectNewEnd)) { 550 textFieldReplyCount_--; 551 } 552 if (textFieldReplyCount_ == 0) { 553 textFieldReplyCountCv_.notify_one(); 554 } 555 if (mTextString == text && mSelectNewBegin == start && mSelectNewEnd == end) { 556 return; 557 } 558 mTextString = text; 559 mSelectOldBegin = mSelectNewBegin; 560 mSelectOldEnd = mSelectNewEnd; 561 mSelectNewBegin = start; 562 mSelectNewEnd = end; 563 std::shared_ptr<IInputMethodAgent> agent = GetInputMethodAgent(); 564 if (agent == nullptr) { 565 IMSA_HILOGI("InputMethodController::OnSelectionChange agent is nullptr"); 566 return; 567 } 568 agent->OnSelectionChange(mTextString, mSelectOldBegin, mSelectOldEnd, mSelectNewBegin, mSelectNewEnd); 569 } 570 OnConfigurationChange(Configuration info)571 void InputMethodController::OnConfigurationChange(Configuration info) 572 { 573 IMSA_HILOGI("InputMethodController::OnConfigurationChange"); 574 enterKeyType_ = static_cast<uint32_t>(info.GetEnterKeyType()); 575 inputPattern_ = static_cast<uint32_t>(info.GetTextInputType()); 576 } 577 HandleGetOperation()578 void InputMethodController::HandleGetOperation() 579 { 580 IMSA_HILOGI("InputMethodController::start"); 581 if (isStopInput) { 582 IMSA_HILOGE("InputMethodController::text filed is not Focused"); 583 mSelectNewEnd = -1; 584 mInputDataChannel->NotifyGetOperationCompletion(); 585 return; 586 } 587 std::unique_lock<std::mutex> numLock(textFieldReplyCountLock_); 588 auto ret = textFieldReplyCountCv_.wait_for( 589 numLock, std::chrono::milliseconds(WAIT_TIME), [this] { return textFieldReplyCount_ == 0; }); 590 if (!ret) { 591 IMSA_HILOGE("InputMethodController::timeout"); 592 // timeout,reset the waitOnSelectionChangeNum_ to eliminate the impact on subsequent processing 593 textFieldReplyCount_ = 0; 594 } 595 IMSA_HILOGI("InputMethodController::notify"); 596 mInputDataChannel->NotifyGetOperationCompletion(); 597 } 598 IsCorrectParam(int32_t number)599 bool InputMethodController::IsCorrectParam(int32_t number) 600 { 601 if (mTextString.size() > INT_MAX || number < 0 || mSelectNewEnd < 0 || mSelectNewBegin < 0) { 602 IMSA_HILOGE("InputMethodController::param error, number: %{public}d, begin: %{public}d, end: %{public}d", 603 number, mSelectNewBegin, mSelectNewEnd); 604 return false; 605 } 606 if (mSelectNewBegin > mSelectNewEnd) { 607 int32_t temp = mSelectNewEnd; 608 mSelectNewEnd = mSelectNewBegin; 609 mSelectNewBegin = temp; 610 } 611 if (static_cast<size_t>(mSelectNewEnd) > mTextString.size()) { 612 IMSA_HILOGE("InputMethodController::param error, end: %{public}d, size: %{public}zu", mSelectNewEnd, 613 mTextString.size()); 614 return false; 615 } 616 return true; 617 } 618 GetTextBeforeCursor(int32_t number,std::u16string & text)619 int32_t InputMethodController::GetTextBeforeCursor(int32_t number, std::u16string &text) 620 { 621 IMSA_HILOGI("InputMethodController::GetTextBeforeCursor"); 622 text = u""; 623 if (!IsCorrectParam(number)) { 624 return ErrorCode::ERROR_CONTROLLER_INVOKING_FAILED; 625 } 626 int32_t startPos = (number <= mSelectNewBegin ? (mSelectNewBegin - number) : 0); 627 int32_t length = (number <= mSelectNewBegin ? number : mSelectNewBegin); 628 text = mTextString.substr(startPos, length); 629 return ErrorCode::NO_ERROR; 630 } 631 GetTextAfterCursor(int32_t number,std::u16string & text)632 int32_t InputMethodController::GetTextAfterCursor(int32_t number, std::u16string &text) 633 { 634 IMSA_HILOGI("InputMethodController::GetTextAfterCursor"); 635 text = u""; 636 if (!IsCorrectParam(number)) { 637 return ErrorCode::ERROR_CONTROLLER_INVOKING_FAILED; 638 } 639 text = mTextString.substr(mSelectNewEnd, number); 640 return ErrorCode::NO_ERROR; 641 } 642 dispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent)643 bool InputMethodController::dispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) 644 { 645 IMSA_HILOGI("InputMethodController::start"); 646 if (isStopInput) { 647 IMSA_HILOGD("InputMethodController::dispatchKeyEvent isStopInput"); 648 return false; 649 } 650 std::shared_ptr<IInputMethodAgent> agent = GetInputMethodAgent(); 651 if (agent == nullptr) { 652 IMSA_HILOGI("InputMethodController::dispatchKeyEvent agent is nullptr"); 653 return false; 654 } 655 MessageParcel data; 656 if (!(data.WriteInterfaceToken(agent->GetDescriptor()) 657 && data.WriteInt32(keyEvent->GetKeyCode()) 658 && data.WriteInt32(keyEvent->GetKeyAction()))) { 659 return false; 660 } 661 662 return agent->DispatchKeyEvent(data); 663 } 664 GetEnterKeyType(int32_t & keyType)665 int32_t InputMethodController::GetEnterKeyType(int32_t &keyType) 666 { 667 IMSA_HILOGI("InputMethodController::GetEnterKeyType"); 668 keyType = enterKeyType_; 669 return ErrorCode::NO_ERROR; 670 } 671 GetInputPattern(int32_t & inputpattern)672 int32_t InputMethodController::GetInputPattern(int32_t &inputpattern) 673 { 674 IMSA_HILOGI("InputMethodController::GetInputPattern"); 675 inputpattern = inputPattern_; 676 return ErrorCode::NO_ERROR; 677 } 678 SetCallingWindow(uint32_t windowId)679 void InputMethodController::SetCallingWindow(uint32_t windowId) 680 { 681 if (isStopInput) { 682 IMSA_HILOGD("InputMethodController::SetCallingWindow isStopInput"); 683 return; 684 } 685 IMSA_HILOGI("InputMethodController::SetCallingWindow windowId = %{public}d", windowId); 686 std::shared_ptr<IInputMethodAgent> agent = GetInputMethodAgent(); 687 if (agent == nullptr) { 688 IMSA_HILOGI("InputMethodController::SetCallingWindow agent is nullptr"); 689 return; 690 } 691 agent->SetCallingWindow(windowId); 692 } 693 SetInputMethodAgent(sptr<IRemoteObject> & object)694 void InputMethodController::SetInputMethodAgent(sptr<IRemoteObject> &object) 695 { 696 IMSA_HILOGI("run in SetInputMethodAgent"); 697 std::lock_guard<std::mutex> lock(agentLock_); 698 std::shared_ptr<IInputMethodAgent> agent = std::make_shared<InputMethodAgentProxy>(object); 699 if (agent == nullptr) { 700 IMSA_HILOGI("InputMethodController::SetInputMethodAgent agent is nullptr"); 701 return; 702 } 703 mAgent = agent; 704 } 705 GetInputMethodAgent()706 std::shared_ptr<IInputMethodAgent> InputMethodController::GetInputMethodAgent() 707 { 708 std::lock_guard<std::mutex> lock(agentLock_); 709 return mAgent; 710 } 711 ShowSoftKeyboard()712 int32_t InputMethodController::ShowSoftKeyboard() 713 { 714 IMSA_HILOGI("InputMethodController ShowSoftKeyboard"); 715 auto proxy = GetSystemAbilityProxy(); 716 if (proxy == nullptr) { 717 IMSA_HILOGE("proxy is nullptr"); 718 return ErrorCode::ERROR_EX_NULL_POINTER; 719 } 720 return proxy->ShowCurrentInput(); 721 } 722 HideSoftKeyboard()723 int32_t InputMethodController::HideSoftKeyboard() 724 { 725 IMSA_HILOGI("InputMethodController HideSoftKeyboard"); 726 auto proxy = GetSystemAbilityProxy(); 727 if (proxy == nullptr) { 728 IMSA_HILOGE("proxy is nullptr"); 729 return ErrorCode::ERROR_EX_NULL_POINTER; 730 } 731 return proxy->HideCurrentInput(); 732 } 733 StopInputSession()734 int32_t InputMethodController::StopInputSession() 735 { 736 IMSA_HILOGI("InputMethodController HideSoftKeyboard"); 737 isStopInput = true; 738 auto proxy = GetSystemAbilityProxy(); 739 if (proxy == nullptr) { 740 IMSA_HILOGE("proxy is nullptr"); 741 return ErrorCode::ERROR_EX_NULL_POINTER; 742 } 743 return proxy->StopInputSession(); 744 } 745 ShowOptionalInputMethod()746 int32_t InputMethodController::ShowOptionalInputMethod() 747 { 748 IMSA_HILOGI("InputMethodController::ShowOptionalInputMethod"); 749 auto proxy = GetSystemAbilityProxy(); 750 if (proxy == nullptr) { 751 IMSA_HILOGE("proxy is nullptr"); 752 return ErrorCode::ERROR_EX_NULL_POINTER; 753 } 754 return proxy->DisplayOptionalInputMethod(); 755 } 756 ListInputMethodSubtype(const Property & property,std::vector<SubProperty> & subProps)757 int32_t InputMethodController::ListInputMethodSubtype(const Property &property, std::vector<SubProperty> &subProps) 758 { 759 IMSA_HILOGI("InputMethodController::ListInputMethodSubtype"); 760 auto proxy = GetSystemAbilityProxy(); 761 if (proxy == nullptr) { 762 IMSA_HILOGE("proxy is nullptr"); 763 return ErrorCode::ERROR_EX_NULL_POINTER; 764 } 765 return proxy->ListInputMethodSubtype(property.name, subProps); 766 } 767 ListCurrentInputMethodSubtype(std::vector<SubProperty> & subProps)768 int32_t InputMethodController::ListCurrentInputMethodSubtype(std::vector<SubProperty> &subProps) 769 { 770 IMSA_HILOGI("InputMethodController::ListCurrentInputMethodSubtype"); 771 auto proxy = GetSystemAbilityProxy(); 772 if (proxy == nullptr) { 773 IMSA_HILOGE("proxy is nullptr"); 774 return ErrorCode::ERROR_EX_NULL_POINTER; 775 } 776 return proxy->ListCurrentInputMethodSubtype(subProps); 777 } 778 SwitchInputMethod(const std::string & name,const std::string & subName)779 int32_t InputMethodController::SwitchInputMethod(const std::string &name, const std::string &subName) 780 { 781 IMSA_HILOGI("InputMethodController::SwitchInputMethod"); 782 auto proxy = GetSystemAbilityProxy(); 783 if (proxy == nullptr) { 784 IMSA_HILOGE("proxy is nullptr"); 785 return ErrorCode::ERROR_EX_NULL_POINTER; 786 } 787 return proxy->SwitchInputMethod(name, subName); 788 } 789 } // namespace MiscServices 790 } // namespace OHOS 791