1#ifndef ANDROID_PDX_CHANNEL_HANDLE_H_
2#define ANDROID_PDX_CHANNEL_HANDLE_H_
3
4#include <cstdint>
5#include <type_traits>
6
7namespace android {
8namespace pdx {
9
10enum class ChannelHandleMode {
11  Local,
12  Borrowed,
13  Remote,
14};
15
16class 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
26class ChannelHandleBase {
27 public:
28  ChannelHandleBase() = default;
29  ChannelHandleBase(const int32_t& value) : value_{value} {}
30
31  ChannelHandleBase(const ChannelHandleBase&) = delete;
32  ChannelHandleBase& operator=(const ChannelHandleBase&) = delete;
33
34  std::int32_t value() const { return value_; }
35  bool valid() const { return value_ >= 0; }
36  explicit operator bool() const { return valid(); }
37
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
48template <ChannelHandleMode Mode>
49class ChannelHandle : public ChannelHandleBase {
50 public:
51  ChannelHandle() = default;
52  using ChannelHandleBase::ChannelHandleBase;
53  ChannelHandle(ChannelHandle&& other) : ChannelHandleBase{other.value_} {
54    other.value_ = kEmptyHandle;
55  }
56  ~ChannelHandle() = default;
57
58  ChannelHandle Duplicate() const { return ChannelHandle{value_}; }
59
60  ChannelHandle& operator=(ChannelHandle&& other) {
61    value_ = other.value_;
62    other.value_ = kEmptyHandle;
63    return *this;
64  }
65};
66
67template <>
68class ChannelHandle<ChannelHandleMode::Local> : public ChannelHandleBase {
69 public:
70  ChannelHandle() = default;
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
77  ChannelHandle(ChannelHandle&& other)
78      : ChannelHandleBase{other.value_}, manager_{other.manager_} {
79    other.manager_ = nullptr;
80    other.value_ = kEmptyHandle;
81  }
82
83  ChannelHandle& operator=(ChannelHandle&& other) {
84    value_ = other.value_;
85    manager_ = other.manager_;
86    other.value_ = kEmptyHandle;
87    other.manager_ = nullptr;
88    return *this;
89  }
90
91  ~ChannelHandle() {
92    if (manager_)
93      manager_->CloseHandle(value_);
94  }
95
96  ChannelHandle<ChannelHandleMode::Borrowed> Borrow() const {
97    return ChannelHandle<ChannelHandleMode::Borrowed>{value_};
98  }
99
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
111using LocalChannelHandle = ChannelHandle<ChannelHandleMode::Local>;
112using BorrowedChannelHandle = ChannelHandle<ChannelHandleMode::Borrowed>;
113using 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().
118using ChannelReference = int32_t;
119
120}  // namespace pdx
121}  // namespace android
122
123#endif  // ANDROID_PDX_CHANNEL_HANDLE_H_
124