1 /*
2 * Copyright (c) 2021-2023 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 "distributed_input_handler.h"
17
18 #include <cstring>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <pthread.h>
22 #include <sstream>
23 #include <sys/stat.h>
24 #include <unistd.h>
25
26 #include <openssl/sha.h>
27 #include <sys/inotify.h>
28 #include <linux/input.h>
29 #include <linux/uinput.h>
30
31 #include "nlohmann/json.hpp"
32
33 #include "constants_dinput.h"
34 #include "dinput_errcode.h"
35 #include "dinput_log.h"
36 #include "dinput_softbus_define.h"
37 #include "dinput_utils_tool.h"
38 #include "softbus_bus_center.h"
39
40 namespace OHOS {
41 namespace DistributedHardware {
42 namespace DistributedInput {
43 IMPLEMENT_SINGLE_INSTANCE(DistributedInputHandler);
DistributedInputHandler()44 DistributedInputHandler::DistributedInputHandler()
45 : collectThreadID_(-1), isCollectingEvents_(false), isStartCollectEventThread(false)
46 {
47 inputHub_ = std::make_unique<InputHub>(true);
48 this->m_listener = nullptr;
49 }
50
~DistributedInputHandler()51 DistributedInputHandler::~DistributedInputHandler()
52 {
53 StopInputMonitorDeviceThread();
54 }
55
StructTransJson(const InputDevice & pBuf,std::string & strDescriptor)56 void DistributedInputHandler::StructTransJson(const InputDevice &pBuf, std::string &strDescriptor)
57 {
58 DHLOGI("[%s] %d, %d, %d, %d, %s.\n", (pBuf.name).c_str(), pBuf.bus, pBuf.vendor, pBuf.product, pBuf.version,
59 GetAnonyString(pBuf.descriptor).c_str());
60 nlohmann::json tmpJson;
61 tmpJson[DEVICE_NAME] = pBuf.name;
62 tmpJson[PHYSICAL_PATH] = pBuf.physicalPath;
63 tmpJson[UNIQUE_ID] = pBuf.uniqueId;
64 tmpJson[BUS] = pBuf.bus;
65 tmpJson[VENDOR] = pBuf.vendor;
66 tmpJson[PRODUCT] = pBuf.product;
67 tmpJson[VERSION] = pBuf.version;
68 tmpJson[DESCRIPTOR] = pBuf.descriptor;
69 tmpJson[CLASSES] = pBuf.classes;
70 tmpJson[EVENT_TYPES] = pBuf.eventTypes;
71 tmpJson[EVENT_KEYS] = pBuf.eventKeys;
72 tmpJson[ABS_TYPES] = pBuf.absTypes;
73 tmpJson[ABS_INFOS] = pBuf.absInfos;
74 tmpJson[REL_TYPES] = pBuf.relTypes;
75 tmpJson[PROPERTIES] = pBuf.properties;
76
77 tmpJson[MISCELLANEOUS] = pBuf.miscellaneous;
78 tmpJson[LEDS] = pBuf.leds;
79 tmpJson[REPEATS] = pBuf.repeats;
80 tmpJson[SWITCHS] = pBuf.switchs;
81
82 std::ostringstream stream;
83 stream << tmpJson.dump();
84 strDescriptor = stream.str();
85 DHLOGI("Record InputDevice json info: %s", strDescriptor.c_str());
86 return;
87 }
88
Initialize()89 int32_t DistributedInputHandler::Initialize()
90 {
91 if (!isStartCollectEventThread) {
92 InitCollectEventsThread();
93 isStartCollectEventThread = true;
94 }
95 return DH_SUCCESS;
96 }
97
FindDevicesInfoByType(const uint32_t inputTypes,std::map<int32_t,std::string> & datas)98 void DistributedInputHandler::FindDevicesInfoByType(const uint32_t inputTypes, std::map<int32_t, std::string> &datas)
99 {
100 if (inputHub_ != nullptr) {
101 inputHub_->GetDevicesInfoByType(inputTypes, datas);
102 }
103 }
104
FindDevicesInfoByDhId(std::vector<std::string> dhidsVec,std::map<int32_t,std::string> & datas)105 void DistributedInputHandler::FindDevicesInfoByDhId(
106 std::vector<std::string> dhidsVec, std::map<int32_t, std::string> &datas)
107 {
108 if (inputHub_ != nullptr) {
109 inputHub_->GetDevicesInfoByDhId(dhidsVec, datas);
110 }
111 }
112
Query()113 std::vector<DHItem> DistributedInputHandler::Query()
114 {
115 std::vector<DHItem> retInfos;
116
117 if (inputHub_ != nullptr) {
118 std::vector<InputDevice> vecInput = inputHub_->GetAllInputDevices();
119 for (auto iter : vecInput) {
120 DHItem item;
121 item.dhId = iter.descriptor;
122 item.subtype = "input";
123 StructTransJson(iter, item.attrs);
124 retInfos.push_back(item);
125 }
126 }
127
128 return retInfos;
129 }
130
QueryExtraInfo()131 std::map<std::string, std::string> DistributedInputHandler::QueryExtraInfo()
132 {
133 std::map<std::string, std::string> ret;
134 return ret;
135 }
136
IsSupportPlugin()137 bool DistributedInputHandler::IsSupportPlugin()
138 {
139 return true;
140 }
141
RegisterPluginListener(std::shared_ptr<PluginListener> listener)142 void DistributedInputHandler::RegisterPluginListener(std::shared_ptr<PluginListener> listener)
143 {
144 this->m_listener = listener;
145 }
146
UnRegisterPluginListener()147 void DistributedInputHandler::UnRegisterPluginListener()
148 {
149 this->m_listener = nullptr;
150 }
151
InitCollectEventsThread()152 bool DistributedInputHandler::InitCollectEventsThread()
153 {
154 pthread_attr_t attr;
155 pthread_attr_init(&attr);
156 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
157
158 isCollectingEvents_ = true;
159 collectThreadID_ = -1;
160 int32_t ret = pthread_create(&collectThreadID_, &attr, CollectEventsThread, this);
161 if (ret != 0) {
162 DHLOGE("DistributedInputHandler::InitCollectEventsThread create thread failed:%d \n", ret);
163 pthread_attr_destroy(&attr);
164 collectThreadID_ = -1;
165 isCollectingEvents_ = false;
166 return false;
167 }
168 return true;
169 }
170
CollectEventsThread(void * param)171 void *DistributedInputHandler::CollectEventsThread(void *param)
172 {
173 int32_t ret = pthread_setname_np(pthread_self(), COLLECT_EVENT_THREAD_NAME);
174 if (ret != 0) {
175 DHLOGE("CollectEventsThread setname failed.");
176 }
177 DistributedInputHandler *pThis = reinterpret_cast<DistributedInputHandler *>(param);
178 pThis->StartInputMonitorDeviceThread();
179 DHLOGI("DistributedInputHandler::CollectEventsThread exist!");
180 return nullptr;
181 }
182
StartInputMonitorDeviceThread()183 void DistributedInputHandler::StartInputMonitorDeviceThread()
184 {
185 if (inputHub_ == nullptr) {
186 DHLOGE("inputHub_ not initialized");
187 return;
188 }
189 while (isCollectingEvents_) {
190 size_t count = inputHub_->StartCollectInputHandler(mEventBuffer, inputDeviceBufferSize);
191 if (count > 0) {
192 DHLOGI("Count: %zu", count);
193 for (size_t iCnt = 0; iCnt < count; iCnt++) {
194 NotifyHardWare(iCnt);
195 }
196 } else {
197 continue;
198 }
199 }
200 isCollectingEvents_ = false;
201 DHLOGI("DistributedInputHandler::StartCollectEventsThread exit!");
202 }
203
NotifyHardWare(int iCnt)204 void DistributedInputHandler::NotifyHardWare(int iCnt)
205 {
206 switch (mEventBuffer[iCnt].type) {
207 case DeviceType::DEVICE_ADDED:
208 if (this->m_listener != nullptr) {
209 std::string hdInfo;
210 StructTransJson(mEventBuffer[iCnt].deviceInfo, hdInfo);
211 std::string subtype = "input";
212 this->m_listener->PluginHardware(mEventBuffer[iCnt].deviceInfo.descriptor, hdInfo, subtype);
213 }
214 break;
215 case DeviceType::DEVICE_REMOVED:
216 if (this->m_listener != nullptr) {
217 this->m_listener->UnPluginHardware(mEventBuffer[iCnt].deviceInfo.descriptor);
218 }
219 break;
220 default:
221 break;
222 }
223 }
224
StopInputMonitorDeviceThread()225 void DistributedInputHandler::StopInputMonitorDeviceThread()
226 {
227 isCollectingEvents_ = false;
228 isStartCollectEventThread = false;
229 inputHub_->StopCollectInputHandler();
230 if (collectThreadID_ != (pthread_t)(-1)) {
231 DHLOGI("DistributedInputHandler::Wait collect thread exit");
232 pthread_join(collectThreadID_, NULL);
233 collectThreadID_ = (pthread_t)(-1);
234 }
235 DHLOGI("DistributedInputHandler::StopInputMonitorDeviceThread exit!");
236 }
237
GetHardwareHandler()238 IHardwareHandler* GetHardwareHandler()
239 {
240 return &DistributedInputHandler::GetInstance();
241 }
242 } // namespace DistributedInput
243 } // namespace DistributedHardware
244 } // namespace OHOS
245