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