/* * Copyright (C) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "input_method_controller.h" #include "iservice_registry.h" #include "system_ability_definition.h" #include "global.h" namespace OHOS { namespace MiscServices { using namespace MessageID; sptr InputMethodController::instance_; std::mutex InputMethodController::instanceLock_; InputMethodController::InputMethodController() : stop_(false) { IMSA_HILOGI("InputMethodController structure"); Initialize(); } InputMethodController::~InputMethodController() { if (msgHandler != nullptr) { delete msgHandler; msgHandler = nullptr; stop_ = false; } } sptr InputMethodController::GetInstance() { IMSA_HILOGI("InputMethodController::GetInstance"); if (instance_ == nullptr) { std::lock_guard autoLock(instanceLock_); if (instance_ == nullptr) { IMSA_HILOGI("InputMethodController::GetInstance instance_ is nullptr"); instance_ = new InputMethodController(); } } return instance_; } bool InputMethodController::Initialize() { mImms = GetImsaProxy(); msgHandler = new MessageHandler(); mClient = new InputClientStub(); mClient->SetHandler(msgHandler); mInputDataChannel = new InputDataChannelStub(); mInputDataChannel->SetHandler(msgHandler); workThreadHandler = std::thread([this] {WorkThread();}); mAttribute.SetInputPattern(InputAttribute::PATTERN_TEXT); textListener = nullptr; PrepareInput(0, mClient, mInputDataChannel, mAttribute); return true; } sptr InputMethodController::GetImsaProxy() { IMSA_HILOGI("InputMethodController::GetImsaProxy"); sptr systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (systemAbilityManager == nullptr) { IMSA_HILOGI("InputMethodController::GetImsaProxy systemAbilityManager is nullptr"); return nullptr; } auto systemAbility = systemAbilityManager->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID, ""); if (systemAbility == nullptr) { IMSA_HILOGI("InputMethodController::GetImsaProxy systemAbility is nullptr"); return nullptr; } if (deathRecipient_ == nullptr) { deathRecipient_ = new ImsaDeathRecipient(); } systemAbility->AddDeathRecipient(deathRecipient_); sptr iface = new InputMethodSystemAbilityProxy(systemAbility); return iface; } void InputMethodController::WorkThread() { while (!stop_) { Message *msg = msgHandler->GetMessage(); switch (msg->msgId_) { case MSG_ID_INSERT_CHAR: { MessageParcel *data = msg->msgContent_; std::u16string text = data->ReadString16(); if (textListener != nullptr) { textListener->InsertText(text); } break; } case MSG_ID_DELETE_FORWARD: { IMSA_HILOGI("InputMethodController::MSG_ID_DELETE_FORWARD"); MessageParcel *data = msg->msgContent_; int32_t length = data->ReadInt32(); if (textListener != nullptr) { textListener->DeleteForward(length); } break; } case MSG_ID_DELETE_BACKWARD: { IMSA_HILOGI("InputMethodController::MSG_ID_DELETE_BACKWARD"); MessageParcel *data = msg->msgContent_; int32_t length = data->ReadInt32(); if (textListener != nullptr) { textListener->DeleteBackward(length); } break; } case MSG_ID_SET_DISPLAY_MODE: { MessageParcel *data = msg->msgContent_; int32_t ret = data->ReadInt32(); IMSA_HILOGI("MSG_ID_SET_DISPLAY_MODE : %{public}d", ret); break; } case MSG_ID_ON_INPUT_READY: { MessageParcel *data = msg->msgContent_; sptr object = data->ReadRemoteObject(); if (object != nullptr) { mAgent = new InputMethodAgentProxy(object); } break; } case MSG_ID_EXIT_SERVICE: { MessageParcel *data = msg->msgContent_; int32_t ret = data->ReadInt32(); textListener = nullptr; IMSA_HILOGI("MSG_ID_EXIT_SERVICE : %{public}d", ret); break; } case MSG_ID_SEND_KEYBOARD_STATUS: { MessageParcel *data = msg->msgContent_; int32_t ret = data->ReadInt32(); IMSA_HILOGI("MSG_ID_SEND_KEYBOARD_STATUS : %{public}d", ret); KeyboardInfo *info = new KeyboardInfo(); info->SetKeyboardStatus(ret); if (textListener != nullptr) { textListener->SendKeyboardInfo(*info); } break; } case MSG_ID_SEND_FUNCTION_KEY: { MessageParcel *data = msg->msgContent_; int32_t ret = data->ReadInt32(); IMSA_HILOGI("MSG_ID_SEND_FUNCTION_KEY : %{public}d", ret); KeyboardInfo *info = new KeyboardInfo(); info->SetFunctionKey(ret); if (textListener != nullptr) { textListener->SendKeyboardInfo(*info); } break; } case MSG_ID_MOVE_CURSOR: { MessageParcel *data = msg->msgContent_; int32_t ret = data->ReadInt32(); IMSA_HILOGI("MSG_ID_MOVE_CURSOR : %{public}d", ret); if (textListener != nullptr) { Direction direction = static_cast(ret); textListener->MoveCursor(direction); } break; } default: { break; } } delete msg; msg = nullptr; } } void InputMethodController::Attach(sptr &listener) { textListener = listener; StartInput(mClient); } void InputMethodController::ShowTextInput() { IMSA_HILOGI("InputMethodController::ShowTextInput"); StartInput(mClient); } void InputMethodController::HideTextInput() { IMSA_HILOGI("InputMethodController::HideTextInput"); StopInput(mClient); } void InputMethodController::Close() { ReleaseInput(mClient); textListener = nullptr; } void InputMethodController::PrepareInput(int32_t displayId, sptr &client, sptr &channel, InputAttribute &attribute) { IMSA_HILOGI("InputMethodController::PrepareInput"); if (mImms == nullptr) { return; } MessageParcel data; if (!(data.WriteInterfaceToken(mImms->GetDescriptor()) && data.WriteInt32(displayId) && data.WriteRemoteObject(client->AsObject()) && data.WriteRemoteObject(channel->AsObject()) && data.WriteParcelable(&attribute))) { return; } mImms->prepareInput(data); } void InputMethodController::StartInput(sptr &client) { IMSA_HILOGI("InputMethodController::StartInput"); if (mImms == nullptr) { return; } MessageParcel data; if (!(data.WriteInterfaceToken(mImms->GetDescriptor()) && data.WriteRemoteObject(client->AsObject()))) { return; } mImms->startInput(data); } void InputMethodController::ReleaseInput(sptr &client) { IMSA_HILOGI("InputMethodController::ReleaseInput"); if (mImms == nullptr) { return; } MessageParcel data; if (!(data.WriteInterfaceToken(mImms->GetDescriptor()) && data.WriteRemoteObject(client->AsObject().GetRefPtr()))) { return; } mImms->releaseInput(data); } void InputMethodController::StopInput(sptr &client) { IMSA_HILOGI("InputMethodController::StopInput"); if (mImms == nullptr) { return; } MessageParcel data; if (!(data.WriteInterfaceToken(mImms->GetDescriptor()) && data.WriteRemoteObject(client->AsObject().GetRefPtr()))) { return; } mImms->stopInput(data); } void InputMethodController::OnRemoteSaDied(const wptr &remote) { mImms = GetImsaProxy(); } ImsaDeathRecipient::ImsaDeathRecipient() { } void ImsaDeathRecipient::OnRemoteDied(const wptr &object) { InputMethodController::GetInstance()->OnRemoteSaDied(object); } void InputMethodController::OnCursorUpdate(CursorInfo cursorInfo) { if (mAgent == nullptr) { IMSA_HILOGI("InputMethodController::OnCursorUpdate mAgent is nullptr"); return; } if(cursorInfo_.left == cursorInfo.left && cursorInfo_.top == cursorInfo.top && cursorInfo_.height == cursorInfo.height){ return; } cursorInfo_ = cursorInfo; mAgent->OnCursorUpdate(cursorInfo.left, cursorInfo.top, cursorInfo.height); } void InputMethodController::OnSelectionChange(std::u16string text, int start, int end) { IMSA_HILOGI("InputMethodController::OnSelectionChange"); if (mTextString == text && mSelectNewBegin == start && mSelectNewEnd == end) { return; } mTextString = text; mSelectOldBegin = mSelectNewBegin; mSelectOldEnd = mSelectNewEnd; mSelectNewBegin = start; mSelectNewEnd = end; if (mAgent == nullptr) { IMSA_HILOGI("InputMethodController::OnSelectionChange mAgent is nullptr"); return; } mAgent->OnSelectionChange(mTextString, mSelectOldBegin, mSelectOldEnd, mSelectNewBegin, mSelectNewEnd); } void InputMethodController::OnConfigurationChange(Configuration info) { IMSA_HILOGI("InputMethodController::OnConfigurationChange"); } std::u16string InputMethodController::GetTextBeforeCursor() { IMSA_HILOGI("InputMethodController::GetTextBeforeCursor"); if (!mTextString.empty()) { return mTextString.substr(0, mSelectNewBegin); } return u""; } std::u16string InputMethodController::GetTextAfterCursor() { IMSA_HILOGI("InputMethodController::GetTextBeforeCursor"); if (!mTextString.empty()) { if (mTextString.size() > mSelectNewEnd) { return mTextString.substr(mSelectNewEnd); } } return u""; } bool InputMethodController::dispatchKeyEvent(std::shared_ptr keyEvent) { IMSA_HILOGI("InputMethodController::dispatchKeyEvent"); if (mAgent == nullptr) { IMSA_HILOGI("InputMethodController::dispatchKeyEvent mAgent is nullptr"); return false; } MessageParcel data; if (!(data.WriteInterfaceToken(mAgent->GetDescriptor()) && data.WriteInt32(keyEvent->GetKeyCode()) && data.WriteInt32(keyEvent->GetKeyAction()))) { return false; } return mAgent->DispatchKeyEvent(data); } } }