blob: 795ad19f6a88d0c201997364812de2a1d1137728 [file] [log] [blame]
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -07001#include <pdx/default_transport/client_channel.h>
2#include <pdx/default_transport/client_channel_factory.h>
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -07003#include <pdx/file_handle.h>
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -07004#include <private/dvr/bufferhub_rpc.h>
5#include <private/dvr/detached_buffer.h>
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -07006#include <ui/DetachedBufferHandle.h>
7
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -07008#include <poll.h>
9
10using android::pdx::LocalChannelHandle;
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070011using android::pdx::LocalHandle;
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -070012using android::pdx::Status;
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -070013using android::pdx::default_transport::ClientChannel;
14using android::pdx::default_transport::ClientChannelFactory;
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070015
16namespace android {
17namespace dvr {
18
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -070019namespace {
20
21// TODO(b/112338294): Remove this string literal after refactoring BufferHub
22// to use Binder.
23static constexpr char kBufferHubClientPath[] = "system/buffer_hub/client";
24
25} // namespace
26
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -070027BufferHubClient::BufferHubClient()
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -070028 : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {}
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -070029
30BufferHubClient::BufferHubClient(LocalChannelHandle channel_handle)
31 : Client(ClientChannel::Create(std::move(channel_handle))) {}
32
33bool BufferHubClient::IsValid() const {
34 return IsConnected() && GetChannelHandle().valid();
35}
36
37LocalChannelHandle BufferHubClient::TakeChannelHandle() {
38 if (IsConnected()) {
39 return std::move(GetChannelHandle());
40 } else {
41 return {};
42 }
43}
44
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070045DetachedBuffer::DetachedBuffer(uint32_t width, uint32_t height,
46 uint32_t layer_count, uint32_t format,
47 uint64_t usage, size_t user_metadata_size) {
48 ATRACE_NAME("DetachedBuffer::DetachedBuffer");
49 ALOGD_IF(TRACE,
50 "DetachedBuffer::DetachedBuffer: width=%u height=%u layer_count=%u, "
51 "format=%u usage=%" PRIx64 " user_metadata_size=%zu",
52 width, height, layer_count, format, usage, user_metadata_size);
53
54 auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Create>(
55 width, height, layer_count, format, usage, user_metadata_size);
56 if (!status) {
57 ALOGE(
58 "DetachedBuffer::DetachedBuffer: Failed to create detached buffer: %s",
59 status.GetErrorMessage().c_str());
60 client_.Close(-status.error());
61 }
62
63 const int ret = ImportGraphicBuffer();
64 if (ret < 0) {
65 ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s",
66 strerror(-ret));
67 client_.Close(ret);
68 }
69}
70
71DetachedBuffer::DetachedBuffer(LocalChannelHandle channel_handle)
72 : client_(std::move(channel_handle)) {
73 const int ret = ImportGraphicBuffer();
74 if (ret < 0) {
75 ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s",
76 strerror(-ret));
77 client_.Close(ret);
78 }
79}
80
81int DetachedBuffer::ImportGraphicBuffer() {
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -070082 ATRACE_NAME("DetachedBuffer::ImportGraphicBuffer");
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070083
84 auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Import>();
85 if (!status) {
86 ALOGE("DetachedBuffer::DetachedBuffer: Failed to import GraphicBuffer: %s",
87 status.GetErrorMessage().c_str());
88 return -status.error();
89 }
90
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -070091 BufferTraits<LocalHandle> buffer_traits = status.take();
92 if (buffer_traits.id() < 0) {
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070093 ALOGE("DetachedBuffer::DetachedBuffer: Received an invalid id!");
94 return -EIO;
95 }
96
97 // Stash the buffer id to replace the value in id_.
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -070098 const int buffer_id = buffer_traits.id();
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070099
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -0700100 // Import the metadata.
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -0700101 metadata_ = BufferHubMetadata::Import(buffer_traits.take_metadata_handle());
102
103 if (!metadata_.IsValid()) {
104 ALOGE("DetachedBuffer::ImportGraphicBuffer: invalid metadata.");
105 return -ENOMEM;
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -0700106 }
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -0700107
108 if (metadata_.metadata_size() != buffer_traits.metadata_size()) {
109 ALOGE(
110 "DetachedBuffer::ImportGraphicBuffer: metadata buffer too small: "
111 "%zu, expected: %" PRIu64 ".",
112 metadata_.metadata_size(), buffer_traits.metadata_size());
113 return -ENOMEM;
114 }
115
116 size_t metadata_buf_size = buffer_traits.metadata_size();
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -0700117 if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -0700118 ALOGE("DetachedBuffer::ImportGraphicBuffer: metadata too small: %zu",
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -0700119 metadata_buf_size);
120 return -EINVAL;
121 }
122
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -0700123 // Import the buffer: We only need to hold on the native_handle_t here so that
124 // GraphicBuffer instance can be created in future.
125 buffer_handle_ = buffer_traits.take_buffer_handle();
126
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700127 // If all imports succeed, replace the previous buffer and id.
128 id_ = buffer_id;
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -0700129 buffer_state_bit_ = buffer_traits.buffer_state_bit();
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -0700130
131 // TODO(b/112012161) Set up shared fences.
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -0700132 ALOGD_IF(TRACE,
133 "DetachedBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64
134 ".",
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -0700135 id(),
136 metadata_.metadata_header()->buffer_state.load(
137 std::memory_order_acquire));
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700138 return 0;
139}
140
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700141int DetachedBuffer::Poll(int timeout_ms) {
142 ATRACE_NAME("DetachedBuffer::Poll");
143 pollfd p = {client_.event_fd(), POLLIN, 0};
144 return poll(&p, 1, timeout_ms);
145}
146
147Status<LocalChannelHandle> DetachedBuffer::Promote() {
Fan Xuddb90db2018-10-03 10:09:14 -0700148 // TODO(b/112338294) remove after migrate producer buffer to binder
149 ALOGW("DetachedBuffer::Promote: not supported operation during migration");
150 return {};
151
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700152 ATRACE_NAME("DetachedBuffer::Promote");
153 ALOGD_IF(TRACE, "DetachedBuffer::Promote: id=%d.", id_);
154
155 auto status_or_handle =
156 client_.InvokeRemoteMethod<DetachedBufferRPC::Promote>();
157 if (status_or_handle.ok()) {
158 // Invalidate the buffer.
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -0700159 buffer_handle_ = {};
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700160 } else {
161 ALOGE("DetachedBuffer::Promote: Failed to promote buffer (id=%d): %s.", id_,
162 status_or_handle.GetErrorMessage().c_str());
163 }
164 return status_or_handle;
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700165}
166
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -0700167Status<LocalChannelHandle> DetachedBuffer::Duplicate() {
168 ATRACE_NAME("DetachedBuffer::Duplicate");
169 ALOGD_IF(TRACE, "DetachedBuffer::Duplicate: id=%d.", id_);
170
171 auto status_or_handle =
172 client_.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>();
173
174 if (!status_or_handle.ok()) {
175 ALOGE("DetachedBuffer::Duplicate: Failed to duplicate buffer (id=%d): %s.",
176 id_, status_or_handle.GetErrorMessage().c_str());
177 }
178 return status_or_handle;
179}
180
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700181} // namespace dvr
182} // namespace android