1#include "include/dvr/dvr_hardware_composer_client.h"
2
3#include <android/dvr/IVrComposer.h>
4#include <android/dvr/BnVrComposerCallback.h>
5#include <android/hardware_buffer.h>
6#include <binder/IServiceManager.h>
7#include <private/android/AHardwareBufferHelpers.h>
8
9#include <functional>
10#include <memory>
11#include <mutex>
12
13struct DvrHwcFrame {
14  android::dvr::ComposerView::Frame frame;
15};
16
17namespace {
18
19class HwcCallback : public android::dvr::BnVrComposerCallback {
20 public:
21  using CallbackFunction = std::function<int(DvrHwcFrame*)>;
22
23  explicit HwcCallback(const CallbackFunction& callback);
24  ~HwcCallback() override;
25
26  // Reset the callback. This needs to be done early to avoid use after free
27  // accesses from binder thread callbacks.
28  void Shutdown();
29
30  std::unique_ptr<DvrHwcFrame> DequeueFrame();
31
32 private:
33  // android::dvr::BnVrComposerCallback:
34  android::binder::Status onNewFrame(
35      const android::dvr::ParcelableComposerFrame& frame,
36      android::dvr::ParcelableUniqueFd* fence) override;
37
38  // Protects the |callback_| from uses from multiple threads. During shutdown
39  // there may be in-flight frame update events. In those cases the callback
40  // access needs to be protected otherwise binder threads may access an invalid
41  // callback.
42  std::mutex mutex_;
43  CallbackFunction callback_;
44
45  HwcCallback(const HwcCallback&) = delete;
46  void operator=(const HwcCallback&) = delete;
47};
48
49HwcCallback::HwcCallback(const CallbackFunction& callback)
50    : callback_(callback) {}
51
52HwcCallback::~HwcCallback() {}
53
54void HwcCallback::Shutdown() {
55  std::lock_guard<std::mutex> guard(mutex_);
56  callback_ = nullptr;
57}
58
59android::binder::Status HwcCallback::onNewFrame(
60    const android::dvr::ParcelableComposerFrame& frame,
61    android::dvr::ParcelableUniqueFd* fence) {
62  std::lock_guard<std::mutex> guard(mutex_);
63
64  if (!callback_) {
65    fence->set_fence(android::base::unique_fd());
66    return android::binder::Status::ok();
67  }
68
69  std::unique_ptr<DvrHwcFrame> dvr_frame(new DvrHwcFrame());
70  dvr_frame->frame = frame.frame();
71
72  fence->set_fence(android::base::unique_fd(callback_(dvr_frame.release())));
73  return android::binder::Status::ok();
74}
75
76}  // namespace
77
78struct DvrHwcClient {
79  android::sp<android::dvr::IVrComposer> composer;
80  android::sp<HwcCallback> callback;
81};
82
83DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback, void* data) {
84  std::unique_ptr<DvrHwcClient> client(new DvrHwcClient());
85
86  android::sp<android::IServiceManager> sm(android::defaultServiceManager());
87  client->composer = android::interface_cast<android::dvr::IVrComposer>(
88      sm->getService(android::dvr::IVrComposer::SERVICE_NAME()));
89  if (!client->composer.get())
90    return nullptr;
91
92  client->callback = new HwcCallback(std::bind(callback, data,
93                                               std::placeholders::_1));
94  android::binder::Status status = client->composer->registerObserver(
95      client->callback);
96  if (!status.isOk())
97    return nullptr;
98
99  return client.release();
100}
101
102void dvrHwcClientDestroy(DvrHwcClient* client) {
103  client->composer->clearObserver();
104
105  // NOTE: Deleting DvrHwcClient* isn't enough since DvrHwcClient::callback is a
106  // shared pointer that could be referenced from a binder thread. But the
107  // client callback isn't valid past this calls so that needs to be reset.
108  client->callback->Shutdown();
109
110  delete client;
111}
112
113void dvrHwcFrameDestroy(DvrHwcFrame* frame) {
114  delete frame;
115}
116
117DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame) {
118  return frame->frame.display_id;
119}
120
121int32_t dvrHwcFrameGetDisplayWidth(DvrHwcFrame* frame) {
122  return frame->frame.display_width;
123}
124
125int32_t dvrHwcFrameGetDisplayHeight(DvrHwcFrame* frame) {
126  return frame->frame.display_height;
127}
128
129bool dvrHwcFrameGetDisplayRemoved(DvrHwcFrame* frame) {
130  return frame->frame.removed;
131}
132
133size_t dvrHwcFrameGetLayerCount(DvrHwcFrame* frame) {
134  return frame->frame.layers.size();
135}
136
137uint32_t dvrHwcFrameGetActiveConfig(DvrHwcFrame* frame) {
138  return static_cast<uint32_t>(frame->frame.active_config);
139}
140
141uint32_t dvrHwcFrameGetColorMode(DvrHwcFrame* frame) {
142  return static_cast<uint32_t>(frame->frame.color_mode);
143}
144
145void dvrHwcFrameGetColorTransform(DvrHwcFrame* frame, float* out_matrix,
146                                  int32_t* out_hint) {
147  *out_hint = frame->frame.color_transform_hint;
148  memcpy(out_matrix, frame->frame.color_transform,
149         sizeof(frame->frame.color_transform));
150}
151
152uint32_t dvrHwcFrameGetPowerMode(DvrHwcFrame* frame) {
153  return static_cast<uint32_t>(frame->frame.power_mode);
154}
155
156uint32_t dvrHwcFrameGetVsyncEnabled(DvrHwcFrame* frame) {
157  return static_cast<uint32_t>(frame->frame.vsync_enabled);
158}
159
160DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index) {
161  return frame->frame.layers[layer_index].id;
162}
163
164AHardwareBuffer* dvrHwcFrameGetLayerBuffer(DvrHwcFrame* frame,
165                                           size_t layer_index) {
166  AHardwareBuffer* buffer = android::AHardwareBuffer_from_GraphicBuffer(
167      frame->frame.layers[layer_index].buffer.get());
168  AHardwareBuffer_acquire(buffer);
169  return buffer;
170}
171
172int dvrHwcFrameGetLayerFence(DvrHwcFrame* frame, size_t layer_index) {
173  return frame->frame.layers[layer_index].fence->dup();
174}
175
176DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
177                                            size_t layer_index) {
178  return DvrHwcRecti{
179    frame->frame.layers[layer_index].display_frame.left,
180    frame->frame.layers[layer_index].display_frame.top,
181    frame->frame.layers[layer_index].display_frame.right,
182    frame->frame.layers[layer_index].display_frame.bottom,
183  };
184}
185
186DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index) {
187  return DvrHwcRectf{
188    frame->frame.layers[layer_index].crop.left,
189    frame->frame.layers[layer_index].crop.top,
190    frame->frame.layers[layer_index].crop.right,
191    frame->frame.layers[layer_index].crop.bottom,
192  };
193}
194
195DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
196                                             size_t layer_index) {
197  return static_cast<DvrHwcBlendMode>(
198      frame->frame.layers[layer_index].blend_mode);
199}
200
201float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index) {
202  return frame->frame.layers[layer_index].alpha;
203}
204
205uint32_t dvrHwcFrameGetLayerType(DvrHwcFrame* frame, size_t layer_index) {
206  return frame->frame.layers[layer_index].type;
207}
208
209uint32_t dvrHwcFrameGetLayerApplicationId(DvrHwcFrame* frame,
210                                          size_t layer_index) {
211  return frame->frame.layers[layer_index].app_id;
212}
213
214uint32_t dvrHwcFrameGetLayerZOrder(DvrHwcFrame* frame, size_t layer_index) {
215  return frame->frame.layers[layer_index].z_order;
216}
217
218void dvrHwcFrameGetLayerCursor(DvrHwcFrame* frame, size_t layer_index,
219                               int32_t* out_x, int32_t* out_y) {
220  *out_x = frame->frame.layers[layer_index].cursor_x;
221  *out_y = frame->frame.layers[layer_index].cursor_y;
222}
223
224uint32_t dvrHwcFrameGetLayerTransform(DvrHwcFrame* frame, size_t layer_index) {
225  return frame->frame.layers[layer_index].transform;
226}
227
228uint32_t dvrHwcFrameGetLayerDataspace(DvrHwcFrame* frame, size_t layer_index) {
229  return frame->frame.layers[layer_index].dataspace;
230}
231
232uint32_t dvrHwcFrameGetLayerColor(DvrHwcFrame* frame, size_t layer_index) {
233  const auto& color = frame->frame.layers[layer_index].color;
234  return color.r | (static_cast<uint32_t>(color.g) << 8) |
235         (static_cast<uint32_t>(color.b) << 16) |
236         (static_cast<uint32_t>(color.a) << 24);
237}
238
239uint32_t dvrHwcFrameGetLayerNumVisibleRegions(DvrHwcFrame* frame,
240                                              size_t layer_index) {
241  return frame->frame.layers[layer_index].visible_regions.size();
242}
243
244DvrHwcRecti dvrHwcFrameGetLayerVisibleRegion(DvrHwcFrame* frame,
245                                             size_t layer_index, size_t index) {
246  return DvrHwcRecti{
247      frame->frame.layers[layer_index].visible_regions[index].left,
248      frame->frame.layers[layer_index].visible_regions[index].top,
249      frame->frame.layers[layer_index].visible_regions[index].right,
250      frame->frame.layers[layer_index].visible_regions[index].bottom,
251  };
252}
253
254uint32_t dvrHwcFrameGetLayerNumDamagedRegions(DvrHwcFrame* frame,
255                                              size_t layer_index) {
256  return frame->frame.layers[layer_index].damaged_regions.size();
257}
258
259DvrHwcRecti dvrHwcFrameGetLayerDamagedRegion(DvrHwcFrame* frame,
260                                             size_t layer_index, size_t index) {
261  return DvrHwcRecti{
262      frame->frame.layers[layer_index].damaged_regions[index].left,
263      frame->frame.layers[layer_index].damaged_regions[index].top,
264      frame->frame.layers[layer_index].damaged_regions[index].right,
265      frame->frame.layers[layer_index].damaged_regions[index].bottom,
266  };
267}
268