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> allocator;
305     {
306         std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
307         allocator = gIonAllocator.lock();
308     }
309     if (allocator) {
310         UseComponentStoreForIonAllocator(allocator, store);
311     }
312 }
313 
fetchIonAllocator()314 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIonAllocator() {
315     std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
316     std::shared_ptr<C2AllocatorIon> allocator = gIonAllocator.lock();
317     if (allocator == nullptr) {
318         std::shared_ptr<C2ComponentStore> componentStore;
319         {
320             std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
321             componentStore = _mComponentStore;
322         }
323         allocator = std::make_shared<C2AllocatorIon>(C2PlatformAllocatorStore::ION);
324         UseComponentStoreForIonAllocator(allocator, componentStore);
325         gIonAllocator = allocator;
326     }
327     return allocator;
328 }
329 
fetchDmaBufAllocator()330 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchDmaBufAllocator() {
331     std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
332     std::shared_ptr<C2DmaBufAllocator> allocator = gDmaBufAllocator.lock();
333     if (allocator == nullptr) {
334         std::shared_ptr<C2ComponentStore> componentStore;
335         {
336             std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
337             componentStore = _mComponentStore;
338         }
339         allocator = std::make_shared<C2DmaBufAllocator>(C2PlatformAllocatorStore::DMABUFHEAP);
340         UseComponentStoreForDmaBufAllocator(allocator, componentStore);
341         gDmaBufAllocator = allocator;
342     }
343     return allocator;
344 }
345 
fetchBlobAllocator()346 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBlobAllocator() {
347     static std::mutex mutex;
348     static std::weak_ptr<C2Allocator> blobAllocator;
349     std::lock_guard<std::mutex> lock(mutex);
350     std::shared_ptr<C2Allocator> allocator = blobAllocator.lock();
351     if (allocator == nullptr) {
352         allocator = std::make_shared<C2AllocatorBlob>(C2PlatformAllocatorStore::BLOB);
353         blobAllocator = allocator;
354     }
355     return allocator;
356 }
357 
fetchGrallocAllocator()358 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
359     static std::mutex mutex;
360     static std::weak_ptr<C2Allocator> grallocAllocator;
361     std::lock_guard<std::mutex> lock(mutex);
362     std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
363     if (allocator == nullptr) {
364         allocator = std::make_shared<C2AllocatorGralloc>(C2PlatformAllocatorStore::GRALLOC);
365         grallocAllocator = allocator;
366     }
367     return allocator;
368 }
369 
fetchBufferQueueAllocator()370 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBufferQueueAllocator() {
371     static std::mutex mutex;
372     static std::weak_ptr<C2Allocator> grallocAllocator;
373     std::lock_guard<std::mutex> lock(mutex);
374     std::shared_ptr<C2Allocator> allocator = grallocAllocator.lock();
375     if (allocator == nullptr) {
376         allocator = std::make_shared<C2AllocatorGralloc>(
377                 C2PlatformAllocatorStore::BUFFERQUEUE, true);
378         grallocAllocator = allocator;
379     }
380     return allocator;
381 }
382 
383 namespace {
384     std::mutex gPreferredComponentStoreMutex;
385     std::shared_ptr<C2ComponentStore> gPreferredComponentStore;
386 
387     std::mutex gPlatformAllocatorStoreMutex;
388     std::weak_ptr<C2PlatformAllocatorStoreImpl> gPlatformAllocatorStore;
389 }
390 
GetCodec2PlatformAllocatorStore()391 std::shared_ptr<C2AllocatorStore> GetCodec2PlatformAllocatorStore() {
392     std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
393     std::shared_ptr<C2PlatformAllocatorStoreImpl> store = gPlatformAllocatorStore.lock();
394     if (store == nullptr) {
395         store = std::make_shared<C2PlatformAllocatorStoreImpl>();
396         store->setComponentStore(GetPreferredCodec2ComponentStore());
397         gPlatformAllocatorStore = store;
398     }
399     return store;
400 }
401 
SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore)402 void SetPreferredCodec2ComponentStore(std::shared_ptr<C2ComponentStore> componentStore) {
403     static std::mutex mutex;
404     std::lock_guard<std::mutex> lock(mutex); // don't interleve set-s
405 
406     // update preferred store
407     {
408         std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
409         gPreferredComponentStore = componentStore;
410     }
411 
412     // update platform allocator's store as well if it is alive
413     std::shared_ptr<C2PlatformAllocatorStoreImpl> allocatorStore;
414     {
415         std::lock_guard<std::mutex> lock(gPlatformAllocatorStoreMutex);
416         allocatorStore = gPlatformAllocatorStore.lock();
417     }
418     if (allocatorStore) {
419         allocatorStore->setComponentStore(componentStore);
420     }
421 }
422 
GetPreferredCodec2ComponentStore()423 std::shared_ptr<C2ComponentStore> GetPreferredCodec2ComponentStore() {
424     std::lock_guard<std::mutex> lock(gPreferredComponentStoreMutex);
425     return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore();
426 }
427 
GetCodec2PoolMask()428 int GetCodec2PoolMask() {
429     return property_get_int32(
430             "debug.stagefright.c2-poolmask",
431             1 << C2PlatformAllocatorStore::ION |
432             1 << C2PlatformAllocatorStore::BUFFERQUEUE);
433 }
434 
GetPreferredLinearAllocatorId(int poolMask)435 C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask) {
436     return ((poolMask >> C2PlatformAllocatorStore::BLOB) & 1) ? C2PlatformAllocatorStore::BLOB
437                                                               : C2PlatformAllocatorStore::ION;
438 }
439 
440 namespace {
441 
442 class _C2BlockPoolCache {
443 public:
_C2BlockPoolCache()444     _C2BlockPoolCache() : mBlockPoolSeqId(C2BlockPool::PLATFORM_START + 1) {}
445 
446 private:
_createBlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::vector<std::shared_ptr<const C2Component>> components,C2BlockPool::local_id_t poolId,std::shared_ptr<C2BlockPool> * pool)447     c2_status_t _createBlockPool(
448             C2PlatformAllocatorStore::id_t allocatorId,
449             std::vector<std::shared_ptr<const C2Component>> components,
450             C2BlockPool::local_id_t poolId,
451             std::shared_ptr<C2BlockPool> *pool) {
452         std::shared_ptr<C2AllocatorStore> allocatorStore =
453                 GetCodec2PlatformAllocatorStore();
454         std::shared_ptr<C2Allocator> allocator;
455         c2_status_t res = C2_NOT_FOUND;
456 
457         if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
458             allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
459         }
460         auto deleter = [this, poolId](C2BlockPool *pool) {
461             std::unique_lock lock(mMutex);
462             mBlockPools.erase(poolId);
463             mComponents.erase(poolId);
464             delete pool;
465         };
466         switch(allocatorId) {
467             case C2PlatformAllocatorStore::ION: /* also ::DMABUFHEAP */
468                 res = allocatorStore->fetchAllocator(
469                         C2PlatformAllocatorStore::ION, &allocator);
470                 if (res == C2_OK) {
471                     std::shared_ptr<C2BlockPool> ptr(
472                             new C2PooledBlockPool(allocator, poolId), deleter);
473                     *pool = ptr;
474                     mBlockPools[poolId] = ptr;
475                     mComponents[poolId].insert(
476                            mComponents[poolId].end(),
477                            components.begin(), components.end());
478                 }
479                 break;
480             case C2PlatformAllocatorStore::BLOB:
481                 res = allocatorStore->fetchAllocator(
482                         C2PlatformAllocatorStore::BLOB, &allocator);
483                 if (res == C2_OK) {
484                     std::shared_ptr<C2BlockPool> ptr(
485                             new C2PooledBlockPool(allocator, poolId), deleter);
486                     *pool = ptr;
487                     mBlockPools[poolId] = ptr;
488                     mComponents[poolId].insert(
489                            mComponents[poolId].end(),
490                            components.begin(), components.end());
491                 }
492                 break;
493             case C2PlatformAllocatorStore::GRALLOC:
494             case C2AllocatorStore::DEFAULT_GRAPHIC:
495                 res = allocatorStore->fetchAllocator(
496                         C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
497                 if (res == C2_OK) {
498                     std::shared_ptr<C2BlockPool> ptr(
499                         new C2PooledBlockPool(allocator, poolId), deleter);
500                     *pool = ptr;
501                     mBlockPools[poolId] = ptr;
502                     mComponents[poolId].insert(
503                            mComponents[poolId].end(),
504                            components.begin(), components.end());
505                 }
506                 break;
507             case C2PlatformAllocatorStore::BUFFERQUEUE:
508                 res = allocatorStore->fetchAllocator(
509                         C2PlatformAllocatorStore::BUFFERQUEUE, &allocator);
510                 if (res == C2_OK) {
511                     std::shared_ptr<C2BlockPool> ptr(
512                             new C2BufferQueueBlockPool(allocator, poolId), deleter);
513                     *pool = ptr;
514                     mBlockPools[poolId] = ptr;
515                     mComponents[poolId].insert(
516                            mComponents[poolId].end(),
517                            components.begin(), components.end());
518                 }
519                 break;
520             default:
521                 // Try to create block pool from platform store plugins.
522                 std::shared_ptr<C2BlockPool> ptr;
523                 res = C2PlatformStorePluginLoader::GetInstance()->createBlockPool(
524                         allocatorId, poolId, &ptr, deleter);
525                 if (res == C2_OK) {
526                     *pool = ptr;
527                     mBlockPools[poolId] = ptr;
528                     mComponents[poolId].insert(
529                            mComponents[poolId].end(),
530                            components.begin(), components.end());
531                 }
532                 break;
533         }
534         return res;
535     }
536 
537 public:
createBlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::vector<std::shared_ptr<const C2Component>> components,std::shared_ptr<C2BlockPool> * pool)538     c2_status_t createBlockPool(
539             C2PlatformAllocatorStore::id_t allocatorId,
540             std::vector<std::shared_ptr<const C2Component>> components,
541             std::shared_ptr<C2BlockPool> *pool) {
542         std::unique_lock lock(mMutex);
543         return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
544     }
545 
getBlockPool(C2BlockPool::local_id_t blockPoolId,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)546     c2_status_t getBlockPool(
547             C2BlockPool::local_id_t blockPoolId,
548             std::shared_ptr<const C2Component> component,
549             std::shared_ptr<C2BlockPool> *pool) {
550         std::unique_lock lock(mMutex);
551         // TODO: use one iterator for multiple blockpool type scalability.
552         std::shared_ptr<C2BlockPool> ptr;
553         auto it = mBlockPools.find(blockPoolId);
554         if (it != mBlockPools.end()) {
555             ptr = it->second.lock();
556             if (!ptr) {
557                 mBlockPools.erase(it);
558                 mComponents.erase(blockPoolId);
559             } else {
560                 auto found = std::find_if(
561                         mComponents[blockPoolId].begin(),
562                         mComponents[blockPoolId].end(),
563                         [component](const std::weak_ptr<const C2Component> &ptr) {
564                             return component == ptr.lock();
565                         });
566                 if (found != mComponents[blockPoolId].end()) {
567                     *pool = ptr;
568                     return C2_OK;
569                 }
570             }
571         }
572         // TODO: remove this. this is temporary
573         if (blockPoolId == C2BlockPool::PLATFORM_START) {
574             return _createBlockPool(
575                     C2PlatformAllocatorStore::BUFFERQUEUE, {component}, blockPoolId, pool);
576         }
577         return C2_NOT_FOUND;
578     }
579 
580 private:
581     // Deleter needs to hold this mutex, and there is a small chance that deleter
582     // is invoked while the mutex is held.
583     std::recursive_mutex mMutex;
584     C2BlockPool::local_id_t mBlockPoolSeqId;
585 
586     std::map<C2BlockPool::local_id_t, std::weak_ptr<C2BlockPool>> mBlockPools;
587     std::map<C2BlockPool::local_id_t, std::vector<std::weak_ptr<const C2Component>>> mComponents;
588 };
589 
590 static std::unique_ptr<_C2BlockPoolCache> sBlockPoolCache =
591     std::make_unique<_C2BlockPoolCache>();
592 
593 } // anynymous namespace
594 
GetCodec2BlockPool(C2BlockPool::local_id_t id,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)595 c2_status_t GetCodec2BlockPool(
596         C2BlockPool::local_id_t id, std::shared_ptr<const C2Component> component,
597         std::shared_ptr<C2BlockPool> *pool) {
598     pool->reset();
599     std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
600     std::shared_ptr<C2Allocator> allocator;
601     c2_status_t res = C2_NOT_FOUND;
602 
603     if (id >= C2BlockPool::PLATFORM_START) {
604         return sBlockPoolCache->getBlockPool(id, component, pool);
605     }
606 
607     switch (id) {
608     case C2BlockPool::BASIC_LINEAR:
609         res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
610         if (res == C2_OK) {
611             *pool = std::make_shared<C2BasicLinearBlockPool>(allocator);
612         }
613         break;
614     case C2BlockPool::BASIC_GRAPHIC:
615         res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &allocator);
616         if (res == C2_OK) {
617             *pool = std::make_shared<C2BasicGraphicBlockPool>(allocator);
618         }
619         break;
620     default:
621         break;
622     }
623     return res;
624 }
625 
CreateCodec2BlockPool(C2PlatformAllocatorStore::id_t allocatorId,const std::vector<std::shared_ptr<const C2Component>> & components,std::shared_ptr<C2BlockPool> * pool)626 c2_status_t CreateCodec2BlockPool(
627         C2PlatformAllocatorStore::id_t allocatorId,
628         const std::vector<std::shared_ptr<const C2Component>> &components,
629         std::shared_ptr<C2BlockPool> *pool) {
630     pool->reset();
631 
632     return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
633 }
634 
CreateCodec2BlockPool(C2PlatformAllocatorStore::id_t allocatorId,std::shared_ptr<const C2Component> component,std::shared_ptr<C2BlockPool> * pool)635 c2_status_t CreateCodec2BlockPool(
636         C2PlatformAllocatorStore::id_t allocatorId,
637         std::shared_ptr<const C2Component> component,
638         std::shared_ptr<C2BlockPool> *pool) {
639     pool->reset();
640 
641     return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
642 }
643 
644 class C2PlatformComponentStore : public C2ComponentStore {
645 public:
646     virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
647     virtual std::shared_ptr<C2ParamReflector> getParamReflector() const override;
648     virtual C2String getName() const override;
649     virtual c2_status_t querySupportedValues_sm(
650             std::vector<C2FieldSupportedValuesQuery> &fields) const override;
651     virtual c2_status_t querySupportedParams_nb(
652             std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const override;
653     virtual c2_status_t query_sm(
654             const std::vector<C2Param*> &stackParams,
655             const std::vector<C2Param::Index> &heapParamIndices,
656             std::vector<std::unique_ptr<C2Param>> *const heapParams) const override;
657     virtual c2_status_t createInterface(
658             C2String name, std::shared_ptr<C2ComponentInterface> *const interface) override;
659     virtual c2_status_t createComponent(
660             C2String name, std::shared_ptr<C2Component> *const component) override;
661     virtual c2_status_t copyBuffer(
662             std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) override;
663     virtual c2_status_t config_sm(
664             const std::vector<C2Param*> &params,
665             std::vector<std::unique_ptr<C2SettingResult>> *const failures) override;
666     C2PlatformComponentStore();
667 
668     // For testing only
669     C2PlatformComponentStore(
670             std::vector<std::tuple<C2String,
671                                    C2ComponentFactory::CreateCodec2FactoryFunc,
672                                    C2ComponentFactory::DestroyCodec2FactoryFunc>>);
673 
674     virtual ~C2PlatformComponentStore() override = default;
675 
676 private:
677 
678     /**
679      * An object encapsulating a loaded component module.
680      *
681      * \todo provide a way to add traits to known components here to avoid loading the .so-s
682      * for listComponents
683      */
684     struct ComponentModule : public C2ComponentFactory,
685             public std::enable_shared_from_this<ComponentModule> {
686         virtual c2_status_t createComponent(
687                 c2_node_id_t id, std::shared_ptr<C2Component> *component,
688                 ComponentDeleter deleter = std::default_delete<C2Component>()) override;
689         virtual c2_status_t createInterface(
690                 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
691                 InterfaceDeleter deleter = std::default_delete<C2ComponentInterface>()) override;
692 
693         /**
694          * \returns the traits of the component in this module.
695          */
696         std::shared_ptr<const C2Component::Traits> getTraits();
697 
698         /**
699          * Creates an uninitialized component module.
700          *
701          * \param name[in]  component name.
702          *
703          * \note Only used by ComponentLoader.
704          */
ComponentModuleandroid::C2PlatformComponentStore::ComponentModule705         ComponentModule()
706             : mInit(C2_NO_INIT),
707               mLibHandle(nullptr),
708               createFactory(nullptr),
709               destroyFactory(nullptr),
710               mComponentFactory(nullptr) {
711         }
712 
713         /**
714          * Creates an uninitialized component module.
715          * NOTE: For testing only
716          *
717          * \param name[in]  component name.
718          *
719          * \note Only used by ComponentLoader.
720          */
ComponentModuleandroid::C2PlatformComponentStore::ComponentModule721         ComponentModule(
722                 C2ComponentFactory::CreateCodec2FactoryFunc createFactory,
723                 C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory)
724             : mInit(C2_NO_INIT),
725               mLibHandle(nullptr),
726               createFactory(createFactory),
727               destroyFactory(destroyFactory),
728               mComponentFactory(nullptr) {
729         }
730 
731         /**
732          * Initializes a component module with a given library path. Must be called exactly once.
733          *
734          * \note Only used by ComponentLoader.
735          *
736          * \param libPath[in] library path
737          *
738          * \retval C2_OK        the component module has been successfully loaded
739          * \retval C2_NO_MEMORY not enough memory to loading the component module
740          * \retval C2_NOT_FOUND could not locate the component module
741          * \retval C2_CORRUPTED the component module could not be loaded (unexpected)
742          * \retval C2_REFUSED   permission denied to load the component module (unexpected)
743          * \retval C2_TIMED_OUT could not load the module within the time limit (unexpected)
744          */
745         c2_status_t init(std::string libPath);
746 
747         virtual ~ComponentModule() override;
748 
749     protected:
750         std::recursive_mutex mLock; ///< lock protecting mTraits
751         std::shared_ptr<C2Component::Traits> mTraits; ///< cached component traits
752 
753         c2_status_t mInit; ///< initialization result
754 
755         void *mLibHandle; ///< loaded library handle
756         C2ComponentFactory::CreateCodec2FactoryFunc createFactory; ///< loaded create function
757         C2ComponentFactory::DestroyCodec2FactoryFunc destroyFactory; ///< loaded destroy function
758         C2ComponentFactory *mComponentFactory; ///< loaded/created component factory
759     };
760 
761     /**
762      * An object encapsulating a loadable component module.
763      *
764      * \todo make this also work for enumerations
765      */
766     struct ComponentLoader {
767         /**
768          * Load the component module.
769          *
770          * This method simply returns the component module if it is already currently loaded, or
771          * attempts to load it if it is not.
772          *
773          * \param module[out] pointer to the shared pointer where the loaded module shall be stored.
774          *                    This will be nullptr on error.
775          *
776          * \retval C2_OK        the component module has been successfully loaded
777          * \retval C2_NO_MEMORY not enough memory to loading the component module
778          * \retval C2_NOT_FOUND could not locate the component module
779          * \retval C2_CORRUPTED the component module could not be loaded
780          * \retval C2_REFUSED   permission denied to load the component module
781          */
fetchModuleandroid::C2PlatformComponentStore::ComponentLoader782         c2_status_t fetchModule(std::shared_ptr<ComponentModule> *module) {
783             c2_status_t res = C2_OK;
784             std::lock_guard<std::mutex> lock(mMutex);
785             std::shared_ptr<ComponentModule> localModule = mModule.lock();
786             if (localModule == nullptr) {
787                 if(mCreateFactory) {
788                     // For testing only
789                     localModule = std::make_shared<ComponentModule>(mCreateFactory,
790                                                                     mDestroyFactory);
791                 } else {
792                     localModule = std::make_shared<ComponentModule>();
793                 }
794                 res = localModule->init(mLibPath);
795                 if (res == C2_OK) {
796                     mModule = localModule;
797                 }
798             }
799             *module = localModule;
800             return res;
801         }
802 
803         /**
804          * Creates a component loader for a specific library path (or name).
805          */
ComponentLoaderandroid::C2PlatformComponentStore::ComponentLoader806         ComponentLoader(std::string libPath)
807             : mLibPath(libPath) {}
808 
809         // For testing only
ComponentLoaderandroid::C2PlatformComponentStore::ComponentLoader810         ComponentLoader(std::tuple<C2String,
811                           C2ComponentFactory::CreateCodec2FactoryFunc,
812                           C2ComponentFactory::DestroyCodec2FactoryFunc> func)
813             : mLibPath(std::get<0>(func)),
814               mCreateFactory(std::get<1>(func)),
815               mDestroyFactory(std::get<2>(func)) {}
816 
817     private:
818         std::mutex mMutex; ///< mutex guarding the module
819         std::weak_ptr<ComponentModule> mModule; ///< weak reference to the loaded module
820         std::string mLibPath; ///< library path
821 
822         // For testing only
823         C2ComponentFactory::CreateCodec2FactoryFunc mCreateFactory = nullptr;
824         C2ComponentFactory::DestroyCodec2FactoryFunc mDestroyFactory = nullptr;
825     };
826 
827     struct Interface : public C2InterfaceHelper {
828         std::shared_ptr<C2StoreIonUsageInfo> mIonUsageInfo;
829         std::shared_ptr<C2StoreDmaBufUsageInfo> mDmaBufUsageInfo;
830 
Interfaceandroid::C2PlatformComponentStore::Interface831         Interface(std::shared_ptr<C2ReflectorHelper> reflector)
832             : C2InterfaceHelper(reflector) {
833             setDerivedInstance(this);
834 
835             struct Setter {
836                 static C2R setIonUsage(bool /* mayBlock */, C2P<C2StoreIonUsageInfo> &me) {
837 #ifdef __ANDROID_APEX__
838                     static int32_t defaultHeapMask = [] {
839                         int32_t heapmask = base::GetIntProperty(
840                                 "ro.com.android.media.swcodec.ion.heapmask", int32_t(0xFFFFFFFF));
841                         ALOGD("Default ION heapmask = %d", heapmask);
842                         return heapmask;
843                     }();
844                     static int32_t defaultFlags = [] {
845                         int32_t flags = base::GetIntProperty(
846                                 "ro.com.android.media.swcodec.ion.flags", 0);
847                         ALOGD("Default ION flags = %d", flags);
848                         return flags;
849                     }();
850                     static uint32_t defaultAlign = [] {
851                         uint32_t align = base::GetUintProperty(
852                                 "ro.com.android.media.swcodec.ion.align", 0u);
853                         ALOGD("Default ION align = %d", align);
854                         return align;
855                     }();
856                     me.set().heapMask = defaultHeapMask;
857                     me.set().allocFlags = defaultFlags;
858                     me.set().minAlignment = defaultAlign;
859 #else
860                     me.set().heapMask = ~0;
861                     me.set().allocFlags = 0;
862                     me.set().minAlignment = 0;
863 #endif
864                     return C2R::Ok();
865                 };
866 
867                 static C2R setDmaBufUsage(bool /* mayBlock */, C2P<C2StoreDmaBufUsageInfo> &me) {
868                     long long usage = (long long)me.get().m.usage;
869                     if (C2DmaBufAllocator::system_uncached_supported() &&
870                         !(usage & (C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE))) {
871                         strncpy(me.set().m.heapName, "system-uncached", me.v.flexCount());
872                     } else {
873                         strncpy(me.set().m.heapName, "system", me.v.flexCount());
874                     }
875                     me.set().m.allocFlags = 0;
876                     return C2R::Ok();
877                 };
878             };
879 
880             addParameter(
881                 DefineParam(mIonUsageInfo, "ion-usage")
882                 .withDefault(new C2StoreIonUsageInfo())
883                 .withFields({
884                     C2F(mIonUsageInfo, usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
885                     C2F(mIonUsageInfo, capacity).inRange(0, UINT32_MAX, 1024),
886                     C2F(mIonUsageInfo, heapMask).any(),
887                     C2F(mIonUsageInfo, allocFlags).flags({}),
888                     C2F(mIonUsageInfo, minAlignment).equalTo(0)
889                 })
890                 .withSetter(Setter::setIonUsage)
891                 .build());
892 
893             addParameter(
894                 DefineParam(mDmaBufUsageInfo, "dmabuf-usage")
895                 .withDefault(C2StoreDmaBufUsageInfo::AllocShared(0))
896                 .withFields({
897                     C2F(mDmaBufUsageInfo, m.usage).flags({C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE}),
898                     C2F(mDmaBufUsageInfo, m.capacity).inRange(0, UINT32_MAX, 1024),
899                     C2F(mDmaBufUsageInfo, m.allocFlags).flags({}),
900                     C2F(mDmaBufUsageInfo, m.heapName).any(),
901                 })
902                 .withSetter(Setter::setDmaBufUsage)
903                 .build());
904         }
905     };
906 
907     /**
908      * Retrieves the component module for a component.
909      *
910      * \param module pointer to a shared_pointer where the component module will be stored on
911      *               success.
912      *
913      * \retval C2_OK        the component loader has been successfully retrieved
914      * \retval C2_NO_MEMORY not enough memory to locate the component loader
915      * \retval C2_NOT_FOUND could not locate the component to be loaded
916      * \retval C2_CORRUPTED the component loader could not be identified due to some modules being
917      *                      corrupted (this can happen if the name does not refer to an already
918      *                      identified component but some components could not be loaded due to
919      *                      bad library)
920      * \retval C2_REFUSED   permission denied to find the component loader for the named component
921      *                      (this can happen if the name does not refer to an already identified
922      *                      component but some components could not be loaded due to lack of
923      *                      permissions)
924      */
925     c2_status_t findComponent(C2String name, std::shared_ptr<ComponentModule> *module);
926 
927     /**
928      * Loads each component module and discover its contents.
929      */
930     void visitComponents();
931 
932     std::mutex mMutex; ///< mutex guarding the component lists during construction
933     bool mVisited; ///< component modules visited
934     std::map<C2String, ComponentLoader> mComponents; ///< path -> component module
935     std::map<C2String, C2String> mComponentNameToPath; ///< name -> path
936     std::vector<std::shared_ptr<const C2Component::Traits>> mComponentList;
937 
938     std::shared_ptr<C2ReflectorHelper> mReflector;
939     Interface mInterface;
940 
941     // For testing only
942     std::vector<std::tuple<C2String,
943                           C2ComponentFactory::CreateCodec2FactoryFunc,
944                           C2ComponentFactory::DestroyCodec2FactoryFunc>> mCodec2FactoryFuncs;
945 };
946 
init(std::string libPath)947 c2_status_t C2PlatformComponentStore::ComponentModule::init(
948         std::string libPath) {
949     ALOGV("in %s", __func__);
950     ALOGV("loading dll");
951 
952     if(!createFactory) {
953         mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
954         LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
955                 "could not dlopen %s: %s", libPath.c_str(), dlerror());
956 
957         createFactory =
958             (C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
959         LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
960                 "createFactory is null in %s", libPath.c_str());
961 
962         destroyFactory =
963             (C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
964         LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
965                 "destroyFactory is null in %s", libPath.c_str());
966     }
967 
968     mComponentFactory = createFactory();
969     if (mComponentFactory == nullptr) {
970         ALOGD("could not create factory in %s", libPath.c_str());
971         mInit = C2_NO_MEMORY;
972     } else {
973         mInit = C2_OK;
974     }
975 
976     if (mInit != C2_OK) {
977         return mInit;
978     }
979 
980     std::shared_ptr<C2ComponentInterface> intf;
981     c2_status_t res = createInterface(0, &intf);
982     if (res != C2_OK) {
983         ALOGD("failed to create interface: %d", res);
984         return mInit;
985     }
986 
987     std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
988     if (traits) {
989         if (!C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf)) {
990             ALOGD("Failed to fill traits from interface");
991             return mInit;
992         }
993 
994         // TODO: get this properly from the store during emplace
995         switch (traits->domain) {
996         case C2Component::DOMAIN_AUDIO:
997             traits->rank = 8;
998             break;
999         default:
1000             traits->rank = 512;
1001         }
1002     }
1003     mTraits = traits;
1004 
1005     return mInit;
1006 }
1007 
~ComponentModule()1008 C2PlatformComponentStore::ComponentModule::~ComponentModule() {
1009     ALOGV("in %s", __func__);
1010     if (destroyFactory && mComponentFactory) {
1011         destroyFactory(mComponentFactory);
1012     }
1013     if (mLibHandle) {
1014         ALOGV("unloading dll");
1015         dlclose(mLibHandle);
1016     }
1017 }
1018 
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * interface,std::function<void (::C2ComponentInterface *)> deleter)1019 c2_status_t C2PlatformComponentStore::ComponentModule::createInterface(
1020         c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *interface,
1021         std::function<void(::C2ComponentInterface*)> deleter) {
1022     interface->reset();
1023     if (mInit != C2_OK) {
1024         return mInit;
1025     }
1026     std::shared_ptr<ComponentModule> module = shared_from_this();
1027     c2_status_t res = mComponentFactory->createInterface(
1028             id, interface, [module, deleter](C2ComponentInterface *p) mutable {
1029                 // capture module so that we ensure we still have it while deleting interface
1030                 deleter(p); // delete interface first
1031                 module.reset(); // remove module ref (not technically needed)
1032     });
1033     return res;
1034 }
1035 
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * component,std::function<void (::C2Component *)> deleter)1036 c2_status_t C2PlatformComponentStore::ComponentModule::createComponent(
1037         c2_node_id_t id, std::shared_ptr<C2Component> *component,
1038         std::function<void(::C2Component*)> deleter) {
1039     component->reset();
1040     if (mInit != C2_OK) {
1041         return mInit;
1042     }
1043     std::shared_ptr<ComponentModule> module = shared_from_this();
1044     c2_status_t res = mComponentFactory->createComponent(
1045             id, component, [module, deleter](C2Component *p) mutable {
1046                 // capture module so that we ensure we still have it while deleting component
1047                 deleter(p); // delete component first
1048                 module.reset(); // remove module ref (not technically needed)
1049     });
1050     return res;
1051 }
1052 
getTraits()1053 std::shared_ptr<const C2Component::Traits> C2PlatformComponentStore::ComponentModule::getTraits() {
1054     std::unique_lock<std::recursive_mutex> lock(mLock);
1055     return mTraits;
1056 }
1057 
C2PlatformComponentStore()1058 C2PlatformComponentStore::C2PlatformComponentStore()
1059     : mVisited(false),
1060       mReflector(std::make_shared<C2ReflectorHelper>()),
1061       mInterface(mReflector) {
1062 
1063     auto emplace = [this](const char *libPath) {
1064         mComponents.emplace(libPath, libPath);
1065     };
1066 
1067     // TODO: move this also into a .so so it can be updated
1068     emplace("libcodec2_soft_aacdec.so");
1069     emplace("libcodec2_soft_aacenc.so");
1070     emplace("libcodec2_soft_amrnbdec.so");
1071     emplace("libcodec2_soft_amrnbenc.so");
1072     emplace("libcodec2_soft_amrwbdec.so");
1073     emplace("libcodec2_soft_amrwbenc.so");
1074     //emplace("libcodec2_soft_av1dec_aom.so"); // deprecated for the gav1 implementation
1075     emplace("libcodec2_soft_av1dec_gav1.so");
1076     emplace("libcodec2_soft_avcdec.so");
1077     emplace("libcodec2_soft_avcenc.so");
1078     emplace("libcodec2_soft_flacdec.so");
1079     emplace("libcodec2_soft_flacenc.so");
1080     emplace("libcodec2_soft_g711alawdec.so");
1081     emplace("libcodec2_soft_g711mlawdec.so");
1082     emplace("libcodec2_soft_gsmdec.so");
1083     emplace("libcodec2_soft_h263dec.so");
1084     emplace("libcodec2_soft_h263enc.so");
1085     emplace("libcodec2_soft_hevcdec.so");
1086     emplace("libcodec2_soft_hevcenc.so");
1087     emplace("libcodec2_soft_mp3dec.so");
1088     emplace("libcodec2_soft_mpeg2dec.so");
1089     emplace("libcodec2_soft_mpeg4dec.so");
1090     emplace("libcodec2_soft_mpeg4enc.so");
1091     emplace("libcodec2_soft_opusdec.so");
1092     emplace("libcodec2_soft_opusenc.so");
1093     emplace("libcodec2_soft_rawdec.so");
1094     emplace("libcodec2_soft_vorbisdec.so");
1095     emplace("libcodec2_soft_vp8dec.so");
1096     emplace("libcodec2_soft_vp8enc.so");
1097     emplace("libcodec2_soft_vp9dec.so");
1098     emplace("libcodec2_soft_vp9enc.so");
1099 
1100 }
1101 
1102 // For testing only
C2PlatformComponentStore(std::vector<std::tuple<C2String,C2ComponentFactory::CreateCodec2FactoryFunc,C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)1103 C2PlatformComponentStore::C2PlatformComponentStore(
1104     std::vector<std::tuple<C2String,
1105                 C2ComponentFactory::CreateCodec2FactoryFunc,
1106                 C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)
1107     : mVisited(false),
1108       mReflector(std::make_shared<C2ReflectorHelper>()),
1109       mInterface(mReflector),
1110       mCodec2FactoryFuncs(funcs) {
1111 
1112     for(auto const& func: mCodec2FactoryFuncs) {
1113         mComponents.emplace(std::get<0>(func), func);
1114     }
1115 }
1116 
copyBuffer(std::shared_ptr<C2GraphicBuffer> src,std::shared_ptr<C2GraphicBuffer> dst)1117 c2_status_t C2PlatformComponentStore::copyBuffer(
1118         std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) {
1119     (void)src;
1120     (void)dst;
1121     return C2_OMITTED;
1122 }
1123 
query_sm(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const heapParams) const1124 c2_status_t C2PlatformComponentStore::query_sm(
1125         const std::vector<C2Param*> &stackParams,
1126         const std::vector<C2Param::Index> &heapParamIndices,
1127         std::vector<std::unique_ptr<C2Param>> *const heapParams) const {
1128     return mInterface.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
1129 }
1130 
config_sm(const std::vector<C2Param * > & params,std::vector<std::unique_ptr<C2SettingResult>> * const failures)1131 c2_status_t C2PlatformComponentStore::config_sm(
1132         const std::vector<C2Param*> &params,
1133         std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
1134     return mInterface.config(params, C2_MAY_BLOCK, failures);
1135 }
1136 
visitComponents()1137 void C2PlatformComponentStore::visitComponents() {
1138     std::lock_guard<std::mutex> lock(mMutex);
1139     if (mVisited) {
1140         return;
1141     }
1142     for (auto &pathAndLoader : mComponents) {
1143         const C2String &path = pathAndLoader.first;
1144         ComponentLoader &loader = pathAndLoader.second;
1145         std::shared_ptr<ComponentModule> module;
1146         if (loader.fetchModule(&module) == C2_OK) {
1147             std::shared_ptr<const C2Component::Traits> traits = module->getTraits();
1148             if (traits) {
1149                 mComponentList.push_back(traits);
1150                 mComponentNameToPath.emplace(traits->name, path);
1151                 for (const C2String &alias : traits->aliases) {
1152                     mComponentNameToPath.emplace(alias, path);
1153                 }
1154             }
1155         }
1156     }
1157     mVisited = true;
1158 }
1159 
listComponents()1160 std::vector<std::shared_ptr<const C2Component::Traits>> C2PlatformComponentStore::listComponents() {
1161     // This method SHALL return within 500ms.
1162     visitComponents();
1163     return mComponentList;
1164 }
1165 
findComponent(C2String name,std::shared_ptr<ComponentModule> * module)1166 c2_status_t C2PlatformComponentStore::findComponent(
1167         C2String name, std::shared_ptr<ComponentModule> *module) {
1168     (*module).reset();
1169     visitComponents();
1170 
1171     auto pos = mComponentNameToPath.find(name);
1172     if (pos != mComponentNameToPath.end()) {
1173         return mComponents.at(pos->second).fetchModule(module);
1174     }
1175     return C2_NOT_FOUND;
1176 }
1177 
createComponent(C2String name,std::shared_ptr<C2Component> * const component)1178 c2_status_t C2PlatformComponentStore::createComponent(
1179         C2String name, std::shared_ptr<C2Component> *const component) {
1180     // This method SHALL return within 100ms.
1181     component->reset();
1182     std::shared_ptr<ComponentModule> module;
1183     c2_status_t res = findComponent(name, &module);
1184     if (res == C2_OK) {
1185         // TODO: get a unique node ID
1186         res = module->createComponent(0, component);
1187     }
1188     return res;
1189 }
1190 
createInterface(C2String name,std::shared_ptr<C2ComponentInterface> * const interface)1191 c2_status_t C2PlatformComponentStore::createInterface(
1192         C2String name, std::shared_ptr<C2ComponentInterface> *const interface) {
1193     // This method SHALL return within 100ms.
1194     interface->reset();
1195     std::shared_ptr<ComponentModule> module;
1196     c2_status_t res = findComponent(name, &module);
1197     if (res == C2_OK) {
1198         // TODO: get a unique node ID
1199         res = module->createInterface(0, interface);
1200     }
1201     return res;
1202 }
1203 
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const1204 c2_status_t C2PlatformComponentStore::querySupportedParams_nb(
1205         std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
1206     return mInterface.querySupportedParams(params);
1207 }
1208 
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const1209 c2_status_t C2PlatformComponentStore::querySupportedValues_sm(
1210         std::vector<C2FieldSupportedValuesQuery> &fields) const {
1211     return mInterface.querySupportedValues(fields, C2_MAY_BLOCK);
1212 }
1213 
getName() const1214 C2String C2PlatformComponentStore::getName() const {
1215     return "android.componentStore.platform";
1216 }
1217 
getParamReflector() const1218 std::shared_ptr<C2ParamReflector> C2PlatformComponentStore::getParamReflector() const {
1219     return mReflector;
1220 }
1221 
GetCodec2PlatformComponentStore()1222 std::shared_ptr<C2ComponentStore> GetCodec2PlatformComponentStore() {
1223     static std::mutex mutex;
1224     static std::weak_ptr<C2ComponentStore> platformStore;
1225     std::lock_guard<std::mutex> lock(mutex);
1226     std::shared_ptr<C2ComponentStore> store = platformStore.lock();
1227     if (store == nullptr) {
1228         store = std::make_shared<C2PlatformComponentStore>();
1229         platformStore = store;
1230     }
1231     return store;
1232 }
1233 
1234 // For testing only
GetTestComponentStore(std::vector<std::tuple<C2String,C2ComponentFactory::CreateCodec2FactoryFunc,C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs)1235 std::shared_ptr<C2ComponentStore> GetTestComponentStore(
1236         std::vector<std::tuple<C2String,
1237         C2ComponentFactory::CreateCodec2FactoryFunc,
1238         C2ComponentFactory::DestroyCodec2FactoryFunc>> funcs) {
1239     return std::shared_ptr<C2ComponentStore>(new C2PlatformComponentStore(funcs));
1240 }
1241 } // namespace android
1242