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_ability.h" 17 18 #include "input_method_agent_proxy.h" 19 #include "input_method_agent_stub.h" 20 #include "input_method_core_proxy.h" 21 #include "input_method_core_stub.h" 22 #include "input_method_utils.h" 23 #include "iservice_registry.h" 24 #include "message_parcel.h" 25 #include "para_handle.h" 26 #include "string_ex.h" 27 #include "system_ability_definition.h" 28 #include "utils.h" 29 30 namespace OHOS { 31 namespace MiscServices { 32 class MessageHandler; 33 using namespace MessageID; 34 sptr<InputMethodAbility> InputMethodAbility::instance_; 35 std::mutex InputMethodAbility::instanceLock_; 36 InputMethodAbility()37 InputMethodAbility::InputMethodAbility() : stop_(false) 38 { 39 writeInputChannel = nullptr; 40 Initialize(); 41 } 42 ~InputMethodAbility()43 InputMethodAbility::~InputMethodAbility() 44 { 45 IMSA_HILOGI("InputMethodAbility::~InputMethodAbility"); 46 instance_ = nullptr; 47 if (msgHandler != nullptr) { 48 delete msgHandler; 49 msgHandler = nullptr; 50 } 51 stop_ = true; 52 } 53 GetInstance()54 sptr<InputMethodAbility> InputMethodAbility::GetInstance() 55 { 56 IMSA_HILOGI("InputMethodAbility::GetInstance"); 57 if (instance_ == nullptr) { 58 std::lock_guard<std::mutex> autoLock(instanceLock_); 59 if (instance_ == nullptr) { 60 IMSA_HILOGI("InputMethodAbility::GetInstance need new IMA"); 61 instance_ = new InputMethodAbility(); 62 } 63 } 64 return instance_; 65 } 66 GetImsaProxy()67 sptr<InputMethodSystemAbilityProxy> InputMethodAbility::GetImsaProxy() 68 { 69 IMSA_HILOGI("InputMethodAbility::GetImsaProxy"); 70 sptr<ISystemAbilityManager> systemAbilityManager = 71 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 72 if (systemAbilityManager == nullptr) { 73 IMSA_HILOGI("systemAbilityManager is nullptr"); 74 return nullptr; 75 } 76 77 auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, ""); 78 if (systemAbility == nullptr) { 79 IMSA_HILOGI("systemAbility is nullptr"); 80 return nullptr; 81 } 82 if (deathRecipientPtr_ == nullptr) { 83 deathRecipientPtr_ = new (std::nothrow) ServiceDeathRecipient(); 84 if (deathRecipientPtr_ == nullptr) { 85 IMSA_HILOGE("failed to new ServiceDeathRecipient"); 86 return nullptr; 87 } 88 } 89 if ((systemAbility->IsProxyObject()) && (!systemAbility->AddDeathRecipient(deathRecipientPtr_))) { 90 IMSA_HILOGE("failed to add death recipient."); 91 } 92 sptr<InputMethodSystemAbilityProxy> iface = new InputMethodSystemAbilityProxy(systemAbility); 93 return iface; 94 } 95 OnRemoteDied(const wptr<IRemoteObject> & object)96 void InputMethodAbility::ServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object) 97 { 98 IMSA_HILOGI("input method service died"); 99 if (listener != nullptr) { 100 listener->OnInputStop(ParaHandle::GetDefaultIme(Utils::GetUserId())); 101 } 102 } 103 SetCoreAndAgent()104 void InputMethodAbility::SetCoreAndAgent() 105 { 106 IMSA_HILOGI("InputMethodAbility::SetCoreAndAgent"); 107 mImms = GetImsaProxy(); 108 if (mImms == nullptr) { 109 IMSA_HILOGI("InputMethodAbility::SetCoreAndAgent() mImms is nullptr"); 110 return; 111 } 112 sptr<InputMethodCoreStub> stub = new InputMethodCoreStub(0); 113 stub->SetMessageHandler(msgHandler); 114 sptr<IInputMethodCore> stub2 = stub; 115 116 sptr<InputMethodAgentStub> inputMethodAgentStub(new InputMethodAgentStub()); 117 inputMethodAgentStub->SetMessageHandler(msgHandler); 118 sptr<IInputMethodAgent> inputMethodAgent = sptr(new InputMethodAgentProxy(inputMethodAgentStub)); 119 120 MessageParcel data; 121 if (!(data.WriteInterfaceToken(mImms->GetDescriptor()) 122 && data.WriteRemoteObject(stub2->AsObject()) 123 && data.WriteRemoteObject(inputMethodAgent->AsObject()))) { 124 return; 125 } 126 mImms->SetCoreAndAgent(data); 127 } 128 Initialize()129 void InputMethodAbility::Initialize() 130 { 131 IMSA_HILOGI("InputMethodAbility::Initialize"); 132 msgHandler = new MessageHandler(); 133 workThreadHandler = std::thread([this] { 134 WorkThread(); 135 }); 136 137 SetCoreAndAgent(); 138 } 139 setImeListener(sptr<JsInputMethodEngineListener> & imeListener)140 void InputMethodAbility::setImeListener(sptr<JsInputMethodEngineListener> &imeListener) 141 { 142 IMSA_HILOGI("InputMethodAbility::setImeListener"); 143 if (imeListener_ == nullptr) { 144 imeListener_ = imeListener; 145 } 146 if (deathRecipientPtr_ != nullptr && deathRecipientPtr_->listener == nullptr) { 147 deathRecipientPtr_->listener = imeListener; 148 } 149 } 150 setKdListener(sptr<JsKeyboardDelegateListener> & kdListener)151 void InputMethodAbility::setKdListener(sptr<JsKeyboardDelegateListener> &kdListener) 152 { 153 IMSA_HILOGI("InputMethodAbility::setKdListener"); 154 if (kdListener_ == nullptr) { 155 kdListener_ = kdListener; 156 } 157 } 158 WorkThread()159 void InputMethodAbility::WorkThread() 160 { 161 while (!stop_) { 162 Message *msg = msgHandler->GetMessage(); 163 switch (msg->msgId_) { 164 case MSG_ID_INITIALIZE_INPUT: { 165 OnInitialInput(msg); 166 break; 167 } 168 case MSG_ID_INIT_INPUT_CONTROL_CHANNEL: { 169 OnInitInputControlChannel(msg); 170 break; 171 } 172 case MSG_ID_SET_CLIENT_STATE: { 173 MessageParcel *data = msg->msgContent_; 174 isBindClient = data->ReadBool(); 175 break; 176 } 177 case MSG_ID_START_INPUT: { 178 OnStartInput(msg); 179 break; 180 } 181 case MSG_ID_STOP_INPUT: { 182 OnStopInput(msg); 183 break; 184 } 185 case MSG_ID_SHOW_KEYBOARD: { 186 OnShowKeyboard(msg); 187 break; 188 } 189 case MSG_ID_HIDE_KEYBOARD: { 190 OnHideKeyboard(msg); 191 break; 192 } 193 case MSG_ID_ON_CURSOR_UPDATE: { 194 OnCursorUpdate(msg); 195 break; 196 } 197 case MSG_ID_ON_SELECTION_CHANGE: { 198 OnSelectionChange(msg); 199 break; 200 } 201 case MSG_ID_STOP_INPUT_SERVICE:{ 202 MessageParcel *data = msg->msgContent_; 203 std::string imeId = Str16ToStr8(data->ReadString16()); 204 if (imeListener_ != nullptr) { 205 imeListener_->OnInputStop(imeId); 206 } 207 break; 208 } 209 default: { 210 break; 211 } 212 } 213 delete msg; 214 msg = nullptr; 215 } 216 } 217 OnInitialInput(Message * msg)218 void InputMethodAbility::OnInitialInput(Message *msg) 219 { 220 IMSA_HILOGI("InputMethodAbility::OnInitialInput"); 221 MessageParcel *data = msg->msgContent_; 222 displyId = data->ReadInt32(); 223 sptr<IRemoteObject> channelObject = data->ReadRemoteObject(); 224 if (channelObject == nullptr) { 225 IMSA_HILOGI("InputMethodAbility::OnInitialInput channelObject is nullptr"); 226 return; 227 } 228 SetInputControlChannel(channelObject); 229 } 230 OnInitInputControlChannel(Message * msg)231 void InputMethodAbility::OnInitInputControlChannel(Message *msg) 232 { 233 IMSA_HILOGI("InputMethodAbility::OnInitInputControlChannel"); 234 MessageParcel *data = msg->msgContent_; 235 sptr<IRemoteObject> channelObject = data->ReadRemoteObject(); 236 if (channelObject == nullptr) { 237 IMSA_HILOGI("InputMethodAbility::OnInitInputControlChannel channelObject is nullptr"); 238 return; 239 } 240 SetInputControlChannel(channelObject); 241 } 242 OnStartInput(Message * msg)243 void InputMethodAbility::OnStartInput(Message *msg) 244 { 245 IMSA_HILOGI("InputMethodAbility::OnStartInput"); 246 MessageParcel *data = msg->msgContent_; 247 sptr<IRemoteObject> channelObject = data->ReadRemoteObject(); 248 if (channelObject == nullptr) { 249 IMSA_HILOGI("InputMethodAbility::OnStartInput channelObject is nullptr"); 250 return; 251 } 252 SetInputDataChannel(channelObject); 253 editorAttribute = data->ReadParcelable<InputAttribute>(); 254 if (!editorAttribute) { 255 IMSA_HILOGI("InputMethodAbility::OnStartInput editorAttribute is nullptr"); 256 } 257 mSupportPhysicalKbd = data->ReadBool(); 258 } 259 OnShowKeyboard(Message * msg)260 void InputMethodAbility::OnShowKeyboard(Message *msg) 261 { 262 IMSA_HILOGI("InputMethodAbility::OnShowKeyboard"); 263 MessageParcel *data = msg->msgContent_; 264 sptr<IRemoteObject> channelObject = data->ReadRemoteObject(); 265 if (channelObject == nullptr) { 266 IMSA_HILOGI("InputMethodAbility::OnShowKeyboard channelObject is nullptr"); 267 return; 268 } 269 SetInputDataChannel(channelObject); 270 ShowInputWindow(); 271 } 272 OnHideKeyboard(Message * msg)273 void InputMethodAbility::OnHideKeyboard(Message *msg) 274 { 275 IMSA_HILOGI("InputMethodAbility::OnHideKeyboard"); 276 DissmissInputWindow(); 277 } 278 OnStopInput(Message * msg)279 void InputMethodAbility::OnStopInput(Message *msg) 280 { 281 IMSA_HILOGI("InputMethodAbility::OnStopInput"); 282 if (writeInputChannel != nullptr) { 283 delete writeInputChannel; 284 writeInputChannel = nullptr; 285 } 286 } 287 DispatchKeyEvent(int32_t keyCode,int32_t keyStatus)288 bool InputMethodAbility::DispatchKeyEvent(int32_t keyCode, int32_t keyStatus) 289 { 290 IMSA_HILOGI("InputMethodAbility::DispatchKeyEvent: key = %{public}d, status = %{public}d", keyCode, keyStatus); 291 if (!isBindClient) { 292 IMSA_HILOGI("InputMethodAbility::DispatchKeyEvent abort. no client"); 293 return false; 294 } 295 if (kdListener_ == nullptr) { 296 IMSA_HILOGI("InputMethodAbility::DispatchKeyEvent kdListener_ is nullptr"); 297 return false; 298 } 299 return kdListener_->OnKeyEvent(keyCode, keyStatus); 300 } 301 SetCallingWindow(uint32_t windowId)302 void InputMethodAbility::SetCallingWindow(uint32_t windowId) 303 { 304 IMSA_HILOGI("InputMethodAbility::SetCallingWindow"); 305 306 if (!imeListener_) { 307 IMSA_HILOGI("InputMethodAbility::SetCallingWindow imeListener_ is nullptr"); 308 return; 309 } 310 imeListener_->OnSetCallingWindow(windowId); 311 return; 312 } 313 314 OnCursorUpdate(Message * msg)315 void InputMethodAbility::OnCursorUpdate(Message *msg) 316 { 317 IMSA_HILOGI("InputMethodAbility::OnCursorUpdate"); 318 MessageParcel *data = msg->msgContent_; 319 int32_t positionX = data->ReadInt32(); 320 int32_t positionY = data->ReadInt32(); 321 int32_t height = data->ReadInt32(); 322 if (kdListener_ == nullptr) { 323 IMSA_HILOGI("InputMethodAbility::OnCursorUpdate kdListener_ is nullptr"); 324 return; 325 } 326 kdListener_->OnCursorUpdate(positionX, positionY, height); 327 } 328 OnSelectionChange(Message * msg)329 void InputMethodAbility::OnSelectionChange(Message *msg) 330 { 331 IMSA_HILOGI("InputMethodAbility::OnSelectionChange"); 332 MessageParcel *data = msg->msgContent_; 333 std::string text = Str16ToStr8(data->ReadString16()); 334 int32_t oldBegin = data->ReadInt32(); 335 int32_t oldEnd = data->ReadInt32(); 336 int32_t newBegin = data->ReadInt32(); 337 int32_t newEnd = data->ReadInt32(); 338 339 if (kdListener_ == nullptr) { 340 IMSA_HILOGI("InputMethodAbility::OnSelectionChange kdListener_ is nullptr"); 341 return; 342 } 343 kdListener_->OnTextChange(text); 344 345 kdListener_->OnSelectionChange(oldBegin, oldEnd, newBegin, newEnd); 346 } 347 ShowInputWindow()348 void InputMethodAbility::ShowInputWindow() 349 { 350 IMSA_HILOGI("InputMethodAbility::ShowInputWindow"); 351 if (imeListener_ == nullptr) { 352 IMSA_HILOGI("InputMethodAbility::ShowInputWindow imeListener_ is nullptr"); 353 return; 354 } 355 imeListener_->OnInputStart(); 356 imeListener_->OnKeyboardStatus(true); 357 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 358 if (channel == nullptr) { 359 IMSA_HILOGI("InputMethodAbility::ShowInputWindow channel is nullptr"); 360 return; 361 } 362 channel->SendKeyboardStatus(KEYBOARD_SHOW); 363 } 364 DissmissInputWindow()365 void InputMethodAbility::DissmissInputWindow() 366 { 367 IMSA_HILOGI("InputMethodAbility::DissmissInputWindow"); 368 if (imeListener_ == nullptr) { 369 IMSA_HILOGI("InputMethodAbility::DissmissInputWindow imeListener_ is nullptr"); 370 return; 371 } 372 imeListener_->OnKeyboardStatus(false); 373 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 374 if (channel == nullptr) { 375 IMSA_HILOGI("InputMethodAbility::DismissInputWindow channel is nullptr"); 376 return; 377 } 378 channel->SendKeyboardStatus(KEYBOARD_HIDE); 379 } 380 InsertText(const std::string text)381 bool InputMethodAbility::InsertText(const std::string text) 382 { 383 IMSA_HILOGI("InputMethodAbility::InsertText"); 384 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 385 if (channel == nullptr) { 386 IMSA_HILOGI("InputMethodAbility::InsertText channel is nullptr"); 387 return false; 388 } 389 390 return channel->InsertText(Utils::to_utf16(text)); 391 } 392 DeleteForward(int32_t length)393 void InputMethodAbility::DeleteForward(int32_t length) 394 { 395 IMSA_HILOGI("InputMethodAbility::DeleteForward"); 396 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 397 if (channel == nullptr) { 398 IMSA_HILOGI("InputMethodAbility::DeleteForward channel is nullptr"); 399 return; 400 } 401 channel->DeleteForward(length); 402 } 403 DeleteBackward(int32_t length)404 void InputMethodAbility::DeleteBackward(int32_t length) 405 { 406 IMSA_HILOGI("InputMethodAbility::DeleteBackward"); 407 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 408 if (channel == nullptr) { 409 IMSA_HILOGI("InputMethodAbility::DeleteBackward channel is nullptr"); 410 return; 411 } 412 channel->DeleteBackward(length); 413 } 414 SendFunctionKey(int32_t funcKey)415 void InputMethodAbility::SendFunctionKey(int32_t funcKey) 416 { 417 IMSA_HILOGI("InputMethodAbility::SendFunctionKey"); 418 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 419 if (channel == nullptr) { 420 IMSA_HILOGI("InputMethodAbility::SendFunctionKey channel is nullptr"); 421 return; 422 } 423 channel->SendFunctionKey(funcKey); 424 } 425 HideKeyboardSelf()426 void InputMethodAbility::HideKeyboardSelf() 427 { 428 IMSA_HILOGI("InputMethodAbility::HideKeyboardSelf"); 429 std::shared_ptr<InputControlChannelProxy> channel = GetInputControlChannel(); 430 if (channel == nullptr) { 431 IMSA_HILOGI("InputMethodAbility::HideKeyboardSelf channel is nullptr"); 432 return; 433 } 434 channel->hideKeyboardSelf(1); 435 } 436 GetTextBeforeCursor(int32_t number)437 std::u16string InputMethodAbility::GetTextBeforeCursor(int32_t number) 438 { 439 IMSA_HILOGI("InputMethodAbility::GetTextBeforeCursor"); 440 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 441 if (channel == nullptr) { 442 IMSA_HILOGI("InputMethodAbility::GetTextBeforeCursor channel is nullptr"); 443 return u""; 444 } 445 return channel->GetTextBeforeCursor(number); 446 } 447 GetTextAfterCursor(int32_t number)448 std::u16string InputMethodAbility::GetTextAfterCursor(int32_t number) 449 { 450 IMSA_HILOGI("InputMethodAbility::GetTextAfterCursor"); 451 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 452 if (channel == nullptr) { 453 IMSA_HILOGI("InputMethodAbility::GetTextAfterCursor channel is nullptr"); 454 return u""; 455 } 456 return channel->GetTextAfterCursor(number); 457 } 458 MoveCursor(int32_t keyCode)459 void InputMethodAbility::MoveCursor(int32_t keyCode) 460 { 461 IMSA_HILOGI("InputMethodAbility::MoveCursor"); 462 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 463 if (channel == nullptr) { 464 IMSA_HILOGI("InputMethodAbility::MoveCursor channel is nullptr"); 465 return; 466 } 467 468 channel->MoveCursor(keyCode); 469 } 470 GetEnterKeyType()471 int32_t InputMethodAbility::GetEnterKeyType() 472 { 473 IMSA_HILOGI("InputMethodAbility::GetEnterKeyType"); 474 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 475 if (channel == nullptr) { 476 IMSA_HILOGI("InputMethodAbility::GetEnterKeyType channel is nullptr"); 477 return -1; 478 } 479 return channel->GetEnterKeyType(); 480 } 481 GetInputPattern()482 int32_t InputMethodAbility::GetInputPattern() 483 { 484 IMSA_HILOGI("InputMethodAbility::GetInputPattern"); 485 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 486 if (channel == nullptr) { 487 IMSA_HILOGI("InputMethodAbility::GetInputPattern channel is nullptr"); 488 return -1; 489 } 490 return channel->GetInputPattern(); 491 } 492 StopInput()493 void InputMethodAbility::StopInput() 494 { 495 IMSA_HILOGI("InputMethodAbility::StopInput"); 496 std::shared_ptr<InputDataChannelProxy> channel = GetInputDataChannel(); 497 if (channel == nullptr) { 498 IMSA_HILOGI("InputMethodAbility::StopInput channel is nullptr"); 499 return; 500 } 501 channel->StopInput(); 502 } 503 SetInputDataChannel(sptr<IRemoteObject> & object)504 void InputMethodAbility::SetInputDataChannel(sptr<IRemoteObject> &object) 505 { 506 IMSA_HILOGI("run in SetInputDataChannel"); 507 std::lock_guard<std::mutex> lock(dataChannelLock_); 508 std::shared_ptr<InputDataChannelProxy> channelProxy = std::make_shared<InputDataChannelProxy>(object); 509 if (channelProxy == nullptr) { 510 IMSA_HILOGI("InputMethodAbility::SetInputDataChannel inputDataChannel is nullptr"); 511 return; 512 } 513 dataChannel_ = channelProxy; 514 } 515 GetInputDataChannel()516 std::shared_ptr<InputDataChannelProxy> InputMethodAbility::GetInputDataChannel() 517 { 518 std::lock_guard<std::mutex> lock(dataChannelLock_); 519 return dataChannel_; 520 } 521 SetInputControlChannel(sptr<IRemoteObject> & object)522 void InputMethodAbility::SetInputControlChannel(sptr<IRemoteObject> &object) 523 { 524 IMSA_HILOGI("run in SetInputControlChannel"); 525 std::lock_guard<std::mutex> lock(controlChannelLock_); 526 std::shared_ptr<InputControlChannelProxy> channelProxy = std::make_shared<InputControlChannelProxy>(object); 527 if (channelProxy == nullptr) { 528 IMSA_HILOGI("InputMethodAbility::SetInputControlChannel inputDataChannel is nullptr"); 529 return; 530 } 531 controlChannel_ = channelProxy; 532 } 533 GetInputControlChannel()534 std::shared_ptr<InputControlChannelProxy> InputMethodAbility::GetInputControlChannel() 535 { 536 std::lock_guard<std::mutex> lock(controlChannelLock_); 537 return controlChannel_; 538 } 539 } 540 }