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