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 "message_handler.h" 17 #include "input_control_channel_stub.h" 18 #include "i_input_control_channel.h" 19 #include "input_channel.h" 20 #include "input_method_agent_proxy.h" 21 #include "message_parcel.h" 22 23 namespace OHOS { 24 namespace MiscServices { 25 /*! Constructor 26 \param userId the id of the user to whom the object is linking 27 */ InputControlChannelStub(int userId)28 InputControlChannelStub::InputControlChannelStub(int userId) 29 { 30 userId_ = userId; 31 } 32 33 /*! Destructor 34 */ ~InputControlChannelStub()35 InputControlChannelStub::~InputControlChannelStub() 36 { 37 } 38 39 /*! Handle the transaction from the remote binder 40 \n Run in binder thread 41 \param code transaction code number 42 \param data the params from remote binder 43 \param[out] reply the result of the transaction replied to the remote binder 44 \param flags the flags of handling transaction 45 \return int32_t 46 */ OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)47 int32_t InputControlChannelStub::OnRemoteRequest(uint32_t code, MessageParcel& data, 48 MessageParcel& reply, MessageOption& option) 49 { 50 IMSA_HILOGI("InputControlChannelStub::OnRemoteRequest code = %{public}u", code); 51 auto descriptorToken = data.ReadInterfaceToken(); 52 if (descriptorToken != GetDescriptor()) { 53 return ErrorCode::ERROR_STATUS_UNKNOWN_TRANSACTION; 54 } 55 switch (code) { 56 case HIDE_KEYBOARD_SELF: { 57 int flag = data.ReadInt32(); 58 hideKeyboardSelf(flag); 59 reply.WriteNoException(); 60 break; 61 } 62 case ADVANCE_TO_NEXT: { 63 bool isCurrentIme = data.ReadInt32(); 64 bool ret = advanceToNext(isCurrentIme); 65 reply.WriteNoException(); 66 reply.WriteBool(ret); 67 break; 68 } 69 case SET_DISPLAY_MODE: { 70 int mode = data.ReadInt32(); 71 setDisplayMode(mode); 72 reply.WriteNoException(); 73 break; 74 } 75 case ON_KEYBOARD_SHOWED: { 76 onKeyboardShowed(); 77 reply.WriteNoException(); 78 break; 79 } 80 default: { 81 return IRemoteStub::OnRemoteRequest(code, data, reply, option); 82 } 83 } 84 return NO_ERROR; 85 } 86 87 /*! Called when input method service showed keyboard 88 \n This call is running in binder thread 89 */ onKeyboardShowed()90 void InputControlChannelStub::onKeyboardShowed() 91 { 92 IMSA_HILOGI("InputControlChannelStub::onKeyboardShowed"); 93 { 94 std::unique_lock<std::mutex> lck(mtx); 95 keyboardReadyFlag = true; 96 } 97 cv.notify_one(); 98 } 99 100 /*! Send hideKeyboardSelf command to work thread. 101 \n This call is running in binder thread, 102 but the handling of hideKeyboardSelf is in the work thread of PerUserSession. 103 \see PerUserSession::OnHideKeyboardSelf 104 \param flags the flag value of hiding keyboard 105 */ hideKeyboardSelf(int flags)106 void InputControlChannelStub::hideKeyboardSelf(int flags) 107 { 108 IMSA_HILOGI("InputControlChannelStub::hideKeyboardSelf flags = %{public}d", flags); 109 MessageParcel *parcel = new MessageParcel(); 110 parcel->WriteInt32(userId_); 111 parcel->WriteInt32(flags); 112 113 Message *msg = new Message(MessageID::MSG_ID_HIDE_KEYBOARD_SELF, parcel); 114 MessageHandler::Instance()->SendMessage(msg); 115 } 116 117 /*! Send advanceToNext command to work thread. 118 \n This call is running in binder thread, 119 but the handling of advanceToNext is in the work thread of InputMethodSystemAbility service 120 \n or in the work thread of PerUserSession 121 \see InputMethodSystemAbility::OnAdvanceToNext PerUserSession::OnAdvanceToNext 122 \see PerUserSetting::OnAdvanceToNext 123 \param isCurrentIme true - switch to next keyboard type within current input method engine 124 \n false - switch to next input method engine 125 \return true 126 */ advanceToNext(bool isCurrentIme)127 bool InputControlChannelStub::advanceToNext(bool isCurrentIme) 128 { 129 IMSA_HILOGI("InputControlChannelStub::advanceToNext"); 130 MessageParcel *parcel = new MessageParcel(); 131 parcel->WriteInt32(userId_); 132 parcel->WriteBool(isCurrentIme); 133 134 Message *msg = new Message(MessageID::MSG_ID_ADVANCE_TO_NEXT, parcel); 135 MessageHandler::Instance()->SendMessage(msg); 136 return true; 137 } 138 139 /*! Send setDisplayMode command to work thread. 140 \n This call is running in binder thread, 141 but the handling of setDisplayMode is in the work thread of PerUserSession. 142 \see PerUserSession::OnSetDisplayMode 143 \param mode 0 - part screen mode, 1 - full screen mode 144 */ setDisplayMode(int mode)145 void InputControlChannelStub::setDisplayMode(int mode) 146 { 147 IMSA_HILOGI("InputControlChannelStub::setDisplayMode start"); 148 MessageParcel *parcel = new MessageParcel(); 149 parcel->WriteInt32(userId_); 150 parcel->WriteInt32(mode); 151 152 Message *msg = new Message(MessageID::MSG_ID_SET_DISPLAY_MODE, parcel); 153 MessageHandler::Instance()->SendMessage(msg); 154 } 155 156 /*! Reset ready flag to be false 157 \n This should be called before imsCore->startInput() in work thread of PerUserSession 158 */ ResetFlag()159 void InputControlChannelStub::ResetFlag() 160 { 161 IMSA_HILOGI("InputControlChannelStub::ResetFlag"); 162 std::unique_lock<std::mutex> lck(mtx); 163 keyboardReadyFlag = false; 164 agentReadyFlag = false; 165 } 166 167 /*! Wait for keyboard to be ready 168 \n This should be called in work thread of PerUserSession 169 \return true - onKeyboardShowed is called by input method service in time 170 \n false - onKeyboardShowed is not called by input method service in time 171 */ WaitKeyboardReady()172 bool InputControlChannelStub::WaitKeyboardReady() 173 { 174 IMSA_HILOGI("InputControlChannelStub::WaitKeyboardReady"); 175 std::chrono::milliseconds millsec(sleepTime); 176 bool ret = false; 177 { 178 std::unique_lock<std::mutex> lck(mtx); 179 ret = cv.wait_for(lck, millsec, [this] { 180 return keyboardReadyFlag; 181 }); 182 } 183 return ret; 184 } 185 } 186 } 187