blob: 8a8c4ce706cbc208ead75336f1d20643d124a9ac [file] [log] [blame]
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -07001#include <private/dvr/detached_buffer.h>
2
3#include <pdx/file_handle.h>
4#include <ui/DetachedBufferHandle.h>
5
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -07006#include <poll.h>
7
8using android::pdx::LocalChannelHandle;
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -07009using android::pdx::LocalHandle;
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -070010using android::pdx::Status;
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070011
12namespace android {
13namespace dvr {
14
15DetachedBuffer::DetachedBuffer(uint32_t width, uint32_t height,
16 uint32_t layer_count, uint32_t format,
17 uint64_t usage, size_t user_metadata_size) {
18 ATRACE_NAME("DetachedBuffer::DetachedBuffer");
19 ALOGD_IF(TRACE,
20 "DetachedBuffer::DetachedBuffer: width=%u height=%u layer_count=%u, "
21 "format=%u usage=%" PRIx64 " user_metadata_size=%zu",
22 width, height, layer_count, format, usage, user_metadata_size);
23
24 auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Create>(
25 width, height, layer_count, format, usage, user_metadata_size);
26 if (!status) {
27 ALOGE(
28 "DetachedBuffer::DetachedBuffer: Failed to create detached buffer: %s",
29 status.GetErrorMessage().c_str());
30 client_.Close(-status.error());
31 }
32
33 const int ret = ImportGraphicBuffer();
34 if (ret < 0) {
35 ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s",
36 strerror(-ret));
37 client_.Close(ret);
38 }
39}
40
41DetachedBuffer::DetachedBuffer(LocalChannelHandle channel_handle)
42 : client_(std::move(channel_handle)) {
43 const int ret = ImportGraphicBuffer();
44 if (ret < 0) {
45 ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s",
46 strerror(-ret));
47 client_.Close(ret);
48 }
49}
50
51int DetachedBuffer::ImportGraphicBuffer() {
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -070052 ATRACE_NAME("DetachedBuffer::ImportGraphicBuffer");
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070053
54 auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Import>();
55 if (!status) {
56 ALOGE("DetachedBuffer::DetachedBuffer: Failed to import GraphicBuffer: %s",
57 status.GetErrorMessage().c_str());
58 return -status.error();
59 }
60
61 BufferDescription<LocalHandle> buffer_desc = status.take();
62 if (buffer_desc.id() < 0) {
63 ALOGE("DetachedBuffer::DetachedBuffer: Received an invalid id!");
64 return -EIO;
65 }
66
67 // Stash the buffer id to replace the value in id_.
68 const int buffer_id = buffer_desc.id();
69
70 // Import the buffer.
71 IonBuffer ion_buffer;
72 ALOGD_IF(TRACE, "DetachedBuffer::DetachedBuffer: id=%d.", buffer_id);
73
74 if (const int ret = buffer_desc.ImportBuffer(&ion_buffer)) {
75 ALOGE("Failed to import GraphicBuffer, error=%d", ret);
76 return ret;
77 }
78
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -070079 // Import the metadata.
80 IonBuffer metadata_buffer;
81 if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
82 ALOGE("Failed to import metadata buffer, error=%d", ret);
83 return ret;
84 }
85 size_t metadata_buf_size = metadata_buffer.width();
86 if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
87 ALOGE("DetachedBuffer::ImportGraphicBuffer: metadata buffer too small: %zu",
88 metadata_buf_size);
89 return -EINVAL;
90 }
91
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070092 // If all imports succeed, replace the previous buffer and id.
93 id_ = buffer_id;
94 buffer_ = std::move(ion_buffer);
Jiwen 'Steve' Caif326fce2018-08-06 17:36:50 -070095 metadata_buffer_ = std::move(metadata_buffer);
96 user_metadata_size_ = metadata_buf_size - BufferHubDefs::kMetadataHeaderSize;
97
98 void* metadata_ptr = nullptr;
99 if (const int ret =
100 metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
101 /*y=*/0, metadata_buf_size,
102 /*height=*/1, &metadata_ptr)) {
103 ALOGE("DetachedBuffer::ImportGraphicBuffer: Failed to lock metadata.");
104 return ret;
105 }
106
107 // TODO(b/112012161) Set up shared fences.
108
109 // Note that here the buffer state is mapped from shared memory as an atomic
110 // object. The std::atomic's constructor will not be called so that the
111 // original value stored in the memory region can be preserved.
112 metadata_header_ = static_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
113 if (user_metadata_size_) {
114 user_metadata_ptr_ = static_cast<void*>(metadata_header_ + 1);
115 } else {
116 user_metadata_ptr_ = nullptr;
117 }
118
119 id_ = buffer_desc.id();
120 buffer_state_bit_ = buffer_desc.buffer_state_bit();
121
122 ALOGD_IF(TRACE,
123 "DetachedBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64
124 ".",
125 id(), metadata_header_->buffer_state.load());
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700126 return 0;
127}
128
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700129int DetachedBuffer::Poll(int timeout_ms) {
130 ATRACE_NAME("DetachedBuffer::Poll");
131 pollfd p = {client_.event_fd(), POLLIN, 0};
132 return poll(&p, 1, timeout_ms);
133}
134
135Status<LocalChannelHandle> DetachedBuffer::Promote() {
Fan Xuddb90db2018-10-03 10:09:14 -0700136 // TODO(b/112338294) remove after migrate producer buffer to binder
137 ALOGW("DetachedBuffer::Promote: not supported operation during migration");
138 return {};
139
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -0700140 ATRACE_NAME("DetachedBuffer::Promote");
141 ALOGD_IF(TRACE, "DetachedBuffer::Promote: id=%d.", id_);
142
143 auto status_or_handle =
144 client_.InvokeRemoteMethod<DetachedBufferRPC::Promote>();
145 if (status_or_handle.ok()) {
146 // Invalidate the buffer.
147 buffer_ = {};
148 } else {
149 ALOGE("DetachedBuffer::Promote: Failed to promote buffer (id=%d): %s.", id_,
150 status_or_handle.GetErrorMessage().c_str());
151 }
152 return status_or_handle;
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700153}
154
Jiwen 'Steve' Cai2e06c1c2018-07-30 21:35:32 -0700155Status<LocalChannelHandle> DetachedBuffer::Duplicate() {
156 ATRACE_NAME("DetachedBuffer::Duplicate");
157 ALOGD_IF(TRACE, "DetachedBuffer::Duplicate: id=%d.", id_);
158
159 auto status_or_handle =
160 client_.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>();
161
162 if (!status_or_handle.ok()) {
163 ALOGE("DetachedBuffer::Duplicate: Failed to duplicate buffer (id=%d): %s.",
164 id_, status_or_handle.GetErrorMessage().c_str());
165 }
166 return status_or_handle;
167}
168
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700169} // namespace dvr
170} // namespace android