• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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_TAG "C2Store"
18 // #define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <C2AllocatorBlob.h>
22 #include <C2AllocatorGralloc.h>
23 #include <C2AllocatorIon.h>
24 #include <C2DmaBufAllocator.h>
25 #include <C2BufferPriv.h>
26 #include <C2BqBufferPriv.h>
27 #include <C2Component.h>
28 #include <C2Config.h>
29 #include <C2IgbaBufferPriv.h>
30 #include <C2PlatformStorePluginLoader.h>
31 #include <C2PlatformSupport.h>
32 #include <codec2/common/HalSelection.h>
33 #include <cutils/properties.h>
34 #include <util/C2InterfaceHelper.h>
35 
36 #include <aidl/android/hardware/media/c2/IGraphicBufferAllocator.h>
37 
38 #include <dlfcn.h>
39 #include <unistd.h> // getpagesize
40 
41 #include <map>
42 #include <memory>
43 #include <mutex>
44 
45 #ifdef __ANDROID_APEX__
46 #include <android-base/properties.h>
47 #endif
48 
49 namespace android {
50 
51 /**
52  * Returns the preferred component store in this process to access its interface.
53  */
54 std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore();
55 
56 /**
57  * The platform allocator store provides basic allocator-types for the framework based on ion and
58  * gralloc. Allocators are not meant to be updatable.
59  *
60  * \todo Provide allocator based on ashmem
61  * \todo Move ion allocation into its HIDL or provide some mapping from memory usage to ion flags
62  * \todo Make this allocator store extendable
63  */
64 class C2PlatformAllocatorStoreImpl : public C2PlatformAllocatorStore {
65 public:
66     C2PlatformAllocatorStoreImpl();
67 
68     virtual c2_status_t fetchAllocator(
69             id_t id, std::shared_ptr<C2Allocator> *const allocator) override;
70 
listAllocators_nb() const71     virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb()
72             const override {
73         return std::vector<std::shared_ptr<const C2Allocator::Traits>>(); /// \todo
74     }
75 
getName() const76     virtual C2String getName() const override {
77         return "android.allocator-store";
78     }
79 
80     void setComponentStore(std::shared_ptr<C2ComponentStore> store);
81 
82     ~C2PlatformAllocatorStoreImpl() override = default;
83 
84 private:
85     /// returns a shared-singleton blob allocator (gralloc-backed)
86     std::shared_ptr<C2Allocator> fetchBlobAllocator();
87 
88     /// returns a shared-singleton ion allocator
89     std::shared_ptr<C2Allocator> fetchIonAllocator();
90     std::shared_ptr<C2Allocator> fetchDmaBufAllocator();
91 
92     /// returns a shared-singleton gralloc allocator
93     std::shared_ptr<C2Allocator> fetchGrallocAllocator();
94 
95     /// returns a shared-singleton bufferqueue supporting gralloc allocator
96     std::shared_ptr<C2Allocator> fetchBufferQueueAllocator();
97 
98     /// returns a shared-singleton IGBA supporting AHardwareBuffer/gralloc allocator
99     std::shared_ptr<C2Allocator> fetchIgbaAllocator();
100 
101     /// component store to use
102     std::mutex _mComponentStoreSetLock; // protects the entire updating _mComponentStore and its
103                                         // dependencies
104     std::mutex _mComponentStoreReadLock; // must protect only read/write of _mComponentStore
105     std::shared_ptr<C2ComponentStore> _mComponentStore;
106 };
107 
C2PlatformAllocatorStoreImpl()108 C2PlatformAllocatorStoreImpl::C2PlatformAllocatorStoreImpl() {
109 }
110 
using_ion(void)111 static bool using_ion(void) {
112     static int cached_result = []()->int {
113         struct stat buffer;
114         int ret = (stat("/dev/ion", &buffer) == 0);
115 
116         if (property_get_int32("debug.c2.use_dmabufheaps", 0)) {
117             /*
118              * Double check that the system heap is present so we
119              * can gracefully fail back to ION if we cannot satisfy
120              * the override
121              */
122             ret = (stat("/dev/dma_heap/system", &buffer) != 0);
123             if (ret)
124                 ALOGE("debug.c2.use_dmabufheaps set, but no system heap. Ignoring override!");
125             else
126                 ALOGD("debug.c2.use_dmabufheaps set, forcing DMABUF Heaps");
127         }
128 
129         if (ret)
130             ALOGD("Using ION\n");
131         else
132             ALOGD("Using DMABUF Heaps\n");
133         return ret;
134     }();
135 
136     return (cached_result == 1);
137 }
138 
fetchAllocator(id_t id,std::shared_ptr<C2Allocator> * const allocator)139 c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator(
140         id_t id, std::shared_ptr<C2Allocator> *const allocator) {
141     allocator->reset();
142     if (id == C2AllocatorStore::DEFAULT_LINEAR) {
143         id = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
144     }
145     switch (id) {
146     // TODO: should we implement a generic registry for all, and use that?
147     case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
148         if (using_ion())
149             *allocator = fetchIonAllocator();
150         else
151             *allocator = fetchDmaBufAllocator();
152         break;
153 
154     case C2PlatformAllocatorStore::GRALLOC:
155     case C2AllocatorStore::DEFAULT_GRAPHIC:
156         *allocator = fetchGrallocAllocator();
157         break;
158 
159     case C2PlatformAllocatorStore::BUFFERQUEUE:
160         *allocator = fetchBufferQueueAllocator();
161         break;
162 
163     case C2PlatformAllocatorStore::BLOB:
164         *allocator = fetchBlobAllocator();
165         break;
166 
167     case C2PlatformAllocatorStore::IGBA:
168         *allocator = fetchIgbaAllocator();
169         break;
170 
171     default:
172         // Try to create allocator from platform store plugins.
173         c2_status_t res =
174                 C2PlatformStorePluginLoader::GetInstance()->createAllocator(id, allocator);
175         if (res != C2_OK) {
176             return res;
177         }
178         break;
179     }
180     if (*allocator == nullptr) {
181         return C2_NO_MEMORY;
182     }
183     return C2_OK;
184 }
185 
186 namespace {
187 
188 std::mutex gIonAllocatorMutex;
189 std::mutex gDmaBufAllocatorMutex;
190 std::weak_ptr<C2AllocatorIon> gIonAllocator;
191 std::weak_ptr<C2DmaBufAllocator> gDmaBufAllocator;
192 
UseComponentStoreForIonAllocator(const std::shared_ptr<C2AllocatorIon> allocator,std::shared_ptr<C2ComponentStore> store)193 void UseComponentStoreForIonAllocator(
194         const std::shared_ptr<C2AllocatorIon> allocator,
195         std::shared_ptr<C2ComponentStore> store) {
196     C2AllocatorIon::UsageMapperFn mapper;
197     uint64_t minUsage = 0;
198     uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
199     size_t blockSize = getpagesize();
200 
201     // query min and max usage as well as block size via supported values
202     C2StoreIonUsageInfo usageInfo;
203     std::vector<C2FieldSupportedValuesQuery> query = {
204         C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.usage)),
205         C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(usageInfo, usageInfo.capacity)),
206     };
207     c2_status_t res = store->querySupportedValues_sm(query);
208     if (res == C2_OK) {
209         if (query[0].status == C2_OK) {
210             const C2FieldSupportedValues &fsv = query[0].values;
211             if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
212                 minUsage = fsv.values[0].u64;
213                 maxUsage = 0;
214                 for (C2Value::Primitive v : fsv.values) {
215                     maxUsage |= v.u64;
216                 }
217             }
218         }
219         if (query[1].status == C2_OK) {
220             const C2FieldSupportedValues &fsv = query[1].values;
221             if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
222                 blockSize = fsv.range.step.u32;
223             }
224         }
225 
226         mapper = [store](C2MemoryUsage usage, size_t capacity,
227                          size_t *align, unsigned *heapMask, unsigned *flags) -> c2_status_t {
228             if (capacity > UINT32_MAX) {
229                 return C2_BAD_VALUE;
230             }
231             C2StoreIonUsageInfo usageInfo = { usage.expected, capacity };
232             std::vector<std::unique_ptr<C2SettingResult>> failures; // TODO: remove
233             c2_status_t res = store->config_sm({&usageInfo}, &failures);
234             if (res == C2_OK) {
235                 *align = usageInfo.minAlignment;
236                 *heapMask = usageInfo.heapMask;
237                 *flags = usageInfo.allocFlags;
238             }
239             return res;
240         };
241     }
242 
243     allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
244 }
245 
UseComponentStoreForDmaBufAllocator(const std::shared_ptr<C2DmaBufAllocator> allocator,std::shared_ptr<C2ComponentStore> store)246 void UseComponentStoreForDmaBufAllocator(const std::shared_ptr<C2DmaBufAllocator> allocator,
247                                          std::shared_ptr<C2ComponentStore> store) {
248     C2DmaBufAllocator::UsageMapperFn mapper;
249     const size_t maxHeapNameLen = 128;
250     uint64_t minUsage = 0;
251     uint64_t maxUsage = C2MemoryUsage(C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE).expected;
252     size_t blockSize = getpagesize();
253 
254     // query min and max usage as well as block size via supported values
255     std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
256     usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen);
257 
258     std::vector<C2FieldSupportedValuesQuery> query = {
259             C2FieldSupportedValuesQuery::Possible(C2ParamField::Make(*usageInfo, usageInfo->m.usage)),
260             C2FieldSupportedValuesQuery::Possible(
261                     C2ParamField::Make(*usageInfo, usageInfo->m.capacity)),
262     };
263     c2_status_t res = store->querySupportedValues_sm(query);
264     if (res == C2_OK) {
265         if (query[0].status == C2_OK) {
266             const C2FieldSupportedValues& fsv = query[0].values;
267             if (fsv.type == C2FieldSupportedValues::FLAGS && !fsv.values.empty()) {
268                 minUsage = fsv.values[0].u64;
269                 maxUsage = 0;
270                 for (C2Value::Primitive v : fsv.values) {
271                     maxUsage |= v.u64;
272                 }
273             }
274         }
275         if (query[1].status == C2_OK) {
276             const C2FieldSupportedValues& fsv = query[1].values;
277             if (fsv.type == C2FieldSupportedValues::RANGE && fsv.range.step.u32 > 0) {
278                 blockSize = fsv.range.step.u32;
279             }
280         }
281 
282         mapper = [store](C2MemoryUsage usage, size_t capacity, C2String* heapName,
283                          unsigned* flags) -> c2_status_t {
284             if (capacity > UINT32_MAX) {
285                 return C2_BAD_VALUE;
286             }
287 
288             std::unique_ptr<C2StoreDmaBufUsageInfo> usageInfo;
289             usageInfo = C2StoreDmaBufUsageInfo::AllocUnique(maxHeapNameLen, usage.expected, capacity);
290             std::vector<std::unique_ptr<C2SettingResult>> failures;  // TODO: remove
291 
292             c2_status_t res = store->config_sm({&*usageInfo}, &failures);
293             if (res == C2_OK) {
294                 *heapName = C2String(usageInfo->m.heapName);
295                 *flags = usageInfo->m.allocFlags;
296             }
297 
298             return res;
299         };
300     }
301 
302     allocator->setUsageMapper(mapper, minUsage, maxUsage, blockSize);
303 }
304 
305 }
306 
setComponentStore(std::shared_ptr<C2ComponentStore> store)307 void C2PlatformAllocatorStoreImpl::setComponentStore(std::shared_ptr<C2ComponentStore> store) {
308     // technically this set lock is not needed, but is here for safety in case we add more
309     // getter orders
310     std::lock_guard<std::mutex> lock(_mComponentStoreSetLock);
311     {
312         std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
313         _mComponentStore = store;
314     }
315     std::shared_ptr<C2AllocatorIon> ionAllocator;
316     {
317         std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
318         ionAllocator = gIonAllocator.lock();
319     }
320     if (ionAllocator) {
321         UseComponentStoreForIonAllocator(ionAllocator, store);
322     }
323     std::shared_ptr<C2DmaBufAllocator> dmaAllocator;
324     {
325         std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
326         dmaAllocator = gDmaBufAllocator.lock();
327     }
328     if (dmaAllocator) {
329         UseComponentStoreForDmaBufAllocator(dmaAllocator, store);
330     }
331 }
332 
fetchIonAllocator()333 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIonAllocator() {
334     std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
335     std::shared_ptr<C2AllocatorIon> allocator = gIonAllocator.lock();
336     if (allocator == nullptr) {
337         std::shared_ptr<C2ComponentStore> componentStore;
338         {
339             std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
340             componentStore = _mComponentStore;
341         }
342         allocator = std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
343         UseComponentStoreForIonAllocator(allocator, componentStore);
344         gIonAllocator = allocator;
345     }
346     return allocator;
347 }
348 
fetchDmaBufAllocator()349 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchDmaBufAllocator() {
350     std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
351     std::shared_ptr<C2DmaBufAllocator> allocator = gDmaBufAllocator.lock();
352     if (allocator == nullptr) {
353         std::shared_ptr<C2ComponentStore> componentStore;
354         {
355             std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
356             componentStore = _mComponentStore;
357         }
358         allocator = std::make_shared<C2DmaBufAllocator>(C2PlatformAllocatorStore::DMABUFHEAP);
359         UseComponentStoreForDmaBufAllocator(allocator, componentStore);
360         gDmaBufAllocator = allocator;
361     }
362     return allocator;
363 }
364 
fetchBlobAllocator()365 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBlobAllocator() {
366     static std::mutex mutex;
367     static std::weak_ptr<C2Allocator> blobAllocator;
368     std::lock_guard<std::mutex> lock(mutex);
369     std::shared_ptr<C2Allocator> allocator = blobAllocator.lock();
370     if (allocator == nullptr) {
371         allocator = std::make_shared<C2AllocatorBlob>(C2PlatformAllocatorStore::BLOB);
372         blobAllocator = allocator;
373     }
374     return allocator;
375 }
376 
fetchGrallocAllocator()377 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
378     static std::mutex mutex;
379     static std::weak_ptr<C2Allocator> grallocAllocator;
380     std::lock_guard<std::mutex> lock(mutex);
381     std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
382     if (allocator == nullptr) {
383         allocator = std::make_shared<C2AllocatorGralloc>(C2PlatformAllocatorStore::GRALLOC);
384         grallocAllocator = allocator;
385     }
386     return allocator;
387 }
388 
fetchBufferQueueAllocator()389 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBufferQueueAllocator() {
390     static std::mutex mutex;
391     static std::weak_ptr<C2Allocator> grallocAllocator;
392     std::lock_guard<std::mutex> lock(mutex);
393     std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
394     if (allocator == nullptr) {
395         allocator = std::make_shared<C2AllocatorGralloc>(
396                 C2PlatformAllocatorStore::BUFFERQUEUE, true);
397         grallocAllocator = allocator;
398     }
399     return allocator;
400 }
401 
fetchIgbaAllocator()402 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIgbaAllocator() {
403     static std::mutex mutex;
404     static std::weak_ptr<C2Allocator> ahwbAllocator;
405     std::lock_guard<std::mutex> lock(mutex);
406     std::shared_ptr<C2Allocator> allocator = ahwbAllocator.lock();
407     if (allocator == nullptr) {
408         allocator = std::make_shared<C2AllocatorAhwb>(C2PlatformAllocatorStore::IGBA);
409         ahwbAllocator = allocator;
410     }
411     return allocator;
412 }
413 
414 namespace {
415     std::mutex gPreferredComponentStoreMutex;
416     std::shared_ptr<C2ComponentStore> gPreferredComponentStore;
417 
418     std::mutex gPlatformAllocatorStoreMutex;
419     std::weak_ptr<C2PlatformAllocatorStoreImpl> gPlatformAllocatorStore;
420 }
421 
GetCodec2PlatformAllocatorStore()422 std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore() {
423     std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
424     std::shared_ptr<C2PlatformAllocatorStoreImpl> store = gPlatformAllocatorStore.lock();
425     if (store == nullptr) {
426         store = std::make_shared<C2PlatformAllocatorStoreImpl>();
427         store->setComponentStore(GetPreferredCodec2ComponentStore());
428         gPlatformAllocatorStore = store;
429     }
430     return store;
431 }
432 
SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore)433 void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore) {
434     static std::mutex mutex;
435     std::lock_guard<std::mutex> lock(mutex); // don't interleve set-s
436 
437     // update preferred store
438     {
439         std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
440         gPreferredComponentStore = componentStore;
441     }
442 
443     // update platform allocator's store as well if it is alive
444     std::shared_ptr<C2PlatformAllocatorStoreImpl> allocatorStore;
445     {
446         std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
447         allocatorStore = gPlatformAllocatorStore.lock();
448     }
449     if (allocatorStore) {
450         allocatorStore->setComponentStore(componentStore);
451     }
452 }
453 
GetPreferredCodec2ComponentStore()454 std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore() {
455     std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
456     return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore();
457 }
458 
GetCodec2PoolMask()459 int GetCodec2PoolMask() {
460     return property_get_int32(
461             "debug.stagefright.c2-poolmask",
462             1 << C2PlatformAllocatorStore::ION |
463             1 << C2PlatformAllocatorStore::BUFFERQUEUE);
464 }
465 
GetPreferredLinearAllocatorId(int poolMask)466 C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask) {
467     return ((poolMask >> C2PlatformAllocatorStore::BLOB) & 1) ? C2PlatformAllocatorStore::BLOB
468                                                               : C2PlatformAllocatorStore::ION;
469 }
470 
471 namespace {
472 
GetBufferPoolVer()473 static C2PooledBlockPool::BufferPoolVer GetBufferPoolVer() {
474     static C2PooledBlockPool::BufferPoolVer sVer =
475         IsCodec2AidlHalSelected() ? C2PooledBlockPool::VER_AIDL2 : C2PooledBlockPool::VER_HIDL;
476     return sVer;
477 }
478 
479 class _C2BlockPoolCache {
480 public:
_C2BlockPoolCache()481     _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {
482         mBqPoolDeferDeallocAfterStop = false;
483 #ifdef __ANDROID_APEX__
484         bool stopHalBeforeSurface = ::android::base::GetBoolProperty(
485                 "debug.codec2.stop_hal_before_surface", false);
486         if (!stopHalBeforeSurface) {
487             mBqPoolDeferDeallocAfterStop =
488                     ::android::base::GetIntProperty(
489                             "debug.codec2.bqpool_dealloc_after_stop", 0) != 0;
490         }
491 #endif
492     }
493 
494 private:
_createBlockPool(C2PlatformAllocatorDesc & allocatorParam,std::vector<std::shared_ptr<const C2Component>> components,C2BlockPool::local_id_t poolId,bool deferDeallocAfterStop,std::shared_ptr<C2BlockPool> * pool)495     c2_status_t _createBlockPool(
496             C2PlatformAllocatorDesc &allocatorParam,
497             std::vector<std::shared_ptr<const C2Component>> components,
498             C2BlockPool::local_id_t poolId,
499             bool deferDeallocAfterStop,
500             std::shared_ptr<C2BlockPool> *pool) {
501         std::shared_ptr<C2AllocatorStore> allocatorStore =
502                 GetCodec2PlatformAllocatorStore();
503         C2PlatformAllocatorStore::id_t allocatorId = allocatorParam.allocatorId;
504         std::shared_ptr<C2Allocator> allocator;
505         c2_status_t res = C2_NOT_FOUND;
506 
507         if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
508             allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
509         }
510         auto deleter = [this, poolId](C2BlockPool *pool) {
511             std::unique_lock lock(mMutex);
512             mBlockPools.erase(poolId);
513             mComponents.erase(poolId);
514             delete pool;
515         };
516         switch(allocatorId) {
517             case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
518                 res = allocatorStore->fetchAllocator(
519                         C2PlatformAllocatorStore::ION, &allocator);
520                 if (res == C2_OK) {
521                     std::shared_ptr<C2BlockPool> ptr(
522                             new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
523                     *pool = ptr;
524                     mBlockPools[poolId] = ptr;
525                     mComponents[poolId].insert(
526                            mComponents[poolId].end(),
527                            components.begin(), components.end());
528                 }
529                 break;
530             case C2PlatformAllocatorStore::BLOB:
531                 res = allocatorStore->fetchAllocator(
532                         C2PlatformAllocatorStore::BLOB, &allocator);
533                 if (res == C2_OK) {
534                     std::shared_ptr<C2BlockPool> ptr(
535                             new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
536                     *pool = ptr;
537                     mBlockPools[poolId] = ptr;
538                     mComponents[poolId].insert(
539                            mComponents[poolId].end(),
540                            components.begin(), components.end());
541                 }
542                 break;
543             case C2PlatformAllocatorStore::GRALLOC:
544             case C2AllocatorStore::DEFAULT_GRAPHIC:
545                 res = allocatorStore->fetchAllocator(
546                         C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
547                 if (res == C2_OK) {
548                     std::shared_ptr<C2BlockPool> ptr(
549                             new C2PooledBlockPool(allocator, poolId, GetBufferPoolVer()), deleter);
550                     *pool = ptr;
551                     mBlockPools[poolId] = ptr;
552                     mComponents[poolId].insert(
553                            mComponents[poolId].end(),
554                            components.begin(), components.end());
555                 }
556                 break;
557             case C2PlatformAllocatorStore::BUFFERQUEUE:
558                 res = allocatorStore->fetchAllocator(
559                         C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
560                 if (res == C2_OK) {
561                     std::shared_ptr<C2BlockPool> ptr(
562                             new C2BufferQueueBlockPool(allocator, poolId), deleter);
563                     if (deferDeallocAfterStop) {
564                         std::shared_ptr<C2BufferQueueBlockPool> bqPool =
565                             std::static_pointer_cast<C2BufferQueueBlockPool>(ptr);
566                         bqPool->setDeferDeallocationAfterStop();
567                     }
568                     *pool = ptr;
569                     mBlockPools[poolId] = ptr;
570                     mComponents[poolId].insert(
571                            mComponents[poolId].end(),
572                            components.begin(), components.end());
573                 }
574                 break;
575             case C2PlatformAllocatorStore::IGBA:
576                 res = allocatorStore->fetchAllocator(
577                         C2PlatformAllocatorStore::IGBA, &allocator);
578                 if (res == C2_OK) {
579                     bool blockFence =
580                             (components.size() == 1 && allocatorParam.blockFenceSupport);
581                     std::shared_ptr<C2BlockPool> ptr(
582                             new C2IgbaBlockPool(allocator,
583                                                 allocatorParam.igba,
584                                                 std::move(allocatorParam.waitableFd),
585                                                 blockFence, poolId), deleter);
586                     *pool = ptr;
587                     mBlockPools[poolId] = ptr;
588                     mComponents[poolId].insert(
589                            mComponents[poolId].end(),
590                            components.begin(), components.end());
591                 }
592                 break;
593             default:
594                 // Try to create block pool from platform store plugins.
595                 std::shared_ptr<C2BlockPool> ptr;
596                 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
597                         allocatorId, poolId, &ptr, deleter);
598                 if (res == C2_OK) {
599                     *pool = ptr;
600                     mBlockPools[poolId] = ptr;
601                     mComponents[poolId].insert(
602                            mComponents[poolId].end(),
603                            components.begin(), components.end());
604                 }
605                 break;
606         }
607         return res;
608     }
609 
610 public:
createBlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::vector<std::shared_ptr<const C2Component>> components,std::shared_ptr<C2BlockPool> * pool)611     c2_status_t createBlockPool(
612             C2PlatformAllocatorStore::id_t allocatorId,
613             std::vector<std::shared_ptr<const C2Component>> components,
614             std::shared_ptr<C2BlockPool> *pool) {
615         C2PlatformAllocatorDesc allocator;
616         allocator.allocatorId = allocatorId;
617         return createBlockPool(allocator, components, pool);
618     }
619 
createBlockPool(C2PlatformAllocatorDesc & allocator,std::vector<std::shared_ptr<const C2Component>> components,std::shared_ptr<C2BlockPool> * pool)620     c2_status_t createBlockPool(
621             C2PlatformAllocatorDesc &allocator,
622             std::vector<std::shared_ptr<const C2Component>> components,
623             std::shared_ptr<C2BlockPool> *pool) {
624         std::unique_lock lock(mMutex);
625         return _createBlockPool(allocator, components, mBlockPoolSeqId++,
626                                 mBqPoolDeferDeallocAfterStop, pool);
627     }
628 
629 
getBlockPool(C2BlockPool::local_id_t blockPoolId,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)630     c2_status_t getBlockPool(
631             C2BlockPool::local_id_t blockPoolId,
632             std::shared_ptr<const C2Component> component,
633             std::shared_ptr<C2BlockPool> *pool) {
634         std::unique_lock lock(mMutex);
635         // TODO: use one iterator for multiple blockpool type scalability.
636         std::shared_ptr<C2BlockPool> ptr;
637         auto it = mBlockPools.find(blockPoolId);
638         if (it != mBlockPools.end()) {
639             ptr = it->second.lock();
640             if (!ptr) {
641                 mBlockPools.erase(it);
642                 mComponents.erase(blockPoolId);
643             } else {
644                 auto found = std::find_if(
645                         mComponents[blockPoolId].begin(),
646                         mComponents[blockPoolId].end(),
647                         [component](const std::weak_ptr<const C2Component> &ptr) {
648                             return component == ptr.lock();
649                         });
650                 if (found != mComponents[blockPoolId].end()) {
651                     *pool = ptr;
652                     return C2_OK;
653                 }
654             }
655         }
656         // TODO: remove this. this is temporary
657         if (blockPoolId == C2BlockPool::PLATFORM_START) {
658             C2PlatformAllocatorDesc allocator;
659             allocator.allocatorId = C2PlatformAllocatorStore::BUFFERQUEUE;
660             return _createBlockPool(
661                     allocator, {component}, blockPoolId, mBqPoolDeferDeallocAfterStop, pool);
662         }
663         return C2_NOT_FOUND;
664     }
665 
666 private:
667     // Deleter needs to hold this mutex, and there is a small chance that deleter
668     // is invoked while the mutex is held.
669     std::recursive_mutex mMutex;
670     C2BlockPool::local_id_t mBlockPoolSeqId;
671 
672     std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
673     std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
674 
675     bool mBqPoolDeferDeallocAfterStop;
676 };
677 
678 static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
679     std::make_unique<_C2BlockPoolCache>();
680 
681 } // anynymous namespace
682 
GetCodec2BlockPool(C2BlockPool::local_id_t id,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)683 c2_status_t GetCodec2BlockPool(
684         C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
685         std::shared_ptr<C2BlockPool> *pool) {
686     pool->reset();
687     std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
688     std::shared_ptr<C2Allocator> allocator;
689     c2_status_t res = C2_NOT_FOUND;
690 
691     if (id >= C2BlockPool::PLATFORM_START) {
692         return sBlockPoolCache->getBlockPool(id, component, pool);
693     }
694 
695     switch (id) {
696     case C2BlockPool::BASIC_LINEAR:
697         res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
698         if (res == C2_OK) {
699             *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
700         }
701         break;
702     case C2BlockPool::BASIC_GRAPHIC:
703         res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
704         if (res == C2_OK) {
705             *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
706         }
707         break;
708     default:
709         break;
710     }
711     return res;
712 }
713 
CreateCodec2BlockPool(C2PlatformAllocatorStore::id_t allocatorId,const std::vector<std::shared_ptr<const C2Component>> & components,std::shared_ptr<C2BlockPool> * pool)714 c2_status_t CreateCodec2BlockPool(
715         C2PlatformAllocatorStore::id_t allocatorId,
716         const std::vector<std::shared_ptr<const C2Component>> &components,
717         std::shared_ptr<C2BlockPool> *pool) {
718     pool->reset();
719 
720     C2PlatformAllocatorDesc allocator;
721     allocator.allocatorId = allocatorId;
722     return sBlockPoolCache->createBlockPool(allocator, components, pool);
723 }
724 
CreateCodec2BlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)725 c2_status_t CreateCodec2BlockPool(
726         C2PlatformAllocatorStore::id_t allocatorId,
727         std::shared_ptr<const C2Component> component,
728         std::shared_ptr<C2BlockPool> *pool) {
729     pool->reset();
730 
731     C2PlatformAllocatorDesc allocator;
732     allocator.allocatorId = allocatorId;
733     return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
734 }
735 
CreateCodec2BlockPool(C2PlatformAllocatorDesc & allocator,const std::vector<std::shared_ptr<const C2Component>> & components,std::shared_ptr<C2BlockPool> * pool)736 c2_status_t CreateCodec2BlockPool(
737         C2PlatformAllocatorDesc &allocator,
738         const std::vector<std::shared_ptr<const C2Component>> &components,
739         std::shared_ptr<C2BlockPool> *pool) {
740     pool->reset();
741 
742     return sBlockPoolCache->createBlockPool(allocator, components, pool);
743 }
744 
CreateCodec2BlockPool(C2PlatformAllocatorDesc & allocator,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)745 c2_status_t CreateCodec2BlockPool(
746         C2PlatformAllocatorDesc &allocator,
747         std::shared_ptr<const C2Component> component,
748         std::shared_ptr<C2BlockPool> *pool) {
749     pool->reset();
750 
751     return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
752 }
753 
754 class C2PlatformComponentStore : public C2ComponentStore {
755 public:
756     virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
757     virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
758     virtual C2String getName() const override;
759     virtual c2_status_t querySupportedValues_sm(
760             std::vector<C2FieldSupportedValuesQuery> &fields) const override;
761     virtual c2_status_t querySupportedParams_nb(
762             std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
763     virtual c2_status_t query_sm(
764             const std::vector<C2Param*> &stackParams,
765             const std::vector<C2Param::Index> &heapParamIndices,
766             std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
767     virtual c2_status_t createInterface(
768             C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
769     virtual c2_status_t createComponent(
770             C2String name, std::shared_ptr<C2Component> *const component) override;
771     virtual c2_status_t copyBuffer(
772             std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
773     virtual c2_status_t config_sm(
774             const std::vector<C2Param*> &params,
775             std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
776     C2PlatformComponentStore();
777 
778     // For testing only
779     C2PlatformComponentStore(
780             std::vector<std::tuple<C2String,
781                                    C2ComponentFactory::CreateCodec2FactoryFunc,
782                                    C2ComponentFactory::DestroyCodec2FactoryFunc>>);
783 
784     virtual ~C2PlatformComponentStore() override = default;
785 
786 private:
787 
788     /**
789      * An object encapsulating a loaded component module.
790      *
791      * \todo provide a way to add traits to known components here to avoid loading the .so-s
792      * for listComponents
793      */
794     struct ComponentModule : public C2ComponentFactory,
795             public std::enable_shared_from_this<ComponentModule> {
796         virtual c2_status_t createComponent(
797                 c2_node_id_t id, std::shared_ptr<C2Component> *component,
798                 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
799         virtual c2_status_t createInterface(
800                 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
801                 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
802 
803         /**
804          * \returns the traits of the component in this module.
805          */
806         std::shared_ptr<const C2Component::Traits> getTraits();
807 
808         /**
809          * Creates an uninitialized component module.
810          *
811          * \param name[in]  component name.
812          *
813          * \note Only used by ComponentLoader.
814          */
ComponentModuleandroid::C2PlatformComponentStore::ComponentModule815         ComponentModule()
816             : mInit(C2_NO_INIT),
817               mLibHandle(nullptr),
818               createFactory(nullptr),
819               destroyFactory(nullptr),
820               mComponentFactory(nullptr) {
821         }
822 
823         /**
824          * Creates an uninitialized component module.
825          * NOTE: For testing only
826          *
827          * \param name[in]  component name.
828          *
829          * \note Only used by ComponentLoader.
830          */
ComponentModuleandroid::C2PlatformComponentStore::ComponentModule831         ComponentModule(
832                 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
833                 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
834             : mInit(C2_NO_INIT),
835               mLibHandle(nullptr),
836               createFactory(createFactory),
837               destroyFactory(destroyFactory),
838               mComponentFactory(nullptr) {
839         }
840 
841         /**
842          * Initializes a component module with a given library path. Must be called exactly once.
843          *
844          * \note Only used by ComponentLoader.
845          *
846          * \param libPath[in] library path
847          *
848          * \retval C2_OK        the component module has been successfully loaded
849          * \retval C2_NO_MEMORY not enough memory to loading the component module
850          * \retval C2_NOT_FOUND could not locate the component module
851          * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
852          * \retval C2_REFUSED   permission denied to load the component module (unexpected)
853          * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
854          */
855         c2_status_t init(std::string libPath);
856 
857         virtual ~ComponentModule() override;
858 
859     protected:
860         std::recursive_mutex mLock; ///< lock protecting mTraits
861         std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
862 
863         c2_status_t mInit; ///< initialization result
864 
865         void *mLibHandle; ///< loaded library handle
866         C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
867         C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
868         C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
869     };
870 
871     /**
872      * An object encapsulating a loadable component module.
873      *
874      * \todo make this also work for enumerations
875      */
876     struct ComponentLoader {
877         /**
878          * Load the component module.
879          *
880          * This method simply returns the component module if it is already currently loaded, or
881          * attempts to load it if it is not.
882          *
883          * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
884          *                    This will be nullptr on error.
885          *
886          * \retval C2_OK        the component module has been successfully loaded
887          * \retval C2_NO_MEMORY not enough memory to loading the component module
888          * \retval C2_NOT_FOUND could not locate the component module
889          * \retval C2_CORRUPTED the component module could not be loaded
890          * \retval C2_REFUSED   permission denied to load the component module
891          */
fetchModuleandroid::C2PlatformComponentStore::ComponentLoader892         c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
893             c2_status_t res = C2_OK;
894             std::lock_guard<std::mutex> lock(mMutex);
895             std::shared_ptr<ComponentModule> localModule = mModule.lock();
896             if (localModule == nullptr) {
897                 if(mCreateFactory) {
898                     // For testing only
899                     localModule = std::make_shared<ComponentModule>(mCreateFactory,
900                                                                     mDestroyFactory);
901                 } else {
902                     localModule = std::make_shared<ComponentModule>();
903                 }
904                 res = localModule->init(mLibPath);
905                 if (res == C2_OK) {
906                     mModule = localModule;
907                 }
908             }
909             *module = localModule;
910             return res;
911         }
912 
913         /**
914          * Creates a component loader for a specific library path (or name).
915          */
ComponentLoaderandroid::C2PlatformComponentStore::ComponentLoader916         ComponentLoader(std::string libPath)
917             : mLibPath(libPath) {}
918 
919         // For testing only
ComponentLoaderandroid::C2PlatformComponentStore::ComponentLoader920         ComponentLoader(std::tuple<C2String,
921                           C2ComponentFactory::CreateCodec2FactoryFunc,
922                           C2ComponentFactory::DestroyCodec2FactoryFunc> func)
923             : mLibPath(std::get<0>(func)),
924               mCreateFactory(std::get<1>(func)),
925               mDestroyFactory(std::get<2>(func)) {}
926 
927     private:
928         std::mutex mMutex; ///< mutex guarding the module
929         std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
930         std::string mLibPath; ///< library path
931 
932         // For testing only
933         C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
934         C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
935     };
936 
937     struct Interface : public C2InterfaceHelper {
938         std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
939         std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
940 
Interfaceandroid::C2PlatformComponentStore::Interface941         Interface(std::shared_ptr<C2ReflectorHelper> reflector)
942             : C2InterfaceHelper(reflector) {
943             setDerivedInstance(this);
944 
945             struct Setter {
946                 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
947 #ifdef __ANDROID_APEX__
948                     static int32_t defaultHeapMask = [] {
949                         int32_t heapmask = base::GetIntProperty(
950                                 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
951                         ALOGD("Default ION heapmask = %d", heapmask);
952                         return heapmask;
953                     }();
954                     static int32_t defaultFlags = [] {
955                         int32_t flags = base::GetIntProperty(
956                                 "ro.com.android.media.swcodec.ion.flags", 0);
957                         ALOGD("Default ION flags = %d", flags);
958                         return flags;
959                     }();
960                     static uint32_t defaultAlign = [] {
961                         uint32_t align = base::GetUintProperty(
962                                 "ro.com.android.media.swcodec.ion.align", 0u);
963                         ALOGD("Default ION align = %d", align);
964                         return align;
965                     }();
966                     me.set().heapMask = defaultHeapMask;
967                     me.set().allocFlags = defaultFlags;
968                     me.set().minAlignment = defaultAlign;
969 #else
970                     me.set().heapMask = ~0;
971                     me.set().allocFlags = 0;
972                     me.set().minAlignment = 0;
973 #endif
974                     return C2R::Ok();
975                 };
976 
977                 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
978                     long long usage = (long long)me.get().m.usage;
979                     if (C2DmaBufAllocator::system_uncached_supported() &&
980                         !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
981                         strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
982                     } else {
983                         strncpy(me.set().m.heapName, "system", me.v.flexCount());
984                     }
985                     me.set().m.allocFlags = 0;
986                     return C2R::Ok();
987                 };
988             };
989 
990             addParameter(
991                 DefineParam(mIonUsageInfo, "ion-usage")
992                 .withDefault(new C2StoreIonUsageInfo())
993                 .withFields({
994                     C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
995                     C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
996                     C2F(mIonUsageInfo, heapMask).any(),
997                     C2F(mIonUsageInfo, allocFlags).flags({}),
998                     C2F(mIonUsageInfo, minAlignment).equalTo(0)
999                 })
1000                 .withSetter(Setter::setIonUsage)
1001                 .build());
1002 
1003             addParameter(
1004                 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
1005                 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
1006                 .withFields({
1007                     C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
1008                     C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
1009                     C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
1010                     C2F(mDmaBufUsageInfo, m.heapName).any(),
1011                 })
1012                 .withSetter(Setter::setDmaBufUsage)
1013                 .build());
1014         }
1015     };
1016 
1017     /**
1018      * Retrieves the component module for a component.
1019      *
1020      * \param module pointer to a shared_pointer where the component module will be stored on
1021      *               success.
1022      *
1023      * \retval C2_OK        the component loader has been successfully retrieved
1024      * \retval C2_NO_MEMORY not enough memory to locate the component loader
1025      * \retval C2_NOT_FOUND could not locate the component to be loaded
1026      * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
1027      *                      corrupted (this can happen if the name does not refer to an already
1028      *                      identified component but some components could not be loaded due to
1029      *                      bad library)
1030      * \retval C2_REFUSED   permission denied to find the component loader for the named component
1031      *                      (this can happen if the name does not refer to an already identified
1032      *                      component but some components could not be loaded due to lack of
1033      *                      permissions)
1034      */
1035     c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
1036 
1037     /**
1038      * Loads each component module and discover its contents.
1039      */
1040     void visitComponents();
1041 
1042     std::mutex mMutex; ///< mutex guarding the component lists during construction
1043     bool mVisited; ///< component modules visited
1044     std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
1045     std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
1046     std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
1047 
1048     std::shared_ptr<C2ReflectorHelper> mReflector;
1049     Interface mInterface;
1050 
1051     // For testing only
1052     std::vector<std::tuple<C2String,
1053                           C2ComponentFactory::CreateCodec2FactoryFunc,
1054                           C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
1055 };
1056 
init(std::string libPath)1057 c2_status_t C2PlatformComponentStore::ComponentModule::init(
1058         std::string libPath) {
1059     ALOGV("in %s", __func__);
1060     ALOGV("loading dll");
1061 
1062     if(!createFactory) {
1063         mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
1064         LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
1065                 "could not dlopen %s: %s", libPath.c_str(), dlerror());
1066 
1067         createFactory =
1068             (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
1069         LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
1070                 "createFactory is null in %s", libPath.c_str());
1071 
1072         destroyFactory =
1073             (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
1074         LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
1075                 "destroyFactory is null in %s", libPath.c_str());
1076     }
1077 
1078     mComponentFactory = createFactory();
1079     if (mComponentFactory == nullptr) {
1080         ALOGD("could not create factory in %s", libPath.c_str());
1081         mInit = C2_NO_MEMORY;
1082     } else {
1083         mInit = C2_OK;
1084     }
1085 
1086     if (mInit != C2_OK) {
1087         return mInit;
1088     }
1089 
1090     std::shared_ptr<C2ComponentInterface> intf;
1091     c2_status_t res = createInterface(0, &intf);
1092     if (res != C2_OK) {
1093         ALOGD("failed to create interface: %d", res);
1094         return mInit;
1095     }
1096 
1097     std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
1098     if (traits) {
1099         if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
1100             ALOGD("Failed to fill traits from interface");
1101             return mInit;
1102         }
1103 
1104         // TODO: get this properly from the store during emplace
1105         switch (traits->domain) {
1106         case C2Component::DOMAIN_AUDIO:
1107             traits->rank = 8;
1108             break;
1109         default:
1110             traits->rank = 512;
1111         }
1112     }
1113     mTraits = traits;
1114 
1115     return mInit;
1116 }
1117 
~ComponentModule()1118 C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1119     ALOGV("in %s", __func__);
1120     if (destroyFactory && mComponentFactory) {
1121         destroyFactory(mComponentFactory);
1122     }
1123     if (mLibHandle) {
1124         ALOGV("unloading dll");
1125         dlclose(mLibHandle);
1126     }
1127 }
1128 
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * interface,std::function<void (::C2ComponentInterface *)> deleter)1129 c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1130         c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1131         std::function<void(::C2ComponentInterface*)> deleter) {
1132     interface->reset();
1133     if (mInit != C2_OK) {
1134         return mInit;
1135     }
1136     std::shared_ptr<ComponentModule> module = shared_from_this();
1137     c2_status_t res = mComponentFactory->createInterface(
1138             id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1139                 // capture module so that we ensure we still have it while deleting interface
1140                 deleter(p); // delete interface first
1141                 module.reset(); // remove module ref (not technically needed)
1142     });
1143     return res;
1144 }
1145 
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * component,std::function<void (::C2Component *)> deleter)1146 c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1147         c2_node_id_t id, std::shared_ptr<C2Component> *component,
1148         std::function<void(::C2Component*)> deleter) {
1149     component->reset();
1150     if (mInit != C2_OK) {
1151         return mInit;
1152     }
1153     std::shared_ptr<ComponentModule> module = shared_from_this();
1154     c2_status_t res = mComponentFactory->createComponent(
1155             id, component, [module, deleter](C2Component *p) mutable {
1156                 // capture module so that we ensure we still have it while deleting component
1157                 deleter(p); // delete component first
1158                 module.reset(); // remove module ref (not technically needed)
1159     });
1160     return res;
1161 }
1162 
getTraits()1163 std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1164     std::unique_lock<std::recursive_mutex> lock(mLock);
1165     return mTraits;
1166 }
1167 
C2PlatformComponentStore()1168 C2PlatformComponentStore::C2PlatformComponentStore()
1169     : mVisited(false),
1170       mReflector(std::make_shared<C2ReflectorHelper>()),
1171       mInterface(mReflector) {
1172 
1173     auto emplace = [this](const char *libPath) {
1174         mComponents.emplace(libPath, libPath);
1175     };
1176 
1177     // TODO: move this also into a .so so it can be updated
1178     emplace("libcodec2_soft_aacdec.so");
1179     emplace("libcodec2_soft_aacenc.so");
1180     emplace("libcodec2_soft_amrnbdec.so");
1181     emplace("libcodec2_soft_amrnbenc.so");
1182     emplace("libcodec2_soft_amrwbdec.so");
1183     emplace("libcodec2_soft_amrwbenc.so");
1184     //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1185     emplace("libcodec2_soft_av1dec_gav1.so");
1186     emplace("libcodec2_soft_av1dec_dav1d.so");
1187     emplace("libcodec2_soft_av1enc.so");
1188     emplace("libcodec2_soft_avcdec.so");
1189     emplace("libcodec2_soft_avcenc.so");
1190     emplace("libcodec2_soft_flacdec.so");
1191     emplace("libcodec2_soft_flacenc.so");
1192     emplace("libcodec2_soft_g711alawdec.so");
1193     emplace("libcodec2_soft_g711mlawdec.so");
1194     emplace("libcodec2_soft_gsmdec.so");
1195     emplace("libcodec2_soft_h263dec.so");
1196     emplace("libcodec2_soft_h263enc.so");
1197     emplace("libcodec2_soft_hevcdec.so");
1198     emplace("libcodec2_soft_hevcenc.so");
1199     emplace("libcodec2_soft_mp3dec.so");
1200     emplace("libcodec2_soft_mpeg2dec.so");
1201     emplace("libcodec2_soft_mpeg4dec.so");
1202     emplace("libcodec2_soft_mpeg4enc.so");
1203     emplace("libcodec2_soft_opusdec.so");
1204     emplace("libcodec2_soft_opusenc.so");
1205     emplace("libcodec2_soft_rawdec.so");
1206     emplace("libcodec2_soft_vorbisdec.so");
1207     emplace("libcodec2_soft_vp8dec.so");
1208     emplace("libcodec2_soft_vp8enc.so");
1209     emplace("libcodec2_soft_vp9dec.so");
1210     emplace("libcodec2_soft_vp9enc.so");
1211     emplace("libcodec2_soft_apvenc.so");
1212     emplace("libcodec2_soft_apvdec.so");
1213 }
1214 
1215 // For testing only
C2PlatformComponentStore(std::vector<std::tuple<C2String,C2ComponentFactory::CreateCodec2FactoryFunc,C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)1216 C2PlatformComponentStore::C2PlatformComponentStore(
1217     std::vector<std::tuple<C2String,
1218                 C2ComponentFactory::CreateCodec2FactoryFunc,
1219                 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1220     : mVisited(false),
1221       mReflector(std::make_shared<C2ReflectorHelper>()),
1222       mInterface(mReflector),
1223       mCodec2FactoryFuncs(funcs) {
1224 
1225     for(auto const& func: mCodec2FactoryFuncs) {
1226         mComponents.emplace(std::get<0>(func), func);
1227     }
1228 }
1229 
copyBuffer(std::shared_ptr<C2GraphicBuffer> src,std::shared_ptr<C2GraphicBuffer> dst)1230 c2_status_t C2PlatformComponentStore::copyBuffer(
1231         std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1232     (void)src;
1233     (void)dst;
1234     return C2_OMITTED;
1235 }
1236 
query_sm(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const heapParams) const1237 c2_status_t C2PlatformComponentStore::query_sm(
1238         const std::vector<C2Param*> &stackParams,
1239         const std::vector<C2Param::Index> &heapParamIndices,
1240         std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1241     return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1242 }
1243 
config_sm(const std::vector<C2Param * > & params,std::vector<std::unique_ptr<C2SettingResult>> * const failures)1244 c2_status_t C2PlatformComponentStore::config_sm(
1245         const std::vector<C2Param*> &params,
1246         std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1247     return mInterface.config(params, C2_MAY_BLOCK, failures);
1248 }
1249 
visitComponents()1250 void C2PlatformComponentStore::visitComponents() {
1251     std::lock_guard<std::mutex> lock(mMutex);
1252     if (mVisited) {
1253         return;
1254     }
1255     for (auto &pathAndLoader : mComponents) {
1256         const C2String &path = pathAndLoader.first;
1257         ComponentLoader &loader = pathAndLoader.second;
1258         std::shared_ptr<ComponentModule> module;
1259         if (loader.fetchModule(&module) == C2_OK) {
1260             std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1261             if (traits) {
1262                 mComponentList.push_back(traits);
1263                 mComponentNameToPath.emplace(traits->name, path);
1264                 for (const C2String &alias : traits->aliases) {
1265                     mComponentNameToPath.emplace(alias, path);
1266                 }
1267             }
1268         }
1269     }
1270     mVisited = true;
1271 }
1272 
listComponents()1273 std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1274     // This method SHALL return within 500ms.
1275     visitComponents();
1276     return mComponentList;
1277 }
1278 
findComponent(C2String name,std::shared_ptr<ComponentModule> * module)1279 c2_status_t C2PlatformComponentStore::findComponent(
1280         C2String name, std::shared_ptr<ComponentModule> *module) {
1281     (*module).reset();
1282     visitComponents();
1283 
1284     auto pos = mComponentNameToPath.find(name);
1285     if (pos != mComponentNameToPath.end()) {
1286         return mComponents.at(pos->second).fetchModule(module);
1287     }
1288     return C2_NOT_FOUND;
1289 }
1290 
createComponent(C2String name,std::shared_ptr<C2Component> * const component)1291 c2_status_t C2PlatformComponentStore::createComponent(
1292         C2String name, std::shared_ptr<C2Component> *const component) {
1293     // This method SHALL return within 100ms.
1294     component->reset();
1295     std::shared_ptr<ComponentModule> module;
1296     c2_status_t res = findComponent(name, &module);
1297     if (res == C2_OK) {
1298         // TODO: get a unique node ID
1299         res = module->createComponent(0, component);
1300     }
1301     return res;
1302 }
1303 
createInterface(C2String name,std::shared_ptr<C2ComponentInterface> * const interface)1304 c2_status_t C2PlatformComponentStore::createInterface(
1305         C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1306     // This method SHALL return within 100ms.
1307     interface->reset();
1308     std::shared_ptr<ComponentModule> module;
1309     c2_status_t res = findComponent(name, &module);
1310     if (res == C2_OK) {
1311         // TODO: get a unique node ID
1312         res = module->createInterface(0, interface);
1313     }
1314     return res;
1315 }
1316 
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const1317 c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1318         std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1319     return mInterface.querySupportedParams(params);
1320 }
1321 
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const1322 c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1323         std::vector<C2FieldSupportedValuesQuery> &fields) const {
1324     return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1325 }
1326 
getName() const1327 C2String C2PlatformComponentStore::getName() const {
1328     return "android.componentStore.platform";
1329 }
1330 
getParamReflector() const1331 std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1332     return mReflector;
1333 }
1334 
GetCodec2PlatformComponentStore()1335 std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1336     static std::mutex mutex;
1337     static std::weak_ptr<C2ComponentStore> platformStore;
1338     std::lock_guard<std::mutex> lock(mutex);
1339     std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1340     if (store == nullptr) {
1341         store = std::make_shared<C2PlatformComponentStore>();
1342         platformStore = store;
1343     }
1344     return store;
1345 }
1346 
1347 // For testing only
GetTestComponentStore(std::vector<std::tuple<C2String,C2ComponentFactory::CreateCodec2FactoryFunc,C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)1348 std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1349         std::vector<std::tuple<C2String,
1350         C2ComponentFactory::CreateCodec2FactoryFunc,
1351         C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1352     return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1353 }
1354 } // namespace android
1355