1 /*
2 * Copyright (c) 2021-2024 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_collector.h"
17
18 #include <cstring>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <pthread.h>
22 #include <sys/stat.h>
23 #include <securec.h>
24 #include <unistd.h>
25
26 #include <openssl/sha.h>
27 #include <sys/inotify.h>
28 #include <linux/input.h>
29
30 #include "nlohmann/json.hpp"
31
32 #include "dinput_errcode.h"
33 #include "dinput_log.h"
34 #include "dinput_utils_tool.h"
35
36 namespace OHOS {
37 namespace DistributedHardware {
38 namespace DistributedInput {
DistributedInputCollector()39 DistributedInputCollector::DistributedInputCollector() : mEventBuffer{}, collectThreadID_(-1),
40 isCollectingEvents_(false), isStartGetDeviceHandlerThread(false), inputTypes_(0)
41 {
42 inputHub_ = std::make_unique<InputHub>(false);
43 }
44
~DistributedInputCollector()45 DistributedInputCollector::~DistributedInputCollector()
46 {
47 StopCollectEventsThread();
48 }
49
GetInstance()50 DistributedInputCollector &DistributedInputCollector::GetInstance()
51 {
52 static DistributedInputCollector instance;
53 return instance;
54 }
55
PreInit()56 void DistributedInputCollector::PreInit()
57 {
58 DHLOGI("PreInit for record local device infos");
59 if (inputHub_ == nullptr) {
60 DHLOGE("inputHub_ not initialized");
61 return;
62 }
63 inputHub_->RecordDeviceStates();
64 }
65
StartCollectionThread(std::shared_ptr<AppExecFwk::EventHandler> sinkHandler)66 int32_t DistributedInputCollector::StartCollectionThread(std::shared_ptr<AppExecFwk::EventHandler> sinkHandler)
67 {
68 sinkHandler_ = sinkHandler;
69 if (sinkHandler_ == nullptr || inputHub_ == nullptr) {
70 DHLOGE("DistributedInputCollector::Init sinkHandler_ or inputHub_ invalid \n");
71 return ERR_DH_INPUT_SERVER_SINK_COLLECTOR_INIT_FAIL;
72 }
73
74 DHLOGI("Try start collect thread");
75 if (!isStartGetDeviceHandlerThread) {
76 InitCollectEventsThread();
77 isStartGetDeviceHandlerThread = true;
78 }
79 return DH_SUCCESS;
80 }
81
InitCollectEventsThread()82 bool DistributedInputCollector::InitCollectEventsThread()
83 {
84 pthread_attr_t attr;
85 pthread_attr_init(&attr);
86 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
87
88 isCollectingEvents_ = true;
89 collectThreadID_ = -1;
90 int32_t ret = pthread_create(&collectThreadID_, &attr, CollectEventsThread, this);
91 if (ret != 0) {
92 DHLOGE("DistributedInputCollector::InitCollectEventsThread create thread failed:%{public}d \n", ret);
93 pthread_attr_destroy(&attr);
94 collectThreadID_ = -1;
95 isCollectingEvents_ = false;
96 return false;
97 }
98 return true;
99 }
100
CollectEventsThread(void * param)101 void *DistributedInputCollector::CollectEventsThread(void *param)
102 {
103 int32_t ret = pthread_setname_np(pthread_self(), COLLECT_EVENT_THREAD_NAME);
104 if (ret != 0) {
105 DHLOGE("CollectEventsThread setname failed.");
106 }
107 DistributedInputCollector *pThis = reinterpret_cast<DistributedInputCollector *>(param);
108 if (pThis == nullptr) {
109 DHLOGE("pThis is null.");
110 return nullptr;
111 }
112 pThis->StartCollectEventsThread();
113 DHLOGW("DistributedInputCollector::CollectEventsThread exist!");
114 return nullptr;
115 }
116
StartCollectEventsThread()117 void DistributedInputCollector::StartCollectEventsThread()
118 {
119 DHLOGI("StartCollectEventsThread!");
120 while (isCollectingEvents_) {
121 memset_s(&mEventBuffer, sizeof(mEventBuffer), 0, sizeof(mEventBuffer));
122 if (inputHub_ == nullptr) {
123 DHLOGI("inputHub is nullptr!");
124 return;
125 }
126 size_t count = inputHub_->StartCollectInputEvents(mEventBuffer, INPUT_EVENT_BUFFER_SIZE);
127 if (count == 0) {
128 continue;
129 }
130
131 // The RawEvent obtained by the controlled end calls transport and is
132 // sent to the main control end.
133 std::shared_ptr<nlohmann::json> jsonArrayMsg = std::make_shared<nlohmann::json>();
134 for (size_t ind = 0; ind < count; ind++) {
135 nlohmann::json tmpJson;
136 tmpJson[INPUT_KEY_WHEN] = mEventBuffer[ind].when;
137 tmpJson[INPUT_KEY_TYPE] = mEventBuffer[ind].type;
138 tmpJson[INPUT_KEY_CODE] = mEventBuffer[ind].code;
139 tmpJson[INPUT_KEY_VALUE] = mEventBuffer[ind].value;
140 tmpJson[INPUT_KEY_PATH] = mEventBuffer[ind].path;
141 tmpJson[INPUT_KEY_DESCRIPTOR] = mEventBuffer[ind].descriptor;
142 jsonArrayMsg->push_back(tmpJson);
143 }
144
145 AppExecFwk::InnerEvent::Pointer msgEvent = AppExecFwk::InnerEvent::Get(
146 static_cast<uint32_t>(EHandlerMsgType::DINPUT_SINK_EVENT_HANDLER_MSG), jsonArrayMsg, 0);
147 if (sinkHandler_ != nullptr) {
148 sinkHandler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
149 }
150 }
151 DHLOGW("DistributedInputCollector::StartCollectEventsThread exit!");
152 }
153
StopCollectEventsThread()154 void DistributedInputCollector::StopCollectEventsThread()
155 {
156 isCollectingEvents_ = false;
157 isStartGetDeviceHandlerThread = false;
158 if (inputHub_ == nullptr) {
159 DHLOGI("inputHub is nullptr!");
160 return;
161 }
162 inputHub_->StopCollectInputEvents();
163 if (collectThreadID_ != (pthread_t)(-1)) {
164 DHLOGI("DistributedInputCollector::Wait collect thread exit");
165 pthread_join(collectThreadID_, NULL);
166 collectThreadID_ = (pthread_t)(-1);
167 }
168 inputHub_->ClearDeviceStates();
169 DHLOGW("DistributedInputCollector::StopCollectEventsThread exit!");
170 }
171
SetSharingTypes(bool enabled,const uint32_t & inputType)172 AffectDhIds DistributedInputCollector::SetSharingTypes(bool enabled, const uint32_t &inputType)
173 {
174 inputTypes_ = 0;
175 if ((inputType & static_cast<uint32_t>(DInputDeviceType::MOUSE)) != 0 ||
176 (inputType & static_cast<uint32_t>(DInputDeviceType::TOUCHPAD)) != 0) {
177 inputTypes_ |= INPUT_DEVICE_CLASS_CURSOR;
178 }
179 if ((inputType & static_cast<uint32_t>(DInputDeviceType::KEYBOARD)) != 0) {
180 inputTypes_ |= INPUT_DEVICE_CLASS_KEYBOARD;
181 }
182 if ((inputType & static_cast<uint32_t>(DInputDeviceType::TOUCHSCREEN)) != 0) {
183 inputTypes_ |= INPUT_DEVICE_CLASS_TOUCH_MT | INPUT_DEVICE_CLASS_TOUCH;
184 }
185
186 return inputHub_->SetSupportInputType(enabled, inputTypes_);
187 }
188
ReportDhIdSharingState(const AffectDhIds & dhIds)189 void DistributedInputCollector::ReportDhIdSharingState(const AffectDhIds &dhIds)
190 {
191 std::lock_guard<std::mutex> lock(sharingDhIdListenerMtx_);
192 if (sharingDhIdListeners_.size() == 0) {
193 DHLOGE("sharingDhIdListeners is null, can not report sharing dhid");
194 return;
195 }
196
197 for (auto const &id : dhIds.sharingDhIds) {
198 DHLOGI("Sharing DhId: %{public}s", GetAnonyString(id).c_str());
199 for (auto iter : sharingDhIdListeners_) {
200 iter->OnSharing(id);
201 }
202 }
203
204 for (auto const &id : dhIds.noSharingDhIds) {
205 DHLOGI("No Sharing DhId: %{public}s", GetAnonyString(id).c_str());
206 for (auto iter : sharingDhIdListeners_) {
207 iter->OnNoSharing(id);
208 }
209 }
210 }
211
StopCollectionThread()212 void DistributedInputCollector::StopCollectionThread()
213 {
214 StopCollectEventsThread();
215 }
216
SetSharingDhIds(bool enabled,std::vector<std::string> dhIds)217 AffectDhIds DistributedInputCollector::SetSharingDhIds(bool enabled, std::vector<std::string> dhIds)
218 {
219 return inputHub_->SetSharingDevices(enabled, dhIds);
220 }
221
GetSharingDhIds()222 std::vector<std::string> DistributedInputCollector::GetSharingDhIds()
223 {
224 return inputHub_->GetSharingDevices();
225 }
226
GetMouseNodePath(const std::vector<std::string> & dhIds,std::string & mouseNodePath,std::string & dhId)227 void DistributedInputCollector::GetMouseNodePath(const std::vector<std::string> &dhIds,
228 std::string &mouseNodePath, std::string &dhId)
229 {
230 if (inputHub_ == nullptr) {
231 DHLOGE("inputHub is nullptr!");
232 return;
233 }
234 inputHub_->GetSharedMousePathByDhId(dhIds, mouseNodePath, dhId);
235 }
236
GetSharedKeyboardPathsByDhIds(const std::vector<std::string> & dhIds,std::vector<std::string> & sharedKeyboardPaths,std::vector<std::string> & sharedKeyboardDhIds)237 void DistributedInputCollector::GetSharedKeyboardPathsByDhIds(const std::vector<std::string> &dhIds,
238 std::vector<std::string> &sharedKeyboardPaths, std::vector<std::string> &sharedKeyboardDhIds)
239 {
240 if (inputHub_ == nullptr) {
241 DHLOGE("inputHub is nullptr!");
242 return;
243 }
244 inputHub_->GetSharedKeyboardPathsByDhIds(dhIds, sharedKeyboardPaths, sharedKeyboardDhIds);
245 }
246
IsAllDevicesStoped()247 bool DistributedInputCollector::IsAllDevicesStoped()
248 {
249 if (inputHub_ == nullptr) {
250 DHLOGE("inputHub is nullptr!");
251 return false;
252 }
253 return inputHub_->IsAllDevicesStoped();
254 }
255
RegisterSharingDhIdListener(sptr<ISharingDhIdListener> sharingDhIdListener)256 int32_t DistributedInputCollector::RegisterSharingDhIdListener(sptr<ISharingDhIdListener> sharingDhIdListener)
257 {
258 DHLOGI("RegisterSharingDhIdListener");
259 std::lock_guard<std::mutex> lock(sharingDhIdListenerMtx_);
260 sharingDhIdListeners_.insert(sharingDhIdListener);
261 return DH_SUCCESS;
262 }
263
GetDeviceInfoByType(const uint32_t inputTypes,std::map<int32_t,std::string> & deviceInfo)264 void DistributedInputCollector::GetDeviceInfoByType(const uint32_t inputTypes, std::map<int32_t,
265 std::string> &deviceInfo)
266 {
267 if (inputHub_ == nullptr) {
268 DHLOGE("inputHub is nullptr!");
269 return;
270 }
271 inputHub_->GetDevicesInfoByType(inputTypes, deviceInfo);
272 }
273
ClearSkipDevicePaths()274 void DistributedInputCollector::ClearSkipDevicePaths()
275 {
276 if (inputHub_ == nullptr) {
277 DHLOGE("inputHub is nullptr!");
278 return;
279 }
280 inputHub_->ClearSkipDevicePaths();
281 inputHub_->ScanAndRecordInputDevices();
282 }
283 } // namespace DistributedInput
284 } // namespace DistributedHardware
285 } // namespace OHOS
286