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