1 #ifndef ANDROID_PDX_CHANNEL_HANDLE_H_
2 #define ANDROID_PDX_CHANNEL_HANDLE_H_
3 
4 #include <cstdint>
5 #include <type_traits>
6 
7 namespace android {
8 namespace pdx {
9 
10 enum class ChannelHandleMode {
11   Local,
12   Borrowed,
13   Remote,
14 };
15 
16 class ChannelManagerInterface {
17  public:
18   virtual void CloseHandle(std::int32_t handle) = 0;
19 
20  protected:
21   // Nobody should be allowed to delete the instance of channel manager
22   // through this interface.
23   virtual ~ChannelManagerInterface() = default;
24 };
25 
26 class ChannelHandleBase {
27  public:
28   ChannelHandleBase() = default;
ChannelHandleBase(const int32_t & value)29   explicit ChannelHandleBase(const int32_t& value) : value_{value} {}
30 
31   ChannelHandleBase(const ChannelHandleBase&) = delete;
32   ChannelHandleBase& operator=(const ChannelHandleBase&) = delete;
33 
value()34   std::int32_t value() const { return value_; }
valid()35   bool valid() const { return value_ >= 0; }
36   explicit operator bool() const { return valid(); }
37 
Close()38   void Close() { value_ = kEmptyHandle; }
39 
40  protected:
41   // Must not be used by itself. Must be derived from.
42   ~ChannelHandleBase() = default;
43   enum : std::int32_t { kEmptyHandle = -1 };
44 
45   std::int32_t value_{kEmptyHandle};
46 };
47 
48 template <ChannelHandleMode Mode>
49 class ChannelHandle : public ChannelHandleBase {
50  public:
51   ChannelHandle() = default;
52   using ChannelHandleBase::ChannelHandleBase;
ChannelHandle(ChannelHandle && other)53   ChannelHandle(ChannelHandle&& other) noexcept : ChannelHandleBase{other.value_} {
54     other.value_ = kEmptyHandle;
55   }
56   ~ChannelHandle() = default;
57 
Duplicate()58   ChannelHandle Duplicate() const { return ChannelHandle{value_}; }
59 
60   ChannelHandle& operator=(ChannelHandle&& other) noexcept {
61     value_ = other.value_;
62     other.value_ = kEmptyHandle;
63     return *this;
64   }
65 };
66 
67 template <>
68 class ChannelHandle<ChannelHandleMode::Local> : public ChannelHandleBase {
69  public:
70   ChannelHandle() = default;
ChannelHandle(ChannelManagerInterface * manager,int32_t value)71   ChannelHandle(ChannelManagerInterface* manager, int32_t value)
72       : ChannelHandleBase{value}, manager_{manager} {}
73 
74   ChannelHandle(const ChannelHandle&) = delete;
75   ChannelHandle& operator=(const ChannelHandle&) = delete;
76 
ChannelHandle(ChannelHandle && other)77   ChannelHandle(ChannelHandle&& other) noexcept
78       : ChannelHandleBase{other.value_}, manager_{other.manager_} {
79     other.manager_ = nullptr;
80     other.value_ = kEmptyHandle;
81   }
82 
83   ChannelHandle& operator=(ChannelHandle&& other) noexcept {
84     value_ = other.value_;
85     manager_ = other.manager_;
86     other.value_ = kEmptyHandle;
87     other.manager_ = nullptr;
88     return *this;
89   }
90 
~ChannelHandle()91   ~ChannelHandle() {
92     if (manager_)
93       manager_->CloseHandle(value_);
94   }
95 
Borrow()96   ChannelHandle<ChannelHandleMode::Borrowed> Borrow() const {
97     return ChannelHandle<ChannelHandleMode::Borrowed>{value_};
98   }
99 
Close()100   void Close() {
101     if (manager_)
102       manager_->CloseHandle(value_);
103     manager_ = nullptr;
104     value_ = kEmptyHandle;
105   }
106 
107  private:
108   ChannelManagerInterface* manager_{nullptr};
109 };
110 
111 using LocalChannelHandle = ChannelHandle<ChannelHandleMode::Local>;
112 using BorrowedChannelHandle = ChannelHandle<ChannelHandleMode::Borrowed>;
113 using RemoteChannelHandle = ChannelHandle<ChannelHandleMode::Remote>;
114 
115 // ChannelReference is a 32 bit integer used in IPC serialization to be
116 // transferred across processes. You can convert this value to a local channel
117 // handle by calling Transaction.GetChannelHandle().
118 using ChannelReference = int32_t;
119 
120 }  // namespace pdx
121 }  // namespace android
122 
123 #endif  // ANDROID_PDX_CHANNEL_HANDLE_H_
124