1 /*
2 * Copyright (c) 2021-2025 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_device_impl.h"
17
18 #include "multimodal_input_connect_manager.h"
19 #include "bytrace_adapter.h"
20 #include "mmi_log.h"
21
22 #undef MMI_LOG_TAG
23 #define MMI_LOG_TAG "InputDeviceImpl"
24
25 namespace OHOS {
26 namespace MMI {
27 namespace {
28 constexpr std::string_view INPUT_DEV_CHANGE_ADD_DEV { "add" };
29 constexpr std::string_view INPUT_DEV_CHANGE_REMOVE_DEV { "remove" };
30 }
31
GetInstance()32 InputDeviceImpl& InputDeviceImpl::GetInstance()
33 {
34 static InputDeviceImpl instance;
35 return instance;
36 }
37
RegisterDevListener(const std::string & type,InputDevListenerPtr listener)38 int32_t InputDeviceImpl::RegisterDevListener(const std::string &type, InputDevListenerPtr listener)
39 {
40 CHKPR(listener, RET_ERR);
41 MMI_HILOGI("Register listener of change of input devices");
42
43 bool needStartServer = false;
44 {
45 std::lock_guard<std::mutex> guard(devListenerMutex_);
46 auto iter = devListener_.find(type);
47 if (iter == devListener_.end()) {
48 MMI_HILOGE("Type of listener (%{public}s) is not supported", type.c_str());
49 return RET_ERR;
50 }
51
52 auto &listeners = iter->second;
53 bool isNew = std::all_of(listeners.cbegin(), listeners.cend(),
54 [listener](InputDevListenerPtr tListener) {
55 return (tListener != listener);
56 });
57 if (isNew) {
58 listeners.push_back(listener);
59 needStartServer = listeners.size();
60 }
61 }
62
63 if (needStartServer) {
64 auto ret = StartListeningToServer();
65 if (ret != RET_OK) {
66 MMI_HILOGE("StartListeningToServer fail, error:%{public}d", ret);
67 std::lock_guard<std::mutex> guard(devListenerMutex_);
68 auto iter = devListener_.find(type);
69 if (iter != devListener_.end()) {
70 iter->second.remove(listener);
71 }
72 return ret;
73 }
74 }
75
76 MMI_HILOGI("Succeed to register listener of change of input devices");
77 return RET_OK;
78 }
79
UnregisterDevListener(const std::string & type,InputDevListenerPtr listener)80 int32_t InputDeviceImpl::UnregisterDevListener(const std::string &type, InputDevListenerPtr listener)
81 {
82 bool needStopServer = false;
83 {
84 std::lock_guard<std::mutex> guard(devListenerMutex_);
85 auto iter = devListener_.find(type);
86 if (iter == devListener_.end()) {
87 MMI_HILOGE("Type of listener (%{public}s) is not supported", type.c_str());
88 return RET_ERR;
89 }
90
91 auto &listeners = iter->second;
92 if (listener == nullptr) {
93 MMI_HILOGI("Unregister all listeners of change of input devices");
94 needStopServer = !listeners.empty();
95 listeners.clear();
96 } else {
97 MMI_HILOGI("Unregister listener of change of input devices");
98 size_t oldSize = listeners.size();
99 listeners.remove_if([listener](const auto &item) {
100 return (item == listener);
101 });
102 needStopServer = (oldSize > 0) && listeners.empty();
103 }
104 }
105
106 if (needStopServer) {
107 StopListeningToServer();
108 }
109 return RET_OK;
110 }
111
OnDevListener(int32_t deviceId,const std::string & type)112 void InputDeviceImpl::OnDevListener(int32_t deviceId, const std::string &type)
113 {
114 CALL_DEBUG_ENTER;
115 MMI_HILOGI("Change(%{public}s) of input device(%{public}d)", type.c_str(), deviceId);
116
117 std::vector<InputDevListenerPtr> listenersToNotify;
118 {
119 std::lock_guard<std::mutex> guard(devListenerMutex_);
120 auto iter = devListener_.find(CHANGED_TYPE);
121 if (iter == devListener_.end()) {
122 MMI_HILOGE("Find change failed");
123 return;
124 }
125 listenersToNotify.assign(iter->second.begin(), iter->second.end());
126 }
127
128 BytraceAdapter::StartDevListener(type, deviceId);
129
130 for (const auto &item : listenersToNotify) {
131 if (type == INPUT_DEV_CHANGE_ADD_DEV) {
132 item->OnDeviceAdded(deviceId, type);
133 } else if (type == INPUT_DEV_CHANGE_REMOVE_DEV) {
134 item->OnDeviceRemoved(deviceId, type);
135 }
136 }
137 BytraceAdapter::StopDevListener();
138 }
139
GetInputDeviceIds(FunInputDevIds callback)140 int32_t InputDeviceImpl::GetInputDeviceIds(FunInputDevIds callback)
141 {
142 CALL_DEBUG_ENTER;
143 CHKPR(callback, RET_ERR);
144 std::vector<int32_t> ids;
145 if (MULTIMODAL_INPUT_CONNECT_MGR->GetDeviceIds(ids) != RET_OK) {
146 MMI_HILOGE("GetInputDeviceIds failed");
147 return RET_ERR;
148 }
149 callback(ids);
150 return RET_OK;
151 }
152
GetInputDevice(int32_t deviceId,FunInputDevInfo callback)153 int32_t InputDeviceImpl::GetInputDevice(int32_t deviceId, FunInputDevInfo callback)
154 {
155 CALL_DEBUG_ENTER;
156 CHKPR(callback, RET_ERR);
157 std::shared_ptr<InputDevice> inputDevice = std::make_shared<InputDevice>();
158 if (MULTIMODAL_INPUT_CONNECT_MGR->GetDevice(deviceId, inputDevice) != RET_OK) {
159 MMI_HILOGE("GetDevice failed");
160 return RET_ERR;
161 }
162 callback(inputDevice);
163 return RET_OK;
164 }
165
SupportKeys(int32_t deviceId,std::vector<int32_t> keyCodes,FunInputDevKeys callback)166 int32_t InputDeviceImpl::SupportKeys(int32_t deviceId, std::vector<int32_t> keyCodes, FunInputDevKeys callback)
167 {
168 CALL_DEBUG_ENTER;
169 CHKPR(callback, RET_ERR);
170 std::vector<bool> keystroke;
171 if (MULTIMODAL_INPUT_CONNECT_MGR->SupportKeys(deviceId, keyCodes, keystroke) != RET_OK) {
172 MMI_HILOGE("SupportKeys failed");
173 return RET_ERR;
174 }
175 callback(keystroke);
176 return RET_OK;
177 }
178
GetKeyboardType(int32_t deviceId,FunKeyboardTypes callback)179 int32_t InputDeviceImpl::GetKeyboardType(int32_t deviceId, FunKeyboardTypes callback)
180 {
181 CALL_DEBUG_ENTER;
182 CHKPR(callback, RET_ERR);
183 int32_t keyboardType = 0;
184 if (MULTIMODAL_INPUT_CONNECT_MGR->GetKeyboardType(deviceId, keyboardType) != RET_OK) {
185 MMI_HILOGE("GetKeyboardType failed");
186 return RET_ERR;
187 }
188 callback(keyboardType);
189 return RET_OK;
190 }
191
SetKeyboardRepeatDelay(int32_t delay)192 int32_t InputDeviceImpl::SetKeyboardRepeatDelay(int32_t delay)
193 {
194 CALL_DEBUG_ENTER;
195 if (MULTIMODAL_INPUT_CONNECT_MGR->SetKeyboardRepeatDelay(delay) != RET_OK) {
196 MMI_HILOGE("SetKeyboardRepeatDelay failed");
197 return RET_ERR;
198 }
199 return RET_OK;
200 }
201
SetKeyboardRepeatRate(int32_t rate)202 int32_t InputDeviceImpl::SetKeyboardRepeatRate(int32_t rate)
203 {
204 CALL_DEBUG_ENTER;
205 if (MULTIMODAL_INPUT_CONNECT_MGR->SetKeyboardRepeatRate(rate) != RET_OK) {
206 MMI_HILOGE("SetKeyboardRepeatRate failed");
207 return RET_ERR;
208 }
209 return RET_OK;
210 }
211
GetKeyboardRepeatDelay(std::function<void (int32_t)> callback)212 int32_t InputDeviceImpl::GetKeyboardRepeatDelay(std::function<void(int32_t)> callback)
213 {
214 CALL_DEBUG_ENTER;
215 CHKPR(callback, RET_ERR);
216 int32_t repeatDelay = 0;
217 if (MULTIMODAL_INPUT_CONNECT_MGR->GetKeyboardRepeatDelay(repeatDelay) != RET_OK) {
218 MMI_HILOGE("GetKeyboardRepeatDelay failed");
219 return RET_ERR;
220 }
221 callback(repeatDelay);
222 return RET_OK;
223 }
224
GetKeyboardRepeatRate(std::function<void (int32_t)> callback)225 int32_t InputDeviceImpl::GetKeyboardRepeatRate(std::function<void(int32_t)> callback)
226 {
227 CALL_DEBUG_ENTER;
228 int32_t repeatRate = 0;
229 if (MULTIMODAL_INPUT_CONNECT_MGR->GetKeyboardRepeatRate(repeatRate) != RET_OK) {
230 MMI_HILOGE("GetKeyboardRepeatRate failed");
231 return RET_ERR;
232 }
233 callback(repeatRate);
234 return RET_OK;
235 }
236
GetUserData()237 int32_t InputDeviceImpl::GetUserData()
238 {
239 return userData_;
240 }
241
RegisterInputdevice(int32_t deviceId,bool enable,std::function<void (int32_t)> callback)242 int32_t InputDeviceImpl::RegisterInputdevice(int32_t deviceId, bool enable, std::function<void(int32_t)> callback)
243 {
244 CALL_DEBUG_ENTER;
245 CHKPR(callback, RET_ERR);
246 int32_t _id;
247 {
248 std::lock_guard<std::mutex> guard(inputDeviceMutex_);
249 _id = operationIndex_++;
250 inputdeviceList_[_id] = callback;
251 }
252 int32_t ret = MULTIMODAL_INPUT_CONNECT_MGR->SetInputDeviceEnabled(deviceId, enable, _id);
253 if (ret != RET_OK) {
254 MMI_HILOGE("Failed to register");
255 return ret;
256 }
257 return RET_OK;
258 }
259
OnSetInputDeviceAck(int32_t index,int32_t result)260 void InputDeviceImpl::OnSetInputDeviceAck(int32_t index, int32_t result)
261 {
262 CALL_DEBUG_ENTER;
263 std::function<void(int32_t)> callback;
264 {
265 std::lock_guard<std::mutex> guard(inputDeviceMutex_);
266 auto iter = inputdeviceList_.find(index);
267 if (iter == inputdeviceList_.end()) {
268 MMI_HILOGE("Find index failed");
269 return;
270 }
271 callback = std::move(iter->second);
272 inputdeviceList_.erase(iter);
273 }
274 callback(result);
275 }
276
OnConnected()277 void InputDeviceImpl::OnConnected()
278 {
279 bool shouldStartServer = false;
280 {
281 std::lock_guard<std::mutex> guard(devListenerMutex_);
282 auto iter = devListener_.find(CHANGED_TYPE);
283 shouldStartServer = (iter != devListener_.end()) && !iter->second.empty();
284 }
285
286 if (!shouldStartServer) {
287 return;
288 }
289
290 auto ret = StartListeningToServer();
291 if (ret != RET_OK) {
292 MMI_HILOGE("StartListeningToServer fail, error:%{public}d", ret);
293 }
294 }
295
OnDisconnected()296 void InputDeviceImpl::OnDisconnected()
297 {
298 MMI_HILOGI("Disconnected from server");
299 isListeningProcess_.store(false);
300 }
301
StartListeningToServer()302 int32_t InputDeviceImpl::StartListeningToServer()
303 {
304 if (isListeningProcess_.load()) {
305 return RET_OK;
306 }
307 MMI_HILOGI("Start monitoring changes of input devices");
308 int32_t ret = MULTIMODAL_INPUT_CONNECT_MGR->RegisterDevListener();
309 if (ret != RET_OK) {
310 MMI_HILOGE("RegisterDevListener to server fail, error:%{public}d", ret);
311 return ret;
312 }
313 isListeningProcess_.store(true);
314 return RET_OK;
315 }
316
StopListeningToServer()317 void InputDeviceImpl::StopListeningToServer()
318 {
319 if (!isListeningProcess_.load()) {
320 return;
321 }
322 MMI_HILOGI("Stop monitoring changes of input devices");
323 auto ret = MULTIMODAL_INPUT_CONNECT_MGR->UnregisterDevListener();
324 if (ret != RET_OK) {
325 MMI_HILOGE("UnregisterDevListener from server fail, error:%{public}d", ret);
326 }
327 isListeningProcess_.store(false);
328 }
329 } // namespace MMI
330 } // namespace OHOS
331