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