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