buffer_hub_client.cpp revision 8a71b13127f737a46c55ba94d31ba0262e7cbf8a
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 133BufferConsumer::BufferConsumer(LocalChannelHandle channel) 134 : BASE(std::move(channel)) { 135 const int ret = ImportBuffer(); 136 if (ret < 0) { 137 ALOGE("BufferConsumer::BufferConsumer: Failed to import buffer: %s", 138 strerror(-ret)); 139 Close(ret); 140 } 141} 142 143std::unique_ptr<BufferConsumer> BufferConsumer::Import( 144 LocalChannelHandle channel) { 145 ATRACE_NAME("BufferConsumer::Import"); 146 ALOGD_IF(TRACE, "BufferConsumer::Import: channel=%d", channel.value()); 147 return BufferConsumer::Create(std::move(channel)); 148} 149 150std::unique_ptr<BufferConsumer> BufferConsumer::Import( 151 Status<LocalChannelHandle> status) { 152 return Import(status ? status.take() 153 : LocalChannelHandle{nullptr, -status.error()}); 154} 155 156int BufferConsumer::Acquire(LocalHandle* ready_fence) { 157 return Acquire(ready_fence, nullptr, 0); 158} 159 160int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta, 161 size_t meta_size_bytes) { 162 ATRACE_NAME("BufferConsumer::Acquire"); 163 LocalFence fence; 164 auto return_value = 165 std::make_pair(std::ref(fence), WrapBuffer(meta, meta_size_bytes)); 166 auto status = InvokeRemoteMethodInPlace<BufferHubRPC::ConsumerAcquire>( 167 &return_value, meta_size_bytes); 168 if (status && ready_fence) 169 *ready_fence = fence.take(); 170 return status ? 0 : -status.error(); 171} 172 173int BufferConsumer::Release(const LocalHandle& release_fence) { 174 ATRACE_NAME("BufferConsumer::Release"); 175 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>( 176 BorrowedFence(release_fence.Borrow()))); 177} 178 179int BufferConsumer::ReleaseAsync() { 180 ATRACE_NAME("BufferConsumer::ReleaseAsync"); 181 return ReturnStatusOrError( 182 SendImpulse(BufferHubRPC::ConsumerRelease::Opcode)); 183} 184 185int BufferConsumer::Discard() { return Release(LocalHandle()); } 186 187int BufferConsumer::SetIgnore(bool ignore) { 188 return ReturnStatusOrError( 189 InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore)); 190} 191 192BufferProducer::BufferProducer(int width, int height, int format, int usage, 193 size_t metadata_size, size_t slice_count) 194 : BASE(BufferHubRPC::kClientPath) { 195 ATRACE_NAME("BufferProducer::BufferProducer"); 196 ALOGD_IF(TRACE, 197 "BufferProducer::BufferProducer: fd=%d width=%d height=%d format=%d " 198 "usage=%d, metadata_size=%zu, slice_count=%zu", 199 event_fd(), width, height, format, usage, metadata_size, 200 slice_count); 201 202 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>( 203 width, height, format, usage, metadata_size, slice_count); 204 if (!status) { 205 ALOGE( 206 "BufferProducer::BufferProducer: Failed to create producer buffer: %s", 207 status.GetErrorMessage().c_str()); 208 Close(-status.error()); 209 return; 210 } 211 212 const int ret = ImportBuffer(); 213 if (ret < 0) { 214 ALOGE( 215 "BufferProducer::BufferProducer: Failed to import producer buffer: %s", 216 strerror(-ret)); 217 Close(ret); 218 } 219} 220 221BufferProducer::BufferProducer(const std::string& name, int user_id, 222 int group_id, int width, int height, int format, 223 int usage, size_t meta_size_bytes, 224 size_t slice_count) 225 : BASE(BufferHubRPC::kClientPath) { 226 ATRACE_NAME("BufferProducer::BufferProducer"); 227 ALOGD_IF(TRACE, 228 "BufferProducer::BufferProducer: fd=%d name=%s user_id=%d " 229 "group_id=%d width=%d height=%d format=%d usage=%d, " 230 "meta_size_bytes=%zu, slice_count=%zu", 231 event_fd(), name.c_str(), user_id, group_id, width, height, format, 232 usage, meta_size_bytes, slice_count); 233 234 auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>( 235 name, user_id, group_id, width, height, format, usage, meta_size_bytes, 236 slice_count); 237 if (!status) { 238 ALOGE( 239 "BufferProducer::BufferProducer: Failed to create/get persistent " 240 "buffer \"%s\": %s", 241 name.c_str(), status.GetErrorMessage().c_str()); 242 Close(-status.error()); 243 return; 244 } 245 246 const int ret = ImportBuffer(); 247 if (ret < 0) { 248 ALOGE( 249 "BufferProducer::BufferProducer: Failed to import producer buffer " 250 "\"%s\": %s", 251 name.c_str(), strerror(-ret)); 252 Close(ret); 253 } 254} 255 256BufferProducer::BufferProducer(int usage, size_t size) 257 : BASE(BufferHubRPC::kClientPath) { 258 ATRACE_NAME("BufferProducer::BufferProducer"); 259 ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%d size=%zu", usage, 260 size); 261 const int width = static_cast<int>(size); 262 const int height = 1; 263 const int format = HAL_PIXEL_FORMAT_BLOB; 264 const size_t meta_size_bytes = 0; 265 const size_t slice_count = 1; 266 auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>( 267 width, height, format, usage, meta_size_bytes, slice_count); 268 if (!status) { 269 ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s", 270 status.GetErrorMessage().c_str()); 271 Close(-status.error()); 272 return; 273 } 274 275 const int ret = ImportBuffer(); 276 if (ret < 0) { 277 ALOGE( 278 "BufferProducer::BufferProducer: Failed to import producer buffer: %s", 279 strerror(-ret)); 280 Close(ret); 281 } 282} 283 284BufferProducer::BufferProducer(const std::string& name, int user_id, 285 int group_id, int usage, size_t size) 286 : BASE(BufferHubRPC::kClientPath) { 287 ATRACE_NAME("BufferProducer::BufferProducer"); 288 ALOGD_IF(TRACE, 289 "BufferProducer::BufferProducer: name=%s user_id=%d group=%d " 290 "usage=%d size=%zu", 291 name.c_str(), user_id, group_id, usage, size); 292 const int width = static_cast<int>(size); 293 const int height = 1; 294 const int format = HAL_PIXEL_FORMAT_BLOB; 295 const size_t meta_size_bytes = 0; 296 const size_t slice_count = 1; 297 auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>( 298 name, user_id, group_id, width, height, format, usage, meta_size_bytes, 299 slice_count); 300 if (!status) { 301 ALOGE( 302 "BufferProducer::BufferProducer: Failed to create persistent " 303 "buffer \"%s\": %s", 304 name.c_str(), status.GetErrorMessage().c_str()); 305 Close(-status.error()); 306 return; 307 } 308 309 const int ret = ImportBuffer(); 310 if (ret < 0) { 311 ALOGE( 312 "BufferProducer::BufferProducer: Failed to import producer buffer " 313 "\"%s\": %s", 314 name.c_str(), strerror(-ret)); 315 Close(ret); 316 } 317} 318 319BufferProducer::BufferProducer(const std::string& name) 320 : BASE(BufferHubRPC::kClientPath) { 321 ATRACE_NAME("BufferProducer::BufferProducer"); 322 ALOGD_IF(TRACE, "BufferProducer::BufferProducer: name=%s", name.c_str()); 323 324 auto status = InvokeRemoteMethod<BufferHubRPC::GetPersistentBuffer>(name); 325 if (!status) { 326 ALOGE( 327 "BufferProducer::BufferProducer: Failed to get producer buffer by name " 328 "\"%s\": %s", 329 name.c_str(), status.GetErrorMessage().c_str()); 330 Close(-status.error()); 331 return; 332 } 333 334 const int ret = ImportBuffer(); 335 if (ret < 0) { 336 ALOGE( 337 "BufferProducer::BufferProducer: Failed to import producer buffer " 338 "\"%s\": %s", 339 name.c_str(), strerror(-ret)); 340 Close(ret); 341 } 342} 343 344BufferProducer::BufferProducer(LocalChannelHandle channel) 345 : BASE(std::move(channel)) { 346 const int ret = ImportBuffer(); 347 if (ret < 0) { 348 ALOGE( 349 "BufferProducer::BufferProducer: Failed to import producer buffer: %s", 350 strerror(-ret)); 351 Close(ret); 352 } 353} 354 355int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta, 356 size_t meta_size_bytes) { 357 ATRACE_NAME("BufferProducer::Post"); 358 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>( 359 BorrowedFence(ready_fence.Borrow()), WrapBuffer(meta, meta_size_bytes))); 360} 361 362int BufferProducer::Gain(LocalHandle* release_fence) { 363 ATRACE_NAME("BufferProducer::Gain"); 364 auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>(); 365 if (!status) 366 return -status.error(); 367 if (release_fence) 368 *release_fence = status.take().take(); 369 return 0; 370} 371 372int BufferProducer::GainAsync() { 373 ATRACE_NAME("BufferProducer::GainAsync"); 374 return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode)); 375} 376 377std::unique_ptr<BufferProducer> BufferProducer::Import( 378 LocalChannelHandle channel) { 379 ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value()); 380 return BufferProducer::Create(std::move(channel)); 381} 382 383std::unique_ptr<BufferProducer> BufferProducer::Import( 384 Status<LocalChannelHandle> status) { 385 return Import(status ? status.take() 386 : LocalChannelHandle{nullptr, -status.error()}); 387} 388 389int BufferProducer::MakePersistent(const std::string& name, int user_id, 390 int group_id) { 391 ATRACE_NAME("BufferProducer::MakePersistent"); 392 return ReturnStatusOrError( 393 InvokeRemoteMethod<BufferHubRPC::ProducerMakePersistent>(name, user_id, 394 group_id)); 395} 396 397int BufferProducer::RemovePersistence() { 398 ATRACE_NAME("BufferProducer::RemovePersistence"); 399 return ReturnStatusOrError( 400 InvokeRemoteMethod<BufferHubRPC::ProducerRemovePersistence>()); 401} 402 403std::unique_ptr<BufferProducer> BufferProducer::CreateUncachedBlob( 404 size_t size) { 405 return BufferProducer::Create(kUncachedBlobUsageFlags, size); 406} 407 408std::unique_ptr<BufferProducer> BufferProducer::CreatePersistentUncachedBlob( 409 const std::string& name, int user_id, int group_id, size_t size) { 410 return BufferProducer::Create(name, user_id, group_id, 411 kUncachedBlobUsageFlags, size); 412} 413 414} // namespace dvr 415} // namespace android 416