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 #ifndef DISTRIBUTED_INPUT_NODE_MANAGER_H
17 #define DISTRIBUTED_INPUT_NODE_MANAGER_H
18 
19 #include <atomic>
20 #include <condition_variable>
21 #include <map>
22 #include <mutex>
23 #include <queue>
24 #include <string>
25 #include <thread>
26 
27 #include "event_handler.h"
28 #include "nlohmann/json.hpp"
29 
30 #include "constants_dinput.h"
31 #include "input_hub.h"
32 #include "i_session_state_callback.h"
33 #include "virtual_device.h"
34 
35 namespace OHOS {
36 namespace DistributedHardware {
37 namespace DistributedInput {
38 constexpr uint32_t DINPUT_NODE_MANAGER_SCAN_ALL_NODE = 1;
39 constexpr uint32_t DINPUT_INJECT_EVENT_FAIL = 2;
40 const std::string INPUT_NODE_DEVID = "devId";
41 const std::string INPUT_NODE_DHID = "dhId";
42 /**
43  * @brief the unique id for the input peripheral.
44  * left is device networkid, right is dhId in that device.
45  */
46 using DhUniqueID = std::pair<std::string, std::string>;
47 /**
48  * @brief a batch events form one device
49  * left: device networid where these events from
50  * right: the event batch
51  */
52 using EventBatch = std::pair<std::string, std::vector<RawEvent>>;
53 class DistributedInputNodeManager {
54 public:
55     DistributedInputNodeManager();
56     ~DistributedInputNodeManager();
57 
58     int32_t OpenDevicesNode(const std::string &devId, const std::string &dhId, const std::string &parameters);
59 
60     int32_t GetDevice(const std::string &devId, const std::string &dhId, VirtualDevice *&device);
61     void ReportEvent(const std::string &devId, const std::vector<RawEvent> &events);
62     int32_t CloseDeviceLocked(const std::string &devId, const std::string &dhId);
63     void StartInjectThread();
64     void StopInjectThread();
65     int32_t CreateVirtualTouchScreenNode(const std::string &devId, const std::string &dhId, const uint64_t srcWinId,
66         const uint32_t sourcePhyWidth, const uint32_t sourcePhyHeight);
67     int32_t RemoveVirtualTouchScreenNode(const std::string &devId, const std::string &dhId);
68     int32_t GetVirtualTouchScreenFd();
69 
70     void ProcessInjectEvent(const EventBatch &events);
71 
72     /**
73      * @brief Get the Virtual Keyboard Paths By Dh Ids object
74      *
75      * @param dhKeys list for device identify({networkId, dhId})
76      * @param virKeyboardPaths the matched keyboard device
77      * @param virKeyboardDhIds matched keyboard device identify
78      */
79     void GetVirtualKeyboardPaths(const std::vector<DhUniqueID> &dhUniqueIds,
80         std::vector<std::string> &virKeyboardPaths);
81     void NotifyNodeMgrScanVirNode(const std::string &devId, const std::string &dhId);
82     void RegisterInjectEventCb(sptr<ISessionStateCallback> callback);
83     void UnregisterInjectEventCb();
84 
85     class DInputNodeManagerEventHandler : public AppExecFwk::EventHandler {
86     public:
87         DInputNodeManagerEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> &runner,
88             DistributedInputNodeManager *manager);
89         ~DInputNodeManagerEventHandler() override;
90 
91         void ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) override;
92     private:
93         void ScanAllNode(const AppExecFwk::InnerEvent::Pointer &event);
94 
95         using nodeMgrFunc = void (DInputNodeManagerEventHandler::*)(
96             const AppExecFwk::InnerEvent::Pointer &event);
97         std::map<int32_t, nodeMgrFunc> eventFuncMap_;
98         DistributedInputNodeManager *nodeManagerObj_;
99     };
100 
101 private:
102     void AddDeviceLocked(const std::string &networkId, const std::string &dhId, std::unique_ptr<VirtualDevice> device);
103     int32_t CreateHandle(const InputDevice &inputDevice, const std::string &devId, const std::string &dhId);
104     void ParseInputDeviceJson(const std::string &str, InputDevice &pBuf);
105     void ParseInputDevice(const nlohmann::json &inputDeviceJson, InputDevice &pBuf);
106     void ParseInputDeviceBasicInfo(const nlohmann::json &inputDeviceJson, InputDevice &pBuf);
107     void ParseInputDeviceEvents(const nlohmann::json &inputDeviceJson, InputDevice &pBuf);
108     void InjectEvent();
109 
110     void ScanSinkInputDevices(const std::string &devId, const std::string &dhId);
111     bool MatchAndSavePhysicalPath(const std::string &devicePath, const std::string &devId, const std::string &dhId);
112     bool IsVirtualDev(int fd);
113     bool GetDevDhUniqueIdByFd(int fd, DhUniqueID &dhUnqueId, std::string &physicalPath);
114     void SetPathForVirDev(const DhUniqueID &dhUniqueId, const std::string &devicePath);
115     void RunInjectEventCallback(const std::string &dhId, const uint32_t injectEvent);
116 
117     /* the key is {networkId, dhId}, and the value is virtualDevice */
118     std::map<DhUniqueID, std::unique_ptr<VirtualDevice>> virtualDeviceMap_;
119     std::mutex virtualDeviceMapMutex_;
120     std::atomic<bool> isInjectThreadCreated_;
121     std::atomic<bool> isInjectThreadRunning_;
122     std::mutex operationMutex_;
123     std::thread eventInjectThread_;
124     std::mutex injectThreadMutex_;
125     std::condition_variable conditionVariable_;
126     std::queue<EventBatch> injectQueue_;
127     int32_t virtualTouchScreenFd_;
128     std::once_flag callOnceFlag_;
129     std::shared_ptr<DInputNodeManagerEventHandler> callBackHandler_;
130     sptr<ISessionStateCallback> SessionStateCallback_;
131 };
132 } // namespace DistributedInput
133 } // namespace DistributedHardware
134 } // namespace OHOS
135 
136 #endif // DISTRIBUTED_INPUT_INJECT_H