1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _UI_INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
18 #define _UI_INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
19 
20 #include <android-base/unique_fd.h>
21 #include <input/TouchVideoFrame.h>
22 #include <stdint.h>
23 #include <array>
24 #include <optional>
25 #include <string>
26 #include <vector>
27 
28 namespace android {
29 
30 /**
31  * Represents a video device that uses v4l2 api to report touch heatmap data.
32  */
33 class TouchVideoDevice {
34 public:
35     /**
36      * Create a new TouchVideoDevice for the path provided.
37      * Return nullptr upon failure.
38      */
39     static std::unique_ptr<TouchVideoDevice> create(std::string devicePath);
40     ~TouchVideoDevice();
41 
hasValidFd()42     bool hasValidFd() const { return mFd.get() != INVALID_FD; }
43     /**
44      * Obtain the file descriptor associated with this video device.
45      * Could be used for adding to epoll.
46      */
getFd()47     int getFd() const { return mFd.get(); }
48     /**
49      * Get the name of this video device.
50      */
getName()51     const std::string& getName() const { return mName; }
52     /**
53      * Get the file path of this video device.
54      */
getPath()55     const std::string& getPath() const { return mPath; }
56     /**
57      * Get the height of the heatmap frame
58      */
getHeight()59     uint32_t getHeight() const { return mHeight; }
60     /**
61      * Get the width of the heatmap frame
62      */
getWidth()63     uint32_t getWidth() const { return mWidth; }
64     /**
65      * Direct read of the frame. Stores the frame into internal buffer.
66      * Return the number of frames that were successfully read.
67      *
68      * This function should not be called unless buffer is ready!
69      * This must be checked with select, poll, epoll, or similar api first.
70      * If epoll indicates that there is data ready to read, but this function
71      * returns zero, then it is likely an error occurred.
72      */
73     size_t readAndQueueFrames();
74     /**
75      * Return all of the queued frames, and erase them from the local buffer.
76      * The returned frames are in the order that they were received from the
77      * v4l2 device, with the oldest frame at the index 0.
78      */
79     std::vector<TouchVideoFrame> consumeFrames();
80     /**
81      * Get string representation of this video device.
82      */
83     std::string dump() const;
84 
85 private:
86     android::base::unique_fd mFd;
87     std::string mName;
88     std::string mPath;
89 
90     uint32_t mHeight;
91     uint32_t mWidth;
92 
93     static constexpr int INVALID_FD = -1;
94     /**
95      * How many buffers to request for heatmap.
96      * The kernel driver will be allocating these buffers for us,
97      * and will provide memory locations to read these from.
98      */
99     static constexpr size_t NUM_BUFFERS = 3;
100     std::array<const int16_t*, NUM_BUFFERS> mReadLocations;
101     /**
102      * How many buffers to keep for the internal queue. When the internal buffer
103      * exceeds this capacity, oldest frames will be dropped.
104      */
105     static constexpr size_t MAX_QUEUE_SIZE = 10;
106     std::vector<TouchVideoFrame> mFrames;
107 
108     /**
109      * The constructor is private because opening a v4l2 device requires many checks.
110      * To get a new TouchVideoDevice, use 'create' instead.
111      */
112     explicit TouchVideoDevice(int fd, std::string&& name, std::string&& devicePath, uint32_t height,
113                               uint32_t width,
114                               const std::array<const int16_t*, NUM_BUFFERS>& readLocations);
115     /**
116      * Read all currently available frames.
117      */
118     std::vector<TouchVideoFrame> readFrames();
119     /**
120      * Read a single frame. May return nullopt if no data is currently available for reading.
121      */
122     std::optional<TouchVideoFrame> readFrame();
123 };
124 
125 } // namespace android
126 
127 #endif // _UI_INPUTFLINGER_TOUCH_VIDEO_DEVICE_H
128