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