1#include "detached_buffer_channel.h" 2#include "producer_channel.h" 3 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 14DetachedBufferChannel::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 25DetachedBufferChannel::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 66DetachedBufferChannel::~DetachedBufferChannel() { 67 ALOGD_IF(TRACE, 68 "DetachedBufferChannel::~DetachedBufferChannel: channel_id=%d " 69 "buffer_id=%d.", 70 channel_id(), buffer_id()); 71 Hangup(); 72} 73 74BufferHubChannel::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 81void DetachedBufferChannel::HandleImpulse(Message& /*message*/) { 82 ATRACE_NAME("DetachedBufferChannel::HandleImpulse"); 83} 84 85bool 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 103Status<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 117Status<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