blob: 606386c7405c53f5ffc315c0201c5c618b2c63dc [file] [log] [blame]
Jiwen 'Steve' Cai8f51ec62018-08-07 21:50:51 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// We would eliminate the clang warnings introduced by libdpx.
18// TODO(b/112338294): Remove those once BufferHub moved to use Binder
19#pragma clang diagnostic push
20#pragma clang diagnostic ignored "-Wconversion"
21#pragma clang diagnostic ignored "-Wdouble-promotion"
22#pragma clang diagnostic ignored "-Wgnu-case-range"
23#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
24#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
25#pragma clang diagnostic ignored "-Wnested-anon-types"
26#pragma clang diagnostic ignored "-Wpacked"
27#pragma clang diagnostic ignored "-Wshadow"
28#pragma clang diagnostic ignored "-Wsign-conversion"
29#pragma clang diagnostic ignored "-Wswitch-enum"
30#pragma clang diagnostic ignored "-Wundefined-func-template"
31#pragma clang diagnostic ignored "-Wunused-template"
32#pragma clang diagnostic ignored "-Wweak-vtables"
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -070033#include <pdx/default_transport/client_channel.h>
34#include <pdx/default_transport/client_channel_factory.h>
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070035#include <pdx/file_handle.h>
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -070036#include <private/dvr/bufferhub_rpc.h>
Jiwen 'Steve' Cai8f51ec62018-08-07 21:50:51 -070037#pragma clang diagnostic pop
38
39#include <ui/BufferHubBuffer.h>
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070040#include <ui/DetachedBufferHandle.h>
41
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -070042#include <poll.h>
43
Jiwen 'Steve' Cai8f51ec62018-08-07 21:50:51 -070044using android::dvr::BufferHubMetadata;
45using android::dvr::BufferTraits;
46using android::dvr::DetachedBufferRPC;
47using android::dvr::NativeHandleWrapper;
Jiwen 'Steve' Caiff675b72018-10-09 18:08:29 -070048
49// TODO(b/112338294): Remove PDX dependencies from libui.
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -070050using android::pdx::LocalChannelHandle;
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070051using android::pdx::LocalHandle;
Jiwen 'Steve' Cai0728fa92018-04-24 19:03:14 -070052using android::pdx::Status;
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -070053using android::pdx::default_transport::ClientChannel;
54using android::pdx::default_transport::ClientChannelFactory;
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070055
56namespace android {
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -070057
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -070058namespace {
59
60// TODO(b/112338294): Remove this string literal after refactoring BufferHub
61// to use Binder.
62static constexpr char kBufferHubClientPath[] = "system/buffer_hub/client";
63
Jiwen 'Steve' Caiff675b72018-10-09 18:08:29 -070064} // namespace
Jiwen 'Steve' Cai9004b8c2018-10-03 18:52:23 -070065
Jiwen 'Steve' Caiff675b72018-10-09 18:08:29 -070066BufferHubClient::BufferHubClient() : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {}
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -070067
Jiwen 'Steve' Caiff675b72018-10-09 18:08:29 -070068BufferHubClient::BufferHubClient(LocalChannelHandle mChannelHandle)
69 : Client(ClientChannel::Create(std::move(mChannelHandle))) {}
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -070070
Jiwen 'Steve' Cai8f51ec62018-08-07 21:50:51 -070071BufferHubClient::~BufferHubClient() {}
72
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -070073bool BufferHubClient::IsValid() const {
74 return IsConnected() && GetChannelHandle().valid();
75}
76
77LocalChannelHandle BufferHubClient::TakeChannelHandle() {
Jiwen 'Steve' Caiff675b72018-10-09 18:08:29 -070078 if (IsConnected()) {
79 return std::move(GetChannelHandle());
80 } else {
81 return {};
82 }
83}
84
85BufferHubBuffer::BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
86 uint32_t format, uint64_t usage, size_t mUserMetadataSize) {
87 ATRACE_CALL();
88 ALOGD("BufferHubBuffer::BufferHubBuffer: width=%u height=%u layerCount=%u, format=%u "
89 "usage=%" PRIx64 " mUserMetadataSize=%zu",
90 width, height, layerCount, format, usage, mUserMetadataSize);
91
92 auto status =
93 mClient.InvokeRemoteMethod<DetachedBufferRPC::Create>(width, height, layerCount, format,
94 usage, mUserMetadataSize);
95 if (!status) {
96 ALOGE("BufferHubBuffer::BufferHubBuffer: Failed to create detached buffer: %s",
97 status.GetErrorMessage().c_str());
98 mClient.Close(-status.error());
99 }
100
101 const int ret = ImportGraphicBuffer();
102 if (ret < 0) {
103 ALOGE("BufferHubBuffer::BufferHubBuffer: Failed to import buffer: %s", strerror(-ret));
104 mClient.Close(ret);
105 }
106}
107
108BufferHubBuffer::BufferHubBuffer(LocalChannelHandle mChannelHandle)
109 : mClient(std::move(mChannelHandle)) {
110 const int ret = ImportGraphicBuffer();
111 if (ret < 0) {
112 ALOGE("BufferHubBuffer::BufferHubBuffer: Failed to import buffer: %s", strerror(-ret));
113 mClient.Close(ret);
114 }
115}
116
117int BufferHubBuffer::ImportGraphicBuffer() {
118 ATRACE_CALL();
119
120 auto status = mClient.InvokeRemoteMethod<DetachedBufferRPC::Import>();
121 if (!status) {
122 ALOGE("BufferHubBuffer::BufferHubBuffer: Failed to import GraphicBuffer: %s",
123 status.GetErrorMessage().c_str());
124 return -status.error();
125 }
126
127 BufferTraits<LocalHandle> bufferTraits = status.take();
128 if (bufferTraits.id() < 0) {
129 ALOGE("BufferHubBuffer::BufferHubBuffer: Received an invalid id!");
130 return -EIO;
131 }
132
133 // Stash the buffer id to replace the value in mId.
134 const int bufferId = bufferTraits.id();
135
136 // Import the metadata.
137 mMetadata = BufferHubMetadata::Import(bufferTraits.take_metadata_handle());
138
139 if (!mMetadata.IsValid()) {
140 ALOGE("BufferHubBuffer::ImportGraphicBuffer: invalid metadata.");
141 return -ENOMEM;
142 }
143
144 if (mMetadata.metadata_size() != bufferTraits.metadata_size()) {
145 ALOGE("BufferHubBuffer::ImportGraphicBuffer: metadata buffer too small: "
146 "%zu, expected: %" PRIu64 ".",
147 mMetadata.metadata_size(), bufferTraits.metadata_size());
148 return -ENOMEM;
149 }
150
151 size_t metadataSize = static_cast<size_t>(bufferTraits.metadata_size());
152 if (metadataSize < dvr::BufferHubDefs::kMetadataHeaderSize) {
153 ALOGE("BufferHubBuffer::ImportGraphicBuffer: metadata too small: %zu", metadataSize);
154 return -EINVAL;
155 }
156
157 // Import the buffer: We only need to hold on the native_handle_t here so that
158 // GraphicBuffer instance can be created in future.
159 mBufferHandle = bufferTraits.take_buffer_handle();
160
161 // If all imports succeed, replace the previous buffer and id.
162 mId = bufferId;
163 mBfferStateBit = bufferTraits.buffer_state_bit();
164
165 // TODO(b/112012161) Set up shared fences.
166 ALOGD("BufferHubBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64 ".", id(),
167 mMetadata.metadata_header()->buffer_state.load(std::memory_order_acquire));
168 return 0;
169}
170
171int BufferHubBuffer::Poll(int timeoutMs) {
172 ATRACE_CALL();
173
174 pollfd p = {mClient.event_fd(), POLLIN, 0};
175 return poll(&p, 1, timeoutMs);
176}
177
178Status<LocalChannelHandle> BufferHubBuffer::Promote() {
179 ATRACE_CALL();
180
181 // TODO(b/112338294) remove after migrate producer buffer to binder
182 ALOGW("BufferHubBuffer::Promote: not supported operation during migration");
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -0700183 return {};
Jiwen 'Steve' Caiff675b72018-10-09 18:08:29 -0700184
185 ALOGD("BufferHubBuffer::Promote: id=%d.", mId);
186
187 auto statusOrHandle = mClient.InvokeRemoteMethod<DetachedBufferRPC::Promote>();
188 if (statusOrHandle.ok()) {
189 // Invalidate the buffer.
190 mBufferHandle = {};
191 } else {
192 ALOGE("BufferHubBuffer::Promote: Failed to promote buffer (id=%d): %s.", mId,
193 statusOrHandle.GetErrorMessage().c_str());
194 }
195 return statusOrHandle;
Jiwen 'Steve' Cai088b3b62018-10-03 18:49:07 -0700196}
197
Jiwen 'Steve' Caiff675b72018-10-09 18:08:29 -0700198Status<LocalChannelHandle> BufferHubBuffer::Duplicate() {
199 ATRACE_CALL();
200 ALOGD("BufferHubBuffer::Duplicate: id=%d.", mId);
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700201
Jiwen 'Steve' Caiff675b72018-10-09 18:08:29 -0700202 auto statusOrHandle = mClient.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>();
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700203
Jiwen 'Steve' Caiff675b72018-10-09 18:08:29 -0700204 if (!statusOrHandle.ok()) {
205 ALOGE("BufferHubBuffer::Duplicate: Failed to duplicate buffer (id=%d): %s.", mId,
206 statusOrHandle.GetErrorMessage().c_str());
207 }
208 return statusOrHandle;
Jiwen 'Steve' Caia8049a22018-03-28 15:14:02 -0700209}
210
Jiwen 'Steve' Caiff675b72018-10-09 18:08:29 -0700211} // namespace android