1 #include <private/dvr/consumer_buffer.h> 2 3 using android::pdx::LocalChannelHandle; 4 using android::pdx::LocalHandle; 5 using android::pdx::Status; 6 7 namespace android { 8 namespace dvr { 9 10 ConsumerBuffer::ConsumerBuffer(LocalChannelHandle channel) 11 : BASE(std::move(channel)) { 12 const int ret = ImportBuffer(); 13 if (ret < 0) { 14 ALOGE("ConsumerBuffer::ConsumerBuffer: Failed to import buffer: %s", 15 strerror(-ret)); 16 Close(ret); 17 } 18 } 19 20 std::unique_ptr<ConsumerBuffer> ConsumerBuffer::Import( 21 LocalChannelHandle channel) { 22 ATRACE_NAME("ConsumerBuffer::Import"); 23 ALOGD_IF(TRACE, "ConsumerBuffer::Import: channel=%d", channel.value()); 24 return ConsumerBuffer::Create(std::move(channel)); 25 } 26 27 std::unique_ptr<ConsumerBuffer> ConsumerBuffer::Import( 28 Status<LocalChannelHandle> status) { 29 return Import(status ? status.take() 30 : LocalChannelHandle{nullptr, -status.error()}); 31 } 32 33 int ConsumerBuffer::LocalAcquire(DvrNativeBufferMetadata* out_meta, 34 LocalHandle* out_fence) { 35 if (!out_meta) 36 return -EINVAL; 37 38 // The buffer can be acquired iff the buffer state for this client is posted. 39 uint32_t current_buffer_state = 40 buffer_state_->load(std::memory_order_acquire); 41 if (!BufferHubDefs::isClientPosted(current_buffer_state, 42 client_state_mask())) { 43 ALOGE( 44 "%s: Failed to acquire the buffer. The buffer is not posted, id=%d " 45 "state=%" PRIx32 " client_state_mask=%" PRIx32 ".", 46 __FUNCTION__, id(), current_buffer_state, client_state_mask()); 47 return -EBUSY; 48 } 49 50 // Change the buffer state for this consumer from posted to acquired. 51 uint32_t updated_buffer_state = current_buffer_state ^ client_state_mask(); 52 while (!buffer_state_->compare_exchange_weak( 53 current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, 54 std::memory_order_acquire)) { 55 ALOGD( 56 "%s Failed to acquire the buffer. Current buffer state was changed to " 57 "%" PRIx32 58 " when trying to acquire the buffer and modify the buffer state to " 59 "%" PRIx32 ". About to try again if the buffer is still posted.", 60 __FUNCTION__, current_buffer_state, updated_buffer_state); 61 if (!BufferHubDefs::isClientPosted(current_buffer_state, 62 client_state_mask())) { 63 ALOGE( 64 "%s: Failed to acquire the buffer. The buffer is no longer posted, " 65 "id=%d state=%" PRIx32 " client_state_mask=%" PRIx32 ".", 66 __FUNCTION__, id(), current_buffer_state, client_state_mask()); 67 return -EBUSY; 68 } 69 // The failure of compare_exchange_weak updates current_buffer_state. 70 updated_buffer_state = current_buffer_state ^ client_state_mask(); 71 } 72 73 // Copy the canonical metadata. 74 void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata); 75 memcpy(out_meta, metadata_ptr, sizeof(DvrNativeBufferMetadata)); 76 // Fill in the user_metadata_ptr in address space of the local process. 77 if (out_meta->user_metadata_size) { 78 out_meta->user_metadata_ptr = 79 reinterpret_cast<uint64_t>(user_metadata_ptr_); 80 } else { 81 out_meta->user_metadata_ptr = 0; 82 } 83 84 uint32_t fence_state = fence_state_->load(std::memory_order_acquire); 85 // If there is an acquire fence from producer, we need to return it. 86 // The producer state bit mask is kFirstClientBitMask for now. 87 if (fence_state & BufferHubDefs::kFirstClientBitMask) { 88 *out_fence = shared_acquire_fence_.Duplicate(); 89 } 90 91 return 0; 92 } 93 94 int ConsumerBuffer::Acquire(LocalHandle* ready_fence) { 95 return Acquire(ready_fence, nullptr, 0); 96 } 97 98 int ConsumerBuffer::Acquire(LocalHandle* ready_fence, void* meta, 99 size_t user_metadata_size) { 100 ATRACE_NAME("ConsumerBuffer::Acquire"); 101 102 if (const int error = CheckMetadata(user_metadata_size)) 103 return error; 104 105 DvrNativeBufferMetadata canonical_meta; 106 if (const int error = LocalAcquire(&canonical_meta, ready_fence)) 107 return error; 108 109 if (meta && user_metadata_size) { 110 void* metadata_src = 111 reinterpret_cast<void*>(canonical_meta.user_metadata_ptr); 112 if (metadata_src) { 113 memcpy(meta, metadata_src, user_metadata_size); 114 } else { 115 ALOGW("ConsumerBuffer::Acquire: no user-defined metadata."); 116 } 117 } 118 119 auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>(); 120 if (!status) 121 return -status.error(); 122 return 0; 123 } 124 125 int ConsumerBuffer::AcquireAsync(DvrNativeBufferMetadata* out_meta, 126 LocalHandle* out_fence) { 127 ATRACE_NAME("ConsumerBuffer::AcquireAsync"); 128 129 if (const int error = LocalAcquire(out_meta, out_fence)) 130 return error; 131 132 auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode); 133 if (!status) 134 return -status.error(); 135 return 0; 136 } 137 138 int ConsumerBuffer::LocalRelease(const DvrNativeBufferMetadata* meta, 139 const LocalHandle& release_fence) { 140 if (const int error = CheckMetadata(meta->user_metadata_size)) 141 return error; 142 143 // Set the buffer state of this client to released if it is not already in 144 // released state. 145 uint32_t current_buffer_state = 146 buffer_state_->load(std::memory_order_acquire); 147 if (BufferHubDefs::isClientReleased(current_buffer_state, 148 client_state_mask())) { 149 return 0; 150 } 151 uint32_t updated_buffer_state = current_buffer_state & (~client_state_mask()); 152 while (!buffer_state_->compare_exchange_weak( 153 current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, 154 std::memory_order_acquire)) { 155 ALOGD( 156 "%s: Failed to release the buffer. Current buffer state was changed to " 157 "%" PRIx32 158 " when trying to release the buffer and modify the buffer state to " 159 "%" PRIx32 ". About to try again.", 160 __FUNCTION__, current_buffer_state, updated_buffer_state); 161 // The failure of compare_exchange_weak updates current_buffer_state. 162 updated_buffer_state = current_buffer_state & (~client_state_mask()); 163 } 164 165 // On release, only the user requested metadata is copied back into the shared 166 // memory for metadata. Since there are multiple consumers, it doesn't make 167 // sense to send the canonical metadata back to the producer. However, one of 168 // the consumer can still choose to write up to user_metadata_size bytes of 169 // data into user_metadata_ptr. 170 if (meta->user_metadata_ptr && meta->user_metadata_size) { 171 void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr); 172 memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size); 173 } 174 175 // Send out the release fence through the shared epoll fd. Note that during 176 // releasing the producer is not expected to be polling on the fence. 177 if (const int error = UpdateSharedFence(release_fence, shared_release_fence_)) 178 return error; 179 180 return 0; 181 } 182 183 int ConsumerBuffer::Release(const LocalHandle& release_fence) { 184 ATRACE_NAME("ConsumerBuffer::Release"); 185 186 DvrNativeBufferMetadata meta; 187 if (const int error = LocalRelease(&meta, release_fence)) 188 return error; 189 190 return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>( 191 BorrowedFence(release_fence.Borrow()))); 192 } 193 194 int ConsumerBuffer::ReleaseAsync() { 195 DvrNativeBufferMetadata meta; 196 return ReleaseAsync(&meta, LocalHandle()); 197 } 198 199 int ConsumerBuffer::ReleaseAsync(const DvrNativeBufferMetadata* meta, 200 const LocalHandle& release_fence) { 201 ATRACE_NAME("ConsumerBuffer::ReleaseAsync"); 202 203 if (const int error = LocalRelease(meta, release_fence)) 204 return error; 205 206 return ReturnStatusOrError( 207 SendImpulse(BufferHubRPC::ConsumerRelease::Opcode)); 208 } 209 210 int ConsumerBuffer::Discard() { return Release(LocalHandle()); } 211 212 } // namespace dvr 213 } // namespace android 214