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 #pragma once
18 
19 #include <android-base/unique_fd.h>
20 #include <input/TouchVideoFrame.h>
21 #include <stdint.h>
22 #include <array>
23 #include <optional>
24 #include <string>
25 #include <vector>
26 
27 namespace android {
28 
29 /**
30  * Represents a video device that uses v4l2 api to report touch heatmap data.
31  */
32 class TouchVideoDevice {
33 public:
34     /**
35      * Create a new TouchVideoDevice for the path provided.
36      * Return nullptr upon failure.
37      */
38     static std::unique_ptr<TouchVideoDevice> create(std::string devicePath);
39     ~TouchVideoDevice();
40 
hasValidFd()41     bool hasValidFd() const { return mFd.get() != INVALID_FD; }
42     /**
43      * Obtain the file descriptor associated with this video device.
44      * Could be used for adding to epoll.
45      */
getFd()46     int getFd() const { return mFd.get(); }
47     /**
48      * Get the name of this video device.
49      */
getName()50     const std::string& getName() const { return mName; }
51     /**
52      * Get the file path of this video device.
53      */
getPath()54     const std::string& getPath() const { return mPath; }
55     /**
56      * Get the height of the heatmap frame
57      */
getHeight()58     uint32_t getHeight() const { return mHeight; }
59     /**
60      * Get the width of the heatmap frame
61      */
getWidth()62     uint32_t getWidth() const { return mWidth; }
63     /**
64      * Direct read of the frame. Stores the frame into internal buffer.
65      * Return the number of frames that were successfully read.
66      *
67      * This function should not be called unless buffer is ready!
68      * This must be checked with select, poll, epoll, or similar api first.
69      * If epoll indicates that there is data ready to read, but this function
70      * returns zero, then it is likely an error occurred.
71      */
72     size_t readAndQueueFrames();
73     /**
74      * Return all of the queued frames, and erase them from the local buffer.
75      * The returned frames are in the order that they were received from the
76      * v4l2 device, with the oldest frame at the index 0.
77      */
78     std::vector<TouchVideoFrame> consumeFrames();
79     /**
80      * Get string representation of this video device.
81      */
82     std::string dump() const;
83 
84 private:
85     android::base::unique_fd mFd;
86     std::string mName;
87     std::string mPath;
88 
89     uint32_t mHeight;
90     uint32_t mWidth;
91 
92     static constexpr int INVALID_FD = -1;
93     /**
94      * How many buffers to request for heatmap.
95      * The kernel driver will be allocating these buffers for us,
96      * and will provide memory locations to read these from.
97      */
98     static constexpr size_t NUM_BUFFERS = 3;
99     std::array<const int16_t*, NUM_BUFFERS> mReadLocations;
100     /**
101      * How many buffers to keep for the internal queue. When the internal buffer
102      * exceeds this capacity, oldest frames will be dropped.
103      */
104     static constexpr size_t MAX_QUEUE_SIZE = 20;
105     std::vector<TouchVideoFrame> mFrames;
106 
107     /**
108      * The constructor is private because opening a v4l2 device requires many checks.
109      * To get a new TouchVideoDevice, use 'create' instead.
110      */
111     explicit TouchVideoDevice(int fd, std::string&& name, std::string&& devicePath, uint32_t height,
112                               uint32_t width,
113                               const std::array<const int16_t*, NUM_BUFFERS>& readLocations);
114     /**
115      * Read all currently available frames.
116      */
117     std::vector<TouchVideoFrame> readFrames();
118     /**
119      * Read a single frame. May return nullopt if no data is currently available for reading.
120      */
121     std::optional<TouchVideoFrame> readFrame();
122 };
123 
124 } // namespace android
125