1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#ifndef ANDROID_DVR_BUFFERHUBD_BUFFER_HUB_H_
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define ANDROID_DVR_BUFFERHUBD_BUFFER_HUB_H_
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <memory>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <string>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <unordered_map>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <hardware/gralloc.h>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/service.h>
101db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka#include <private/dvr/bufferhub_rpc.h>
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace dvr {
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass BufferHubService;
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ConsumerChannel;
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ProducerChannel;
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ConsumerQueueChannel;
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ProducerQueueChannel;
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass BufferHubChannel : public pdx::Channel {
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  enum ChannelType {
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    kProducerType,
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    kConsumerType,
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    kProducerQueueType,
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    kConsumerQueueType,
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  };
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  enum : int { kDetachedId = -1 };
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  BufferHubChannel(BufferHubService* service, int buffer_id, int channel_id,
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                   ChannelType channel_type)
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      : service_(service),
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        buffer_id_(buffer_id),
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        channel_id_(channel_id),
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        channel_type_(channel_type) {}
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  virtual ~BufferHubChannel() {}
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  virtual bool HandleMessage(pdx::Message& message) = 0;
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  virtual void HandleImpulse(pdx::Message& message) = 0;
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Captures buffer info for use by BufferHubService::DumpState().
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  struct BufferInfo {
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Common data field shared by BufferProducer and ProducerQueue.
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    int id = -1;
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    int type = -1;
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t consumer_count = 0;
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Data field for buffer producer.
51cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka    uint32_t width = 0;
52cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka    uint32_t height = 0;
53108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar    uint32_t layer_count = 0;
54cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka    uint32_t format = 0;
550057fddc71d1c3c3de8f9d0bd45a51bb293bfa3cJiwen 'Steve' Cai    uint64_t usage = 0;
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::string name;
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Data filed for producer queue.
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    size_t capacity = 0;
600057fddc71d1c3c3de8f9d0bd45a51bb293bfa3cJiwen 'Steve' Cai    UsagePolicy usage_policy{0, 0, 0, 0};
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
62cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka    BufferInfo(int id, size_t consumer_count, uint32_t width, uint32_t height,
63108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar               uint32_t layer_count, uint32_t format, uint64_t usage, const std::string& name)
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        : id(id),
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          type(kProducerType),
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          consumer_count(consumer_count),
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          width(width),
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          height(height),
69108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar          layer_count(layer_count),
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          format(format),
710057fddc71d1c3c3de8f9d0bd45a51bb293bfa3cJiwen 'Steve' Cai          usage(usage),
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          name(name) {}
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
741db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka    BufferInfo(int id, size_t consumer_count, size_t capacity,
75cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka               const UsagePolicy& usage_policy)
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        : id(id),
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          type(kProducerQueueType),
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          consumer_count(consumer_count),
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          capacity(capacity),
80cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka          usage_policy(usage_policy) {}
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    BufferInfo() {}
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  };
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Returns the buffer info for this buffer.
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  virtual BufferInfo GetBufferInfo() const = 0;
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Signal the client fd that an ownership change occurred using POLLIN.
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void SignalAvailable();
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Clear the ownership change event.
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void ClearAvailable();
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Signal hangup event.
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void Hangup();
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  BufferHubService* service() const { return service_; }
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ChannelType channel_type() const { return channel_type_; }
99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int buffer_id() const { return buffer_id_; }
100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int channel_id() const { return channel_id_; }
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool IsDetached() const { return channel_id_ == kDetachedId; }
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void Detach() {
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (channel_type_ == kProducerType)
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      channel_id_ = kDetachedId;
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void Attach(int channel_id) {
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (channel_type_ == kProducerType && channel_id_ == kDetachedId)
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      channel_id_ = channel_id;
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  BufferHubService* service_;
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Static id of the buffer for logging and informational purposes. This id
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // does not change for the life of the buffer.
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // TODO(eieio): Consider using an id allocator instead of the originating
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // channel id; channel ids wrap after 2^31 ids, but this is not a problem in
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // general because channel ids are not used for any lookup in this service.
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int buffer_id_;
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // The channel id of the buffer. This may change for a persistent producer
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // buffer if it is detached and re-attached to another channel.
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int channel_id_;
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ChannelType channel_type_;
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  BufferHubChannel(const BufferHubChannel&) = delete;
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void operator=(const BufferHubChannel&) = delete;
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass BufferHubService : public pdx::ServiceBase<BufferHubService> {
134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  BufferHubService();
136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ~BufferHubService() override;
137e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
138f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  pdx::Status<void> HandleMessage(pdx::Message& message) override;
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void HandleImpulse(pdx::Message& message) override;
140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void OnChannelClose(pdx::Message& message,
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                      const std::shared_ptr<pdx::Channel>& channel) override;
143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool IsInitialized() const override;
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::string DumpState(size_t max_length) override;
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool AddNamedBuffer(const std::string& name,
148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                      const std::shared_ptr<ProducerChannel>& buffer);
149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::shared_ptr<ProducerChannel> GetNamedBuffer(const std::string& name);
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool RemoveNamedBuffer(const ProducerChannel& buffer);
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  friend BASE;
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::unordered_map<std::string, std::shared_ptr<ProducerChannel>>
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      named_buffers_;
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1580057fddc71d1c3c3de8f9d0bd45a51bb293bfa3cJiwen 'Steve' Cai  pdx::Status<void> OnCreateBuffer(pdx::Message& message, uint32_t width,
1590057fddc71d1c3c3de8f9d0bd45a51bb293bfa3cJiwen 'Steve' Cai                                   uint32_t height, uint32_t format,
1604d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar                                   uint64_t usage, size_t meta_size_bytes);
1614d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  pdx::Status<void> OnCreatePersistentBuffer(pdx::Message& message,
1624d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar                                             const std::string& name,
1634d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar                                             int user_id, int group_id,
1644d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar                                             uint32_t width, uint32_t height,
1654d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar                                             uint32_t format, uint64_t usage,
1664d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar                                             size_t meta_size_bytes);
1670057fddc71d1c3c3de8f9d0bd45a51bb293bfa3cJiwen 'Steve' Cai  pdx::Status<void> OnGetPersistentBuffer(pdx::Message& message,
1680057fddc71d1c3c3de8f9d0bd45a51bb293bfa3cJiwen 'Steve' Cai                                          const std::string& name);
169cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka  pdx::Status<QueueInfo> OnCreateProducerQueue(pdx::Message& message,
170cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka                                               size_t meta_size_bytes,
171cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka                                               const UsagePolicy& usage_policy);
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  BufferHubService(const BufferHubService&) = delete;
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void operator=(const BufferHubService&) = delete;
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace dvr
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#endif  // ANDROID_DVR_BUFFERHUBD_BUFFER_HUB_H_
181