blob: 420ce24a3199a4d71a64dac9f218568f1cd7a12e [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' Cai088b3b62018-10-03 18:49:07 -070019BufferHubClient::BufferHubClient()
20 : Client(ClientChannelFactory::Create(BufferHubRPC::kClientPath)) {}
21
22BufferHubClient::BufferHubClient(LocalChannelHandle channel_handle)
23 : Client(ClientChannel::Create(std::move(channel_handle))) {}
24
25bool BufferHubClient::IsValid() const {
26 return IsConnected() && GetChannelHandle().valid();
27}
28
29LocalChannelHandle BufferHubClient::TakeChannelHandle() {
30 if (IsConnected()) {
31 return std::move(GetChannelHandle());
32 } else {
33 return {};
34 }
35}
36
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070037DetachedBuffer::DetachedBuffer(uint32_t width, uint32_t height,
38 uint32_t layer_count, uint32_t format,
39 uint64_t usage, size_t user_metadata_size) {
40 ATRACE_NAME("DetachedBuffer::DetachedBuffer");
41 ALOGD_IF(TRACE,
42 "DetachedBuffer::DetachedBuffer: width=%u height=%u layer_count=%u, "
43 "format=%u usage=%" PRIx64 " user_metadata_size=%zu",
44 width, height, layer_count, format, usage, user_metadata_size);
45
46 auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Create>(
47 width, height, layer_count, format, usage, user_metadata_size);
48 if (!status) {
49 ALOGE(
50 "DetachedBuffer::DetachedBuffer: Failed to create detached buffer: %s",
51 status.GetErrorMessage().c_str());
52 client_.Close(-status.error());
53 }
54
55 const int ret = ImportGraphicBuffer();
56 if (ret < 0) {
57 ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s",
58 strerror(-ret));
59 client_.Close(ret);
60 }
61}
62
63DetachedBuffer::DetachedBuffer(LocalChannelHandle channel_handle)
64 : client_(std::move(channel_handle)) {
65 const int ret = ImportGraphicBuffer();
66 if (ret < 0) {
67 ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s",
68 strerror(-ret));
69 client_.Close(ret);
70 }
71}
72
73int DetachedBuffer::ImportGraphicBuffer() {
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -070074 ATRACE_NAME("DetachedBuffer::ImportGraphicBuffer");
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070075
76 auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Import>();
77 if (!status) {
78 ALOGE("DetachedBuffer::DetachedBuffer: Failed to import GraphicBuffer: %s",
79 status.GetErrorMessage().c_str());
80 return -status.error();
81 }
82
83 BufferDescription<LocalHandle> buffer_desc = status.take();
84 if (buffer_desc.id() < 0) {
85 ALOGE("DetachedBuffer::DetachedBuffer: Received an invalid id!");
86 return -EIO;
87 }
88
89 // Stash the buffer id to replace the value in id_.
90 const int buffer_id = buffer_desc.id();
91
92 // Import the buffer.
93 IonBuffer ion_buffer;
94 ALOGD_IF(TRACE, "DetachedBuffer::DetachedBuffer: id=%d.", buffer_id);
95
96 if (const int ret = buffer_desc.ImportBuffer(&ion_buffer)) {
97 ALOGE("Failed to import GraphicBuffer, error=%d", ret);
98 return ret;
99 }
100
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -0700101 // Import the metadata.
102 IonBuffer metadata_buffer;
103 if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
104 ALOGE("Failed to import metadata buffer, error=%d", ret);
105 return ret;
106 }
107 size_t metadata_buf_size = metadata_buffer.width();
108 if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
109 ALOGE("DetachedBuffer::ImportGraphicBuffer: metadata buffer too small: %zu",
110 metadata_buf_size);
111 return -EINVAL;
112 }
113
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700114 // If all imports succeed, replace the previous buffer and id.
115 id_ = buffer_id;
116 buffer_ = std::move(ion_buffer);
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -0700117 metadata_buffer_ = std::move(metadata_buffer);
118 user_metadata_size_ = metadata_buf_size - BufferHubDefs::kMetadataHeaderSize;
119
120 void* metadata_ptr = nullptr;
121 if (const int ret =
122 metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
123 /*y=*/0, metadata_buf_size,
124 /*height=*/1, &metadata_ptr)) {
125 ALOGE("DetachedBuffer::ImportGraphicBuffer: Failed to lock metadata.");
126 return ret;
127 }
128
129 // TODO(b/112012161) Set up shared fences.
130
131 // Note that here the buffer state is mapped from shared memory as an atomic
132 // object. The std::atomic's constructor will not be called so that the
133 // original value stored in the memory region can be preserved.
134 metadata_header_ = static_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
135 if (user_metadata_size_) {
136 user_metadata_ptr_ = static_cast<void*>(metadata_header_ + 1);
137 } else {
138 user_metadata_ptr_ = nullptr;
139 }
140
141 id_ = buffer_desc.id();
142 buffer_state_bit_ = buffer_desc.buffer_state_bit();
143
144 ALOGD_IF(TRACE,
145 "DetachedBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64
146 ".",
147 id(), metadata_header_->buffer_state.load());
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700148 return 0;
149}
150
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700151int DetachedBuffer::Poll(int timeout_ms) {
152 ATRACE_NAME("DetachedBuffer::Poll");
153 pollfd p = {client_.event_fd(), POLLIN, 0};
154 return poll(&p, 1, timeout_ms);
155}
156
157Status<LocalChannelHandle> DetachedBuffer::Promote() {
Fan Xuddb90db2018-10-03 10:09:14 -0700158 // TODO(b/112338294) remove after migrate producer buffer to binder
159 ALOGW("DetachedBuffer::Promote: not supported operation during migration");
160 return {};
161
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700162 ATRACE_NAME("DetachedBuffer::Promote");
163 ALOGD_IF(TRACE, "DetachedBuffer::Promote: id=%d.", id_);
164
165 auto status_or_handle =
166 client_.InvokeRemoteMethod<DetachedBufferRPC::Promote>();
167 if (status_or_handle.ok()) {
168 // Invalidate the buffer.
169 buffer_ = {};
170 } else {
171 ALOGE("DetachedBuffer::Promote: Failed to promote buffer (id=%d): %s.", id_,
172 status_or_handle.GetErrorMessage().c_str());
173 }
174 return status_or_handle;
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700175}
176
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -0700177Status<LocalChannelHandle> DetachedBuffer::Duplicate() {
178 ATRACE_NAME("DetachedBuffer::Duplicate");
179 ALOGD_IF(TRACE, "DetachedBuffer::Duplicate: id=%d.", id_);
180
181 auto status_or_handle =
182 client_.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>();
183
184 if (!status_or_handle.ok()) {
185 ALOGE("DetachedBuffer::Duplicate: Failed to duplicate buffer (id=%d): %s.",
186 id_, status_or_handle.GetErrorMessage().c_str());
187 }
188 return status_or_handle;
189}
190
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700191} // namespace dvr
192} // namespace android