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