1#include <private/dvr/buffer_hub_client.h> 2 3#include <log/log.h> 4#include <poll.h> 5#define ATRACE_TAG ATRACE_TAG_GRAPHICS 6#include <utils/Trace.h> 7 8#include <mutex> 9 10#include <pdx/default_transport/client_channel.h> 11#include <pdx/default_transport/client_channel_factory.h> 12 13#include "include/private/dvr/bufferhub_rpc.h" 14 15using android::pdx::LocalHandle; 16using android::pdx::LocalChannelHandle; 17using android::pdx::rpc::WrapBuffer; 18using android::pdx::Status; 19 20namespace android { 21namespace dvr { 22 23BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle) 24 : Client{pdx::default_transport::ClientChannel::Create( 25 std::move(channel_handle))}, 26 id_(-1) {} 27BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path) 28 : Client{pdx::default_transport::ClientChannelFactory::Create( 29 endpoint_path)}, 30 id_(-1) {} 31 32BufferHubBuffer::~BufferHubBuffer() {} 33 34Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() { 35 Status<LocalChannelHandle> status = 36 InvokeRemoteMethod<BufferHubRPC::NewConsumer>(); 37 ALOGE_IF(!status, 38 "BufferHub::CreateConsumer: Failed to create consumer channel: %s", 39 status.GetErrorMessage().c_str()); 40 return status; 41} 42 43int BufferHubBuffer::ImportBuffer() { 44 ATRACE_NAME("BufferHubBuffer::ImportBuffer"); 45 46 Status<NativeBufferHandle<LocalHandle>> status = 47 InvokeRemoteMethod<BufferHubRPC::GetBuffer>(); 48 if (!status) { 49 ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s", 50 status.GetErrorMessage().c_str()); 51 return -status.error(); 52 } else if (status.get().id() < 0) { 53 ALOGE("BufferHubBuffer::ImportBuffer: Received an invalid id!"); 54 return -EIO; 55 } 56 57 auto buffer_handle = status.take(); 58 59 // Stash the buffer id to replace the value in id_. 60 const int new_id = buffer_handle.id(); 61 62 // Import the buffer. 63 IonBuffer ion_buffer; 64 ALOGD_IF( 65 TRACE, "BufferHubBuffer::ImportBuffer: id=%d FdCount=%zu IntCount=%zu", 66 buffer_handle.id(), buffer_handle.FdCount(), buffer_handle.IntCount()); 67 68 const int ret = buffer_handle.Import(&ion_buffer); 69 if (ret < 0) 70 return ret; 71 72 // If the import succeeds, replace the previous buffer and id. 73 buffer_ = std::move(ion_buffer); 74 id_ = new_id; 75 return 0; 76} 77 78int BufferHubBuffer::Poll(int timeout_ms) { 79 ATRACE_NAME("BufferHubBuffer::Poll"); 80 pollfd p = {event_fd(), POLLIN, 0}; 81 return poll(&p, 1, timeout_ms); 82} 83 84int BufferHubBuffer::Lock(int usage, int x, int y, int width, int height, 85 void** address) { 86 return buffer_.Lock(usage, x, y, width, height, address); 87} 88 89int BufferHubBuffer::Unlock() { return buffer_.Unlock(); } 90 91int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) { 92 int width = static_cast<int>(size); 93 int height = 1; 94 int ret = Lock(usage(), 0, 0, width, height, addr); 95 if (ret == 0) 96 Unlock(); 97 return ret; 98} 99 100int BufferHubBuffer::GetBlobReadOnlyPointer(size_t size, void** addr) { 101 return GetBlobReadWritePointer(size, addr); 102} 103 104void BufferHubBuffer::GetBlobFds(int* fds, size_t* fds_count, 105 size_t max_fds_count) const { 106 size_t numFds = static_cast<size_t>(native_handle()->numFds); 107 *fds_count = std::min(max_fds_count, numFds); 108 std::copy(native_handle()->data, native_handle()->data + *fds_count, fds); 109} 110 111BufferConsumer::BufferConsumer(LocalChannelHandle channel) 112 : BASE(std::move(channel)) { 113 const int ret = ImportBuffer(); 114 if (ret < 0) { 115 ALOGE("BufferConsumer::BufferConsumer: Failed to import buffer: %s", 116 strerror(-ret)); 117 Close(ret); 118 } 119} 120 121std::unique_ptr<BufferConsumer> BufferConsumer::Import( 122 LocalChannelHandle channel) { 123 ATRACE_NAME("BufferConsumer::Import"); 124 ALOGD_IF(TRACE, "BufferConsumer::Import: channel=%d", channel.value()); 125 return BufferConsumer::Create(std::move(channel)); 126} 127 128std::unique_ptr<BufferConsumer> BufferConsumer::Import( 129 Status<LocalChannelHandle> status) { 130 return Import(status ? status.take() 131 : LocalChannelHandle{nullptr, -status.error()}); 132} 133 134int BufferConsumer::Acquire(LocalHandle* ready_fence) { 135 return Acquire(ready_fence, nullptr, 0); 136} 137 138int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta, 139 size_t meta_size_bytes) { 140 ATRACE_NAME("BufferConsumer::Acquire"); 141 LocalFence fence; 142 auto return_value = 143 std::make_pair(std::ref(fence), WrapBuffer(meta, meta_size_bytes)); 144 auto status = InvokeRemoteMethodInPlace<BufferHubRPC::ConsumerAcquire>( 145 &return_value, meta_size_bytes); 146 if (status && ready_fence) 147 *ready_fence = fence.take(); 148 return status ? 0 : -status.error(); 149} 150 151int BufferConsumer::Release(const LocalHandle& release_fence) { 152 ATRACE_NAME("BufferConsumer::Release"); 153 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>( 154 BorrowedFence(release_fence.Borrow()))); 155} 156 157int BufferConsumer::ReleaseAsync() { 158 ATRACE_NAME("BufferConsumer::ReleaseAsync"); 159 return ReturnStatusOrError( 160 SendImpulse(BufferHubRPC::ConsumerRelease::Opcode)); 161} 162 163int BufferConsumer::Discard() { return Release(LocalHandle()); } 164 165int BufferConsumer::SetIgnore(bool ignore) { 166 return ReturnStatusOrError( 167 InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore)); 168} 169 170BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format, 171 uint32_t usage, size_t metadata_size) 172 : BufferProducer(width, height, format, usage, usage, metadata_size) {} 173 174BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format, 175 uint64_t producer_usage, uint64_t consumer_usage, 176 size_t metadata_size) 177 : BASE(BufferHubRPC::kClientPath) { 178 ATRACE_NAME("BufferProducer::BufferProducer"); 179 ALOGD_IF(TRACE, 180 "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u " 181 "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64 182 " metadata_size=%zu", 183 event_fd(), width, height, format, producer_usage, consumer_usage, 184 metadata_size); 185 186 // (b/37881101) Deprecate producer/consumer usage 187 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>( 188 width, height, format, (producer_usage | consumer_usage), metadata_size); 189 if (!status) { 190 ALOGE( 191 "BufferProducer::BufferProducer: Failed to create producer buffer: %s", 192 status.GetErrorMessage().c_str()); 193 Close(-status.error()); 194 return; 195 } 196 197 const int ret = ImportBuffer(); 198 if (ret < 0) { 199 ALOGE( 200 "BufferProducer::BufferProducer: Failed to import producer buffer: %s", 201 strerror(-ret)); 202 Close(ret); 203 } 204} 205 206BufferProducer::BufferProducer(const std::string& name, int user_id, 207 int group_id, uint32_t width, uint32_t height, 208 uint32_t format, uint32_t usage, 209 size_t meta_size_bytes) 210 : BufferProducer(name, user_id, group_id, width, height, format, usage, 211 usage, meta_size_bytes) {} 212 213BufferProducer::BufferProducer(const std::string& name, int user_id, 214 int group_id, uint32_t width, uint32_t height, 215 uint32_t format, uint64_t producer_usage, 216 uint64_t consumer_usage, size_t meta_size_bytes) 217 : BASE(BufferHubRPC::kClientPath) { 218 ATRACE_NAME("BufferProducer::BufferProducer"); 219 ALOGD_IF(TRACE, 220 "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d " 221 "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64 222 " consumer_usage=%" PRIx64 " meta_size_bytes=%zu", 223 event_fd(), name.c_str(), user_id, group_id, width, height, format, 224 producer_usage, consumer_usage, meta_size_bytes); 225 226 // (b/37881101) Deprecate producer/consumer usage 227 auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>( 228 name, user_id, group_id, width, height, format, 229 (producer_usage | consumer_usage), meta_size_bytes); 230 if (!status) { 231 ALOGE( 232 "BufferProducer::BufferProducer: Failed to create/get persistent " 233 "buffer \"%s\": %s", 234 name.c_str(), status.GetErrorMessage().c_str()); 235 Close(-status.error()); 236 return; 237 } 238 239 const int ret = ImportBuffer(); 240 if (ret < 0) { 241 ALOGE( 242 "BufferProducer::BufferProducer: Failed to import producer buffer " 243 "\"%s\": %s", 244 name.c_str(), strerror(-ret)); 245 Close(ret); 246 } 247} 248 249BufferProducer::BufferProducer(uint32_t usage, size_t size) 250 : BufferProducer(usage, usage, size) {} 251 252BufferProducer::BufferProducer(uint64_t producer_usage, uint64_t consumer_usage, 253 size_t size) 254 : BASE(BufferHubRPC::kClientPath) { 255 ATRACE_NAME("BufferProducer::BufferProducer"); 256 ALOGD_IF(TRACE, 257 "BufferProducer::BufferProducer: producer_usage=%" PRIx64 258 " consumer_usage=%" PRIx64 " size=%zu", 259 producer_usage, consumer_usage, size); 260 const int width = static_cast<int>(size); 261 const int height = 1; 262 const int format = HAL_PIXEL_FORMAT_BLOB; 263 const size_t meta_size_bytes = 0; 264 265 // (b/37881101) Deprecate producer/consumer usage 266 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>( 267 width, height, format, (producer_usage | consumer_usage), 268 meta_size_bytes); 269 if (!status) { 270 ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s", 271 status.GetErrorMessage().c_str()); 272 Close(-status.error()); 273 return; 274 } 275 276 const int ret = ImportBuffer(); 277 if (ret < 0) { 278 ALOGE( 279 "BufferProducer::BufferProducer: Failed to import producer buffer: %s", 280 strerror(-ret)); 281 Close(ret); 282 } 283} 284 285BufferProducer::BufferProducer(const std::string& name, int user_id, 286 int group_id, uint32_t usage, size_t size) 287 : BufferProducer(name, user_id, group_id, usage, usage, size) {} 288 289BufferProducer::BufferProducer(const std::string& name, int user_id, 290 int group_id, uint64_t producer_usage, 291 uint64_t consumer_usage, size_t size) 292 : BASE(BufferHubRPC::kClientPath) { 293 ATRACE_NAME("BufferProducer::BufferProducer"); 294 ALOGD_IF(TRACE, 295 "BufferProducer::BufferProducer: name=%s user_id=%d group=%d " 296 "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64 " size=%zu", 297 name.c_str(), user_id, group_id, producer_usage, consumer_usage, 298 size); 299 const int width = static_cast<int>(size); 300 const int height = 1; 301 const int format = HAL_PIXEL_FORMAT_BLOB; 302 const size_t meta_size_bytes = 0; 303 304 // (b/37881101) Deprecate producer/consumer usage 305 auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>( 306 name, user_id, group_id, width, height, format, 307 (producer_usage | consumer_usage), meta_size_bytes); 308 if (!status) { 309 ALOGE( 310 "BufferProducer::BufferProducer: Failed to create persistent " 311 "buffer \"%s\": %s", 312 name.c_str(), status.GetErrorMessage().c_str()); 313 Close(-status.error()); 314 return; 315 } 316 317 const int ret = ImportBuffer(); 318 if (ret < 0) { 319 ALOGE( 320 "BufferProducer::BufferProducer: Failed to import producer buffer " 321 "\"%s\": %s", 322 name.c_str(), strerror(-ret)); 323 Close(ret); 324 } 325} 326 327BufferProducer::BufferProducer(const std::string& name) 328 : BASE(BufferHubRPC::kClientPath) { 329 ATRACE_NAME("BufferProducer::BufferProducer"); 330 ALOGD_IF(TRACE, "BufferProducer::BufferProducer: name=%s", name.c_str()); 331 332 auto status = InvokeRemoteMethod<BufferHubRPC::GetPersistentBuffer>(name); 333 if (!status) { 334 ALOGE( 335 "BufferProducer::BufferProducer: Failed to get producer buffer by name " 336 "\"%s\": %s", 337 name.c_str(), status.GetErrorMessage().c_str()); 338 Close(-status.error()); 339 return; 340 } 341 342 const int ret = ImportBuffer(); 343 if (ret < 0) { 344 ALOGE( 345 "BufferProducer::BufferProducer: Failed to import producer buffer " 346 "\"%s\": %s", 347 name.c_str(), strerror(-ret)); 348 Close(ret); 349 } 350} 351 352BufferProducer::BufferProducer(LocalChannelHandle channel) 353 : BASE(std::move(channel)) { 354 const int ret = ImportBuffer(); 355 if (ret < 0) { 356 ALOGE( 357 "BufferProducer::BufferProducer: Failed to import producer buffer: %s", 358 strerror(-ret)); 359 Close(ret); 360 } 361} 362 363int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta, 364 size_t meta_size_bytes) { 365 ATRACE_NAME("BufferProducer::Post"); 366 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>( 367 BorrowedFence(ready_fence.Borrow()), WrapBuffer(meta, meta_size_bytes))); 368} 369 370int BufferProducer::Gain(LocalHandle* release_fence) { 371 ATRACE_NAME("BufferProducer::Gain"); 372 auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>(); 373 if (!status) 374 return -status.error(); 375 if (release_fence) 376 *release_fence = status.take().take(); 377 return 0; 378} 379 380int BufferProducer::GainAsync() { 381 ATRACE_NAME("BufferProducer::GainAsync"); 382 return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode)); 383} 384 385std::unique_ptr<BufferProducer> BufferProducer::Import( 386 LocalChannelHandle channel) { 387 ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value()); 388 return BufferProducer::Create(std::move(channel)); 389} 390 391std::unique_ptr<BufferProducer> BufferProducer::Import( 392 Status<LocalChannelHandle> status) { 393 return Import(status ? status.take() 394 : LocalChannelHandle{nullptr, -status.error()}); 395} 396 397int BufferProducer::MakePersistent(const std::string& name, int user_id, 398 int group_id) { 399 ATRACE_NAME("BufferProducer::MakePersistent"); 400 return ReturnStatusOrError( 401 InvokeRemoteMethod<BufferHubRPC::ProducerMakePersistent>(name, user_id, 402 group_id)); 403} 404 405int BufferProducer::RemovePersistence() { 406 ATRACE_NAME("BufferProducer::RemovePersistence"); 407 return ReturnStatusOrError( 408 InvokeRemoteMethod<BufferHubRPC::ProducerRemovePersistence>()); 409} 410 411} // namespace dvr 412} // namespace android 413