1 /*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "Codec2-AIDL-BufferTypes"
19 #include <android-base/logging.h>
20
21 #include <aidlcommonsupport/NativeHandle.h>
22 #include <aidl/android/hardware/media/bufferpool2/BufferStatusMessage.h>
23 #include <bufferpool2/BufferPoolTypes.h>
24 #include <codec2/aidl/BufferTypes.h>
25 #include <codec2/common/BufferTypes.h>
26 #include <cutils/native_handle.h>
27 #include <media/stagefright/foundation/AUtils.h>
28
29 #include <C2AllocatorIon.h>
30 #include <C2AllocatorGralloc.h>
31 #include <C2BlockInternal.h>
32 #include <C2Buffer.h>
33 #include <C2Component.h>
34 #include <C2FenceFactory.h>
35 #include <C2Param.h>
36 #include <C2PlatformSupport.h>
37 #include <C2Work.h>
38
39 #include <algorithm>
40 #include <functional>
41 #include <iomanip>
42 #include <unordered_map>
43
44 #include "ParamTypes-specialization.h"
45
46 namespace android {
47
48 using ::aidl::android::hardware::media::bufferpool2::BufferPoolData;
49 using ::aidl::android::hardware::media::bufferpool2::BufferStatusMessage;
50 using ::aidl::android::hardware::media::bufferpool2::ResultStatus;
51 using ::aidl::android::hardware::media::bufferpool2::implementation::BufferPoolStatus;
52 using ::aidl::android::hardware::media::bufferpool2::implementation::ClientManager;
53 using ::aidl::android::hardware::media::c2::BaseBlock;
54 using ::aidl::android::hardware::media::c2::utils::BufferPoolTypes;
55
56 using AidlNativeHandle = ::aidl::android::hardware::common::NativeHandle;
57 using AidlHardwareBuffer = ::aidl::android::hardware::HardwareBuffer;
58
59 constexpr BaseBlock::Tag NATIVE_BLOCK = BaseBlock::nativeBlock;
60 constexpr BaseBlock::Tag HWB_BLOCK = BaseBlock::hwbBlock;
61 constexpr BaseBlock::Tag POOLED_BLOCK = BaseBlock::pooledBlock;
62
63 // BaseBlock -> C2BaseBlock
64 template<>
objcpy(C2BaseBlock * d,const BaseBlock & s)65 bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
66 switch (s.getTag()) {
67 case NATIVE_BLOCK: {
68 if (isAidlNativeHandleEmpty(s.get<NATIVE_BLOCK>())) {
69 LOG(ERROR) << "Null BaseBlock::nativeBlock handle";
70 return false;
71 }
72 native_handle_t* sHandle =
73 ::android::dupFromAidl(s.get<NATIVE_BLOCK>());
74 if (sHandle == nullptr) {
75 LOG(ERROR) << "Null BaseBlock::nativeBlock.";
76 return false;
77 }
78 const C2Handle *sC2Handle =
79 reinterpret_cast<const C2Handle*>(sHandle);
80
81 // If successful, the handle is deleted(!) and fds are owned by the block.
82 d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
83 if (d->linear) {
84 d->type = ::android::C2BaseBlock::LINEAR;
85 return true;
86 }
87
88 // If successful, the handle is deleted(!) and fds are owned by the block.
89 d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
90 if (d->graphic) {
91 d->type = ::android::C2BaseBlock::GRAPHIC;
92 return true;
93 }
94
95 LOG(ERROR) << "Unknown handle type in BaseBlock::nativeBlock.";
96 if (sHandle) {
97 native_handle_close(sHandle);
98 native_handle_delete(sHandle);
99 }
100 return false;
101 }
102 case HWB_BLOCK: {
103 AHardwareBuffer *pBuf =
104 const_cast<AidlHardwareBuffer&>(
105 s.get<HWB_BLOCK>()).release();
106 d->graphic = _C2BlockFactory::CreateGraphicBlock(pBuf);
107 if (pBuf) {
108 AHardwareBuffer_release(pBuf);
109 }
110 if (d->graphic) {
111 d->type = ::android::C2BaseBlock::GRAPHIC;
112 return true;
113 }
114 LOG(ERROR) << "Improper ahwb in BaseBlock::hwbBlock.";
115 return false;
116 }
117 case POOLED_BLOCK: {
118 const BufferStatusMessage &bpMessage = s.get<POOLED_BLOCK>();
119 std::shared_ptr<ClientManager> bp = ClientManager::getInstance();
120 std::shared_ptr<BufferPoolData> bpData;
121 native_handle_t *cHandle;
122 BufferPoolStatus bpStatus = bp->receive(
123 bpMessage.connectionId,
124 bpMessage.transactionId,
125 bpMessage.bufferId,
126 bpMessage.timestampUs,
127 &cHandle,
128 &bpData);
129 if (bpStatus != ResultStatus::OK) {
130 LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
131 << "resultStatus = " << bpStatus << ".";
132 return false;
133 } else if (!bpData) {
134 LOG(ERROR) << "No data in bufferpool transaction.";
135 return false;
136 }
137
138 // If successful, the handle is deleted(!) and fds are owned by the block.
139 d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
140 if (d->linear) {
141 d->type = ::android::C2BaseBlock::LINEAR;
142 return true;
143 }
144
145 // If successful, the handle is deleted(!) and fds are owned by the block.
146 d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
147 if (d->graphic) {
148 d->type = ::android::C2BaseBlock::GRAPHIC;
149 return true;
150 }
151 if (cHandle) {
152 // Though we got cloned handle, creating block failed.
153 native_handle_close(cHandle);
154 native_handle_delete(cHandle);
155 }
156
157 LOG(ERROR) << "Unknown handle type in BaseBlock::pooledBlock.";
158 return false;
159 }
160 default:
161 LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
162 << "underlying value "
163 << ::android::underlying_value(s.getTag()) << ".";
164 return false;
165 }
166 }
167
168 // C2Fence -> AidlNativeHandle
169 template<>
objcpy(AidlNativeHandle * d,const C2Fence & s)170 bool objcpy(AidlNativeHandle* d, const C2Fence& s) {
171 // fds are not duplicated here
172 native_handle_t* handle = _C2FenceFactory::CreateNativeHandle(s);
173 if (handle) {
174 // |d| copies the fds without duplicating
175 *d = makeToAidl(handle);
176 // no fds are duplicated, just delete the handle
177 // Note: C2Fence still owns the fds and should not be cleared
178 // before the transaction is complete.
179 native_handle_delete(handle);
180 // } else if (!s.ready()) {
181 // // TODO: we should wait for unmarshallable fences but this may not be
182 // // the best place for it. We can safely ignore here as at this time
183 // // all fences used here are marshallable.
184 }
185 return true;
186 }
187
188 // AidlNativeHandle -> C2Fence
189 template<>
objcpy(C2Fence * d,const AidlNativeHandle & s)190 bool objcpy(C2Fence* d, const AidlNativeHandle& s) {
191 // makeFromAidl does not duplicate the fds.
192 native_handle_t* handle = makeFromAidl(s);
193 // C2Fence duplicates and owns the fds
194 *d = _C2FenceFactory::CreateFromNativeHandle(handle);
195 if (handle) {
196 // |handle| should not be closed here, as the fds are owned by |s|
197 native_handle_delete(handle);
198 }
199 return true;
200 }
201
202 template<>
SetHandle(BaseBlock * block,const C2Handle * handle)203 void SetHandle(BaseBlock *block, const C2Handle *handle) {
204 block->set<BaseBlock::nativeBlock>(dupToAidl(handle));
205 }
206
207 template<>
SetAHardwareBuffer(BaseBlock * block,AHardwareBuffer * ahwb)208 void SetAHardwareBuffer(BaseBlock *block, AHardwareBuffer *ahwb) {
209 AHardwareBuffer_acquire(ahwb);
210 block->set<HWB_BLOCK>(AidlHardwareBuffer());
211 (block->get<HWB_BLOCK>()).reset(ahwb);
212 }
213
214 template<>
SetPooledBlock(BaseBlock * baseBlock,const typename BufferPoolTypes::BufferStatusMessage & pooledBlock)215 void SetPooledBlock<BufferPoolTypes>(
216 BaseBlock *baseBlock,
217 const typename BufferPoolTypes::BufferStatusMessage &pooledBlock) {
218 baseBlock->set<POOLED_BLOCK>(pooledBlock);
219 }
220
221 template<>
GetBufferPoolData(const std::shared_ptr<const _C2BlockPoolData> & blockPoolData,std::shared_ptr<typename BufferPoolTypes::BufferPoolData> * bpData)222 bool GetBufferPoolData<BufferPoolTypes>(
223 const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
224 std::shared_ptr<typename BufferPoolTypes::BufferPoolData> *bpData) {
225 return _C2BlockFactory::GetBufferPoolData(blockPoolData, bpData);
226 }
227
228 } // namespace android
229
230 namespace aidl {
231 namespace android {
232 namespace hardware {
233 namespace media {
234 namespace c2 {
235 namespace utils {
236
237 namespace bufferpool2 = ::aidl::android::hardware::media::bufferpool2;
238 namespace bufferpool2_impl = ::aidl::android::hardware::media::bufferpool2::implementation;
239
240 // DefaultBufferPoolSender's implementation
241
DefaultBufferPoolSender(const std::shared_ptr<IClientManager> & receiverManager,std::chrono::steady_clock::duration refreshInterval)242 DefaultBufferPoolSender::DefaultBufferPoolSender(
243 const std::shared_ptr<IClientManager>& receiverManager,
244 std::chrono::steady_clock::duration refreshInterval)
245 : mReceiverManager(receiverManager),
246 mRefreshInterval(refreshInterval) {
247 }
248
setReceiver(const std::shared_ptr<IClientManager> & receiverManager,std::chrono::steady_clock::duration refreshInterval)249 void DefaultBufferPoolSender::setReceiver(
250 const std::shared_ptr<IClientManager>& receiverManager,
251 std::chrono::steady_clock::duration refreshInterval) {
252 std::lock_guard<std::mutex> lock(mMutex);
253 if (mReceiverManager != receiverManager) {
254 mReceiverManager = receiverManager;
255 mConnections.clear();
256 }
257 mRefreshInterval = refreshInterval;
258 }
259
send(const std::shared_ptr<bufferpool2::BufferPoolData> & bpData,bufferpool2::BufferStatusMessage * bpMessage)260 BufferPoolTypes::BufferPoolStatus DefaultBufferPoolSender::send(
261 const std::shared_ptr<bufferpool2::BufferPoolData>& bpData,
262 bufferpool2::BufferStatusMessage* bpMessage) {
263 int64_t connectionId = bpData->mConnectionId;
264 if (connectionId == 0) {
265 LOG(WARNING) << "registerSender -- invalid sender connection id (0).";
266 return bufferpool2::ResultStatus::CRITICAL_ERROR;
267 }
268 std::lock_guard<std::mutex> lock(mMutex);
269 if (!mReceiverManager) {
270 LOG(ERROR) << "No access to receiver's BufferPool.";
271 return bufferpool2::ResultStatus::NOT_FOUND;
272 }
273 if (!mSenderManager) {
274 mSenderManager = ClientManager::getInstance();
275 if (!mSenderManager) {
276 LOG(ERROR) << "Failed to retrieve local BufferPool ClientManager.";
277 return bufferpool2::ResultStatus::CRITICAL_ERROR;
278 }
279 }
280
281 int64_t receiverConnectionId{0};
282 auto foundConnection = mConnections.find(connectionId);
283 bool isNewConnection = foundConnection == mConnections.end();
284 std::chrono::steady_clock::time_point now =
285 std::chrono::steady_clock::now();
286 if (isNewConnection ||
287 (now - foundConnection->second.lastSent > mRefreshInterval)) {
288 // Initialize the bufferpool connection.
289 bufferpool2_impl::BufferPoolStatus rs =
290 mSenderManager->registerSender(mReceiverManager,
291 connectionId,
292 &receiverConnectionId,
293 &isNewConnection);
294 if ((rs != bufferpool2::ResultStatus::OK)
295 && (rs != bufferpool2::ResultStatus::ALREADY_EXISTS)) {
296 LOG(WARNING) << "registerSender -- returned error: "
297 << static_cast<int32_t>(rs)
298 << ".";
299 return rs;
300 } else if (receiverConnectionId == 0) {
301 LOG(WARNING) << "registerSender -- "
302 "invalid receiver connection id (0).";
303 return bufferpool2::ResultStatus::CRITICAL_ERROR;
304 } else {
305 if (foundConnection == mConnections.end()) {
306 foundConnection = mConnections.try_emplace(
307 connectionId, receiverConnectionId, now).first;
308 } else {
309 foundConnection->second.receiverConnectionId = receiverConnectionId;
310 }
311 }
312 } else {
313 receiverConnectionId = foundConnection->second.receiverConnectionId;
314 }
315
316 uint64_t transactionId;
317 int64_t timestampUs;
318 bufferpool2_impl::BufferPoolStatus rs = mSenderManager->postSend(
319 receiverConnectionId, bpData, &transactionId, ×tampUs);
320 if (rs != bufferpool2::ResultStatus::OK) {
321 LOG(ERROR) << "ClientManager::postSend -- returned error: "
322 << static_cast<int32_t>(rs)
323 << ".";
324 mConnections.erase(foundConnection);
325 return rs;
326 }
327 if (!bpMessage) {
328 LOG(ERROR) << "Null output parameter for BufferStatusMessage.";
329 mConnections.erase(foundConnection);
330 return bufferpool2::ResultStatus::CRITICAL_ERROR;
331 }
332 bpMessage->connectionId = receiverConnectionId;
333 bpMessage->bufferId = bpData->mId;
334 bpMessage->transactionId = transactionId;
335 bpMessage->timestampUs = timestampUs;
336 foundConnection->second.lastSent = now;
337 return rs;
338 }
339
340 // std::list<std::unique_ptr<C2Work>> -> WorkBundle
ToAidl(WorkBundle * d,const std::list<std::unique_ptr<C2Work>> & s,::android::BufferPoolSender<BufferPoolTypes> * bufferPoolSender)341 bool ToAidl(
342 WorkBundle* d,
343 const std::list<std::unique_ptr<C2Work>>& s,
344 ::android::BufferPoolSender<BufferPoolTypes>* bufferPoolSender) {
345 return ::android::objcpy(d, s, bufferPoolSender);
346 }
347
348 // WorkBundle -> std::list<std::unique_ptr<C2Work>>
FromAidl(std::list<std::unique_ptr<C2Work>> * d,const WorkBundle & s)349 bool FromAidl(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
350 return ::android::objcpy(d, s);
351 }
352
ReturnOutputBlocksToClientIfNeeded(const std::list<std::unique_ptr<C2Work>> & workList)353 void ReturnOutputBlocksToClientIfNeeded(
354 const std::list<std::unique_ptr<C2Work>>& workList) {
355 for (const std::unique_ptr<C2Work>& work : workList) {
356 if (!work) {
357 continue;
358 }
359 for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
360 if (worklet) {
361 for (const std::shared_ptr<C2Buffer>& buffer : worklet->output.buffers) {
362 if (buffer) {
363 for (const C2ConstGraphicBlock& block : buffer->data().graphicBlocks()) {
364 std::shared_ptr<_C2BlockPoolData> poolData =
365 _C2BlockFactory::GetGraphicBlockPoolData(block);
366 _C2BlockFactory::DisownIgbaBlock(poolData);
367 }
368 }
369 }
370 }
371 }
372 }
373 }
374
375 } // namespace utils
376 } // namespace c2
377 } // namespace media
378 } // namespace hardware
379 } // namespace android
380 } // namespace aidl
381
382