1 #ifndef ANDROID_DVR_NATIVE_HANDLE_WRAPPER_H_
2 #define ANDROID_DVR_NATIVE_HANDLE_WRAPPER_H_
3 
4 #include <cutils/native_handle.h>
5 #include <log/log.h>
6 #include <pdx/rpc/serializable.h>
7 
8 #include <vector>
9 
10 namespace android {
11 namespace dvr {
12 
13 // A PDX-friendly wrapper to maintain the life cycle of a native_handle_t
14 // object.
15 //
16 // See https://source.android.com/devices/architecture/hidl/types#handle_t for
17 // more information about native_handle_t.
18 template <typename FileHandleType>
19 class NativeHandleWrapper {
20  public:
21   NativeHandleWrapper() = default;
22   NativeHandleWrapper(NativeHandleWrapper&& other) = default;
23   NativeHandleWrapper& operator=(NativeHandleWrapper&& other) = default;
24 
25   // Create a new NativeHandleWrapper by duplicating the handle.
NativeHandleWrapper(const native_handle_t * handle)26   explicit NativeHandleWrapper(const native_handle_t* handle) {
27     const int fd_count = handle->numFds;
28     const int int_count = handle->numInts;
29 
30     // Populate the fd and int vectors: native_handle->data[] is an array of fds
31     // followed by an array of opaque ints.
32     for (int i = 0; i < fd_count; i++) {
33       fds_.emplace_back(FileHandleType::AsDuplicate(handle->data[i]));
34     }
35     for (int i = 0; i < int_count; i++) {
36       ints_.push_back(handle->data[fd_count + i]);
37     }
38   }
39 
int_count()40   size_t int_count() const { return ints_.size(); }
fd_count()41   size_t fd_count() const { return fds_.size(); }
IsValid()42   bool IsValid() const { return ints_.size() != 0 || fds_.size() != 0; }
43 
44   // Duplicate a native handle from the wrapper.
DuplicateHandle()45   native_handle_t* DuplicateHandle() const {
46     if (!IsValid()) {
47       return nullptr;
48     }
49 
50     // numFds + numInts ints.
51     std::vector<FileHandleType> fds;
52     for (const auto& fd : fds_) {
53       if (!fd.IsValid()) {
54         return nullptr;
55       }
56       fds.emplace_back(fd.Duplicate());
57     }
58 
59     return FromFdsAndInts(std::move(fds), ints_);
60   }
61 
62   // Takes the native handle out of the wrapper.
TakeHandle()63   native_handle_t* TakeHandle() {
64     if (!IsValid()) {
65       return nullptr;
66     }
67 
68     return FromFdsAndInts(std::move(fds_), std::move(ints_));
69   }
70 
71  private:
72   NativeHandleWrapper(const NativeHandleWrapper&) = delete;
73   void operator=(const NativeHandleWrapper&) = delete;
74 
FromFdsAndInts(std::vector<FileHandleType> fds,std::vector<int> ints)75   static native_handle_t* FromFdsAndInts(std::vector<FileHandleType> fds,
76                                          std::vector<int> ints) {
77     native_handle_t* handle = native_handle_create(fds.size(), ints.size());
78     if (!handle) {
79       ALOGE("NativeHandleWrapper::TakeHandle: Failed to create new handle.");
80       return nullptr;
81     }
82 
83     // numFds + numInts ints.
84     for (int i = 0; i < handle->numFds; i++) {
85       handle->data[i] = fds[i].Release();
86     }
87     memcpy(&handle->data[handle->numFds], ints.data(),
88            sizeof(int) * handle->numInts);
89 
90     return handle;
91   }
92 
93   std::vector<int> ints_;
94   std::vector<FileHandleType> fds_;
95 
96   PDX_SERIALIZABLE_MEMBERS(NativeHandleWrapper<FileHandleType>, ints_, fds_);
97 };
98 
99 }  // namespace dvr
100 }  // namespace android
101 
102 #endif  // ANDROID_DVR_NATIVE_HANDLE_WRAPPER_H_
103