blob: dcc6ea4fe2ecbae4afea79c01b4a8387a6bcad28 [file] [log] [blame]
Fan Xu74df4902018-09-20 16:40:51 -07001#include <private/dvr/buffer_channel.h>
2#include <private/dvr/producer_channel.h>
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -07003
4using android::pdx::BorrowedHandle;
5using android::pdx::ErrorStatus;
6using android::pdx::Message;
7using android::pdx::RemoteChannelHandle;
8using android::pdx::Status;
9using android::pdx::rpc::DispatchRemoteMethod;
10
11namespace android {
12namespace dvr {
13
14BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
15 int channel_id, IonBuffer buffer,
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -070016 size_t user_metadata_size)
17 : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType),
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -070018 buffer_node_(
19 std::make_shared<BufferNode>(std::move(buffer), user_metadata_size)),
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -070020 buffer_state_bit_(BufferHubDefs::FindFirstClearedBit()) {
21 buffer_node_->set_buffer_state_bit(buffer_state_bit_);
22}
23
24BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
25 uint32_t width, uint32_t height,
26 uint32_t layer_count, uint32_t format,
27 uint64_t usage, size_t user_metadata_size)
28 : BufferHubChannel(service, buffer_id, buffer_id, kDetachedBufferType),
29 buffer_node_(std::make_shared<BufferNode>(
30 width, height, layer_count, format, usage, user_metadata_size)),
31 buffer_state_bit_(BufferHubDefs::FindFirstClearedBit()) {
32 buffer_node_->set_buffer_state_bit(buffer_state_bit_);
33}
34
35BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
36 int channel_id,
37 std::shared_ptr<BufferNode> buffer_node,
38 uint64_t buffer_state_bit)
39 : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType),
40 buffer_node_(buffer_node),
41 buffer_state_bit_(buffer_state_bit) {
42 buffer_node_->set_buffer_state_bit(buffer_state_bit_);
43}
44
45BufferChannel::~BufferChannel() {
46 ALOGD_IF(TRACE, "BufferChannel::~BufferChannel: channel_id=%d buffer_id=%d.",
47 channel_id(), buffer_id());
48 Hangup();
49}
50
51BufferHubChannel::BufferInfo BufferChannel::GetBufferInfo() const {
52 return BufferInfo(
53 buffer_id(), /*consumer_count=*/0, buffer_node_->buffer().width(),
54 buffer_node_->buffer().height(), buffer_node_->buffer().layer_count(),
55 buffer_node_->buffer().format(), buffer_node_->buffer().usage(),
56 /*pending_count=*/0, /*state=*/0, /*signaled_mask=*/0,
57 /*index=*/0);
58}
59
60void BufferChannel::HandleImpulse(Message& /*message*/) {
61 ATRACE_NAME("BufferChannel::HandleImpulse");
62}
63
64bool BufferChannel::HandleMessage(Message& message) {
65 ATRACE_NAME("BufferChannel::HandleMessage");
66 switch (message.GetOp()) {
67 case DetachedBufferRPC::Import::Opcode:
68 DispatchRemoteMethod<DetachedBufferRPC::Import>(
69 *this, &BufferChannel::OnImport, message);
70 return true;
71
72 case DetachedBufferRPC::Duplicate::Opcode:
73 DispatchRemoteMethod<DetachedBufferRPC::Duplicate>(
74 *this, &BufferChannel::OnDuplicate, message);
75 return true;
76
77 case DetachedBufferRPC::Promote::Opcode:
78 DispatchRemoteMethod<DetachedBufferRPC::Promote>(
79 *this, &BufferChannel::OnPromote, message);
80 return true;
81
82 default:
83 return false;
84 }
85}
86
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -070087Status<BufferTraits<BorrowedHandle>> BufferChannel::OnImport(
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -070088 Message& /*message*/) {
89 ATRACE_NAME("BufferChannel::OnImport");
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -070090 ALOGD_IF(TRACE, "BufferChannel::OnImport: buffer=%d.", buffer_id());
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -070091
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -070092 // TODO(b/112057680) Move away from the GraphicBuffer-based IonBuffer.
93 return BufferTraits<BorrowedHandle>{
94 /*buffer_handle=*/buffer_node_->buffer().handle(),
95 /*metadata_handle=*/buffer_node_->metadata().ashmem_handle().Borrow(),
96 /*id=*/buffer_id(),
97 /*buffer_state_bit=*/buffer_state_bit_,
98 /*metadata_size=*/buffer_node_->metadata().metadata_size(),
99 /*width=*/buffer_node_->buffer().width(),
100 /*height=*/buffer_node_->buffer().height(),
101 /*layer_count=*/buffer_node_->buffer().layer_count(),
102 /*format=*/buffer_node_->buffer().format(),
103 /*usage=*/buffer_node_->buffer().usage(),
104 /*stride=*/buffer_node_->buffer().stride(),
105 /*acquire_fence_fd=*/BorrowedHandle{},
106 /*released_fence_fd=*/BorrowedHandle{}};
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -0700107}
108
109Status<RemoteChannelHandle> BufferChannel::OnDuplicate(
110 Message& message) {
111 ATRACE_NAME("BufferChannel::OnDuplicate");
112 ALOGD_IF(TRACE, "BufferChannel::OnDuplicate: buffer=%d.",
113 buffer_id());
114
115 int channel_id;
116 auto status = message.PushChannel(0, nullptr, &channel_id);
117 if (!status) {
118 ALOGE(
119 "BufferChannel::OnDuplicate: Failed to push buffer channel: %s",
120 status.GetErrorMessage().c_str());
121 return ErrorStatus(ENOMEM);
122 }
123
124 // Try find the next buffer state bit which has not been claimed by any
125 // other buffers yet.
126 uint64_t buffer_state_bit =
127 BufferHubDefs::FindNextClearedBit(buffer_node_->active_buffer_bit_mask() |
128 BufferHubDefs::kProducerStateBit);
129 if (buffer_state_bit == 0ULL) {
130 ALOGE(
131 "BufferChannel::OnDuplicate: reached the maximum mumber of channels "
132 "per buffer node: 63.");
133 return ErrorStatus(E2BIG);
134 }
135
136 auto channel =
137 std::shared_ptr<BufferChannel>(new BufferChannel(
138 service(), buffer_id(), channel_id, buffer_node_, buffer_state_bit));
139 if (!channel) {
140 ALOGE("BufferChannel::OnDuplicate: Invalid buffer.");
141 return ErrorStatus(EINVAL);
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 "BufferChannel::OnDuplicate: Failed to set new buffer channel: %s.",
151 channel_status.GetErrorMessage().c_str());
152 }
153
154 return status;
155}
156
157Status<RemoteChannelHandle> BufferChannel::OnPromote(
158 Message& message) {
159 ATRACE_NAME("BufferChannel::OnPromote");
160 ALOGD_IF(TRACE, "BufferChannel::OnPromote: buffer_id=%d", buffer_id());
161
162 // Check whether this is the channel exclusive owner of the buffer_node_.
163 if (buffer_state_bit_ != buffer_node_->active_buffer_bit_mask()) {
164 ALOGE(
165 "BufferChannel::OnPromote: Cannot promote this BufferChannel as its "
166 "BufferNode is shared between multiple channels. This channel's state "
167 "bit=0x%" PRIx64 ", acitve_buffer_bit_mask=0x%" PRIx64 ".",
168 buffer_state_bit_, buffer_node_->active_buffer_bit_mask());
169 return ErrorStatus(EINVAL);
170 }
171
172 // Note that the new ProducerChannel will have different channel_id, but
173 // inherits the buffer_id from the DetachedBuffer.
174 int channel_id;
175 auto status = message.PushChannel(0, nullptr, &channel_id);
176 if (!status) {
177 ALOGE(
178 "BufferChannel::OnPromote: Failed to push ProducerChannel: %s.",
179 status.GetErrorMessage().c_str());
180 return ErrorStatus(ENOMEM);
181 }
182
183 IonBuffer buffer = std::move(buffer_node_->buffer());
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -0700184 IonBuffer metadata_buffer;
185 if (int ret = metadata_buffer.Alloc(buffer_node_->metadata().metadata_size(),
186 /*height=*/1,
187 /*layer_count=*/1,
188 BufferHubDefs::kMetadataFormat,
189 BufferHubDefs::kMetadataUsage)) {
190 ALOGE("BufferChannel::OnPromote: Failed to allocate metadata: %s",
191 strerror(-ret));
192 return ErrorStatus(EINVAL);
193 }
194
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -0700195 size_t user_metadata_size = buffer_node_->user_metadata_size();
196
197 std::unique_ptr<ProducerChannel> channel = ProducerChannel::Create(
198 service(), buffer_id(), channel_id, std::move(buffer),
199 std::move(metadata_buffer), user_metadata_size);
200 if (!channel) {
201 ALOGE(
202 "BufferChannel::OnPromote: Failed to create ProducerChannel from a "
203 "BufferChannel, buffer_id=%d.",
204 buffer_id());
205 }
206
207 const auto channel_status =
208 service()->SetChannel(channel_id, std::move(channel));
209 if (!channel_status) {
210 // Technically, this should never fail, as we just pushed the channel. Note
211 // that LOG_FATAL will be stripped out in non-debug build.
212 LOG_FATAL(
213 "BufferChannel::OnPromote: Failed to set new producer buffer channel: "
214 "%s.",
215 channel_status.GetErrorMessage().c_str());
216 }
217
218 return status;
219}
220
221} // namespace dvr
222} // namespace android