blob: 6d22dee5721ee7c8962e773bd469e36fd67d776f [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,
16 IonBuffer metadata_buffer,
17 size_t user_metadata_size)
18 : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType),
19 buffer_node_(std::make_shared<BufferNode>(
20 std::move(buffer), std::move(metadata_buffer), user_metadata_size)),
21 buffer_state_bit_(BufferHubDefs::FindFirstClearedBit()) {
22 buffer_node_->set_buffer_state_bit(buffer_state_bit_);
23}
24
25BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
26 uint32_t width, uint32_t height,
27 uint32_t layer_count, uint32_t format,
28 uint64_t usage, size_t user_metadata_size)
29 : BufferHubChannel(service, buffer_id, buffer_id, kDetachedBufferType),
30 buffer_node_(std::make_shared<BufferNode>(
31 width, height, layer_count, format, usage, user_metadata_size)),
32 buffer_state_bit_(BufferHubDefs::FindFirstClearedBit()) {
33 buffer_node_->set_buffer_state_bit(buffer_state_bit_);
34}
35
36BufferChannel::BufferChannel(BufferHubService* service, int buffer_id,
37 int channel_id,
38 std::shared_ptr<BufferNode> buffer_node,
39 uint64_t buffer_state_bit)
40 : BufferHubChannel(service, buffer_id, channel_id, kDetachedBufferType),
41 buffer_node_(buffer_node),
42 buffer_state_bit_(buffer_state_bit) {
43 buffer_node_->set_buffer_state_bit(buffer_state_bit_);
44}
45
46BufferChannel::~BufferChannel() {
47 ALOGD_IF(TRACE, "BufferChannel::~BufferChannel: channel_id=%d buffer_id=%d.",
48 channel_id(), buffer_id());
49 Hangup();
50}
51
52BufferHubChannel::BufferInfo BufferChannel::GetBufferInfo() const {
53 return BufferInfo(
54 buffer_id(), /*consumer_count=*/0, buffer_node_->buffer().width(),
55 buffer_node_->buffer().height(), buffer_node_->buffer().layer_count(),
56 buffer_node_->buffer().format(), buffer_node_->buffer().usage(),
57 /*pending_count=*/0, /*state=*/0, /*signaled_mask=*/0,
58 /*index=*/0);
59}
60
61void BufferChannel::HandleImpulse(Message& /*message*/) {
62 ATRACE_NAME("BufferChannel::HandleImpulse");
63}
64
65bool BufferChannel::HandleMessage(Message& message) {
66 ATRACE_NAME("BufferChannel::HandleMessage");
67 switch (message.GetOp()) {
68 case DetachedBufferRPC::Import::Opcode:
69 DispatchRemoteMethod<DetachedBufferRPC::Import>(
70 *this, &BufferChannel::OnImport, message);
71 return true;
72
73 case DetachedBufferRPC::Duplicate::Opcode:
74 DispatchRemoteMethod<DetachedBufferRPC::Duplicate>(
75 *this, &BufferChannel::OnDuplicate, message);
76 return true;
77
78 case DetachedBufferRPC::Promote::Opcode:
79 DispatchRemoteMethod<DetachedBufferRPC::Promote>(
80 *this, &BufferChannel::OnPromote, message);
81 return true;
82
83 default:
84 return false;
85 }
86}
87
88Status<BufferDescription<BorrowedHandle>> BufferChannel::OnImport(
89 Message& /*message*/) {
90 ATRACE_NAME("BufferChannel::OnImport");
91 ALOGD_IF(TRACE, "BufferChannel::OnImport: buffer=%d.",
92 buffer_id());
93
94 return BufferDescription<BorrowedHandle>{buffer_node_->buffer(),
95 buffer_node_->metadata_buffer(),
96 buffer_id(),
97 channel_id(),
98 buffer_state_bit_,
99 BorrowedHandle{},
100 BorrowedHandle{}};
101}
102
103Status<RemoteChannelHandle> BufferChannel::OnDuplicate(
104 Message& message) {
105 ATRACE_NAME("BufferChannel::OnDuplicate");
106 ALOGD_IF(TRACE, "BufferChannel::OnDuplicate: buffer=%d.",
107 buffer_id());
108
109 int channel_id;
110 auto status = message.PushChannel(0, nullptr, &channel_id);
111 if (!status) {
112 ALOGE(
113 "BufferChannel::OnDuplicate: Failed to push buffer channel: %s",
114 status.GetErrorMessage().c_str());
115 return ErrorStatus(ENOMEM);
116 }
117
118 // Try find the next buffer state bit which has not been claimed by any
119 // other buffers yet.
120 uint64_t buffer_state_bit =
121 BufferHubDefs::FindNextClearedBit(buffer_node_->active_buffer_bit_mask() |
122 BufferHubDefs::kProducerStateBit);
123 if (buffer_state_bit == 0ULL) {
124 ALOGE(
125 "BufferChannel::OnDuplicate: reached the maximum mumber of channels "
126 "per buffer node: 63.");
127 return ErrorStatus(E2BIG);
128 }
129
130 auto channel =
131 std::shared_ptr<BufferChannel>(new BufferChannel(
132 service(), buffer_id(), channel_id, buffer_node_, buffer_state_bit));
133 if (!channel) {
134 ALOGE("BufferChannel::OnDuplicate: Invalid buffer.");
135 return ErrorStatus(EINVAL);
136 }
137
138 const auto channel_status =
139 service()->SetChannel(channel_id, std::move(channel));
140 if (!channel_status) {
141 // Technically, this should never fail, as we just pushed the channel. Note
142 // that LOG_FATAL will be stripped out in non-debug build.
143 LOG_FATAL(
144 "BufferChannel::OnDuplicate: Failed to set new buffer channel: %s.",
145 channel_status.GetErrorMessage().c_str());
146 }
147
148 return status;
149}
150
151Status<RemoteChannelHandle> BufferChannel::OnPromote(
152 Message& message) {
153 ATRACE_NAME("BufferChannel::OnPromote");
154 ALOGD_IF(TRACE, "BufferChannel::OnPromote: buffer_id=%d", buffer_id());
155
156 // Check whether this is the channel exclusive owner of the buffer_node_.
157 if (buffer_state_bit_ != buffer_node_->active_buffer_bit_mask()) {
158 ALOGE(
159 "BufferChannel::OnPromote: Cannot promote this BufferChannel as its "
160 "BufferNode is shared between multiple channels. This channel's state "
161 "bit=0x%" PRIx64 ", acitve_buffer_bit_mask=0x%" PRIx64 ".",
162 buffer_state_bit_, buffer_node_->active_buffer_bit_mask());
163 return ErrorStatus(EINVAL);
164 }
165
166 // Note that the new ProducerChannel will have different channel_id, but
167 // inherits the buffer_id from the DetachedBuffer.
168 int channel_id;
169 auto status = message.PushChannel(0, nullptr, &channel_id);
170 if (!status) {
171 ALOGE(
172 "BufferChannel::OnPromote: Failed to push ProducerChannel: %s.",
173 status.GetErrorMessage().c_str());
174 return ErrorStatus(ENOMEM);
175 }
176
177 IonBuffer buffer = std::move(buffer_node_->buffer());
178 IonBuffer metadata_buffer = std::move(buffer_node_->metadata_buffer());
179 size_t user_metadata_size = buffer_node_->user_metadata_size();
180
181 std::unique_ptr<ProducerChannel> channel = ProducerChannel::Create(
182 service(), buffer_id(), channel_id, std::move(buffer),
183 std::move(metadata_buffer), user_metadata_size);
184 if (!channel) {
185 ALOGE(
186 "BufferChannel::OnPromote: Failed to create ProducerChannel from a "
187 "BufferChannel, buffer_id=%d.",
188 buffer_id());
189 }
190
191 const auto channel_status =
192 service()->SetChannel(channel_id, std::move(channel));
193 if (!channel_status) {
194 // Technically, this should never fail, as we just pushed the channel. Note
195 // that LOG_FATAL will be stripped out in non-debug build.
196 LOG_FATAL(
197 "BufferChannel::OnPromote: Failed to set new producer buffer channel: "
198 "%s.",
199 channel_status.GetErrorMessage().c_str());
200 }
201
202 return status;
203}
204
205} // namespace dvr
206} // namespace android