1 #include "detached_buffer_channel.h"
2 #include "producer_channel.h"
3 
4 using android::pdx::BorrowedHandle;
5 using android::pdx::ErrorStatus;
6 using android::pdx::Message;
7 using android::pdx::RemoteChannelHandle;
8 using android::pdx::Status;
9 using android::pdx::rpc::DispatchRemoteMethod;
10 
11 namespace android {
12 namespace dvr {
13 
DetachedBufferChannel(BufferHubService * service,int buffer_id,int channel_id,IonBuffer buffer,IonBuffer metadata_buffer,size_t user_metadata_size)14 DetachedBufferChannel::DetachedBufferChannel(BufferHubService* service,
15                                              int buffer_id, int channel_id,
16                                              IonBuffer buffer,
17                                              IonBuffer metadata_buffer,
18                                              size_t user_metadata_size)
19     : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType),
20       buffer_(std::move(buffer)),
21       metadata_buffer_(std::move(metadata_buffer)),
22       user_metadata_size_(user_metadata_size) {
23 }
24 
DetachedBufferChannel(BufferHubService * service,int buffer_id,uint32_t width,uint32_t height,uint32_t layer_count,uint32_t format,uint64_t usage,size_t user_metadata_size)25 DetachedBufferChannel::DetachedBufferChannel(BufferHubService* service,
26                                              int buffer_id, uint32_t width,
27                                              uint32_t height,
28                                              uint32_t layer_count,
29                                              uint32_t format, uint64_t usage,
30                                              size_t user_metadata_size)
31     : BufferHubChannel(service, buffer_id, buffer_id, kDetachedBufferType),
32       user_metadata_size_(user_metadata_size) {
33   // The size the of metadata buffer is used as the "width" parameter during
34   // allocation. Thus it cannot overflow uint32_t.
35   if (user_metadata_size_ >= (std::numeric_limits<uint32_t>::max() -
36                               BufferHubDefs::kMetadataHeaderSize)) {
37     ALOGE(
38         "DetachedBufferChannel::DetachedBufferChannel: metadata size too big.");
39     return;
40   }
41 
42   if (int ret = buffer_.Alloc(width, height, layer_count, format, usage)) {
43     ALOGE(
44         "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate "
45         "buffer: %s",
46         strerror(-ret));
47     return;
48   }
49 
50   // Buffer metadata has two parts: 1) a fixed sized metadata header; and 2)
51   // user requested metadata.
52   const size_t size = BufferHubDefs::kMetadataHeaderSize + user_metadata_size_;
53   if (int ret = metadata_buffer_.Alloc(size,
54                                        /*height=*/1,
55                                        /*layer_count=*/1,
56                                        BufferHubDefs::kMetadataFormat,
57                                        BufferHubDefs::kMetadataUsage)) {
58     ALOGE(
59         "DetachedBufferChannel::DetachedBufferChannel: Failed to allocate "
60         "metadata: %s",
61         strerror(-ret));
62     return;
63   }
64 }
65 
~DetachedBufferChannel()66 DetachedBufferChannel::~DetachedBufferChannel() {
67   ALOGD_IF(TRACE,
68            "DetachedBufferChannel::~DetachedBufferChannel: channel_id=%d "
69            "buffer_id=%d.",
70            channel_id(), buffer_id());
71   Hangup();
72 }
73 
GetBufferInfo() const74 BufferHubChannel::BufferInfo DetachedBufferChannel::GetBufferInfo() const {
75   return BufferInfo(buffer_id(), /*consumer_count=*/0, buffer_.width(),
76                     buffer_.height(), buffer_.layer_count(), buffer_.format(),
77                     buffer_.usage(), /*pending_count=*/0, /*state=*/0,
78                     /*signaled_mask=*/0, /*index=*/0);
79 }
80 
HandleImpulse(Message &)81 void DetachedBufferChannel::HandleImpulse(Message& /*message*/) {
82   ATRACE_NAME("DetachedBufferChannel::HandleImpulse");
83 }
84 
HandleMessage(Message & message)85 bool DetachedBufferChannel::HandleMessage(Message& message) {
86   ATRACE_NAME("DetachedBufferChannel::HandleMessage");
87   switch (message.GetOp()) {
88     case DetachedBufferRPC::Import::Opcode:
89       DispatchRemoteMethod<DetachedBufferRPC::Import>(
90           *this, &DetachedBufferChannel::OnImport, message);
91       return true;
92 
93     case DetachedBufferRPC::Promote::Opcode:
94       DispatchRemoteMethod<DetachedBufferRPC::Promote>(
95           *this, &DetachedBufferChannel::OnPromote, message);
96       return true;
97 
98     default:
99       return false;
100   }
101 }
102 
OnImport(Message &)103 Status<BufferDescription<BorrowedHandle>> DetachedBufferChannel::OnImport(
104     Message& /*message*/) {
105   ATRACE_NAME("DetachedBufferChannel::OnGetBuffer");
106   ALOGD_IF(TRACE, "DetachedBufferChannel::OnGetBuffer: buffer=%d.",
107            buffer_id());
108 
109   return BufferDescription<BorrowedHandle>{buffer_,
110                                            metadata_buffer_,
111                                            buffer_id(),
112                                            /*buffer_state_bit=*/0,
113                                            BorrowedHandle{},
114                                            BorrowedHandle{}};
115 }
116 
OnPromote(Message & message)117 Status<RemoteChannelHandle> DetachedBufferChannel::OnPromote(
118     Message& message) {
119   ATRACE_NAME("DetachedBufferChannel::OnPromote");
120   ALOGD_IF(TRACE, "DetachedBufferChannel::OnPromote: buffer_id=%d",
121            buffer_id());
122 
123   // Note that the new ProducerChannel will have different channel_id, but
124   // inherits the buffer_id from the DetachedBuffer.
125   int channel_id;
126   auto status = message.PushChannel(0, nullptr, &channel_id);
127   if (!status) {
128     ALOGE(
129         "DetachedBufferChannel::OnPromote: Failed to push ProducerChannel: %s.",
130         status.GetErrorMessage().c_str());
131     return ErrorStatus(ENOMEM);
132   }
133 
134   std::unique_ptr<ProducerChannel> channel = ProducerChannel::Create(
135       service(), buffer_id(), channel_id, std::move(buffer_),
136       std::move(metadata_buffer_), user_metadata_size_);
137   if (!channel) {
138     ALOGE(
139         "DetachedBufferChannel::OnPromote: Failed to create ProducerChannel "
140         "from a DetachedBufferChannel, buffer_id=%d.",
141         buffer_id());
142   }
143 
144   const auto channel_status =
145       service()->SetChannel(channel_id, std::move(channel));
146   if (!channel_status) {
147     // Technically, this should never fail, as we just pushed the channel. Note
148     // that LOG_FATAL will be stripped out in non-debug build.
149     LOG_FATAL(
150         "DetachedBufferChannel::OnPromote: Failed to set new producer buffer "
151         "channel: %s.",
152         channel_status.GetErrorMessage().c_str());
153   }
154 
155   return status;
156 }
157 
158 }  // namespace dvr
159 }  // namespace android
160