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