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