codec2: switch perferred linear allocator type by pool mask

The preferred linear buffer allocator could be switched between Gralloc BLOB
and ION by runtime property "debug.stagefright.c2-poolmask". ION should be
chosen as fallback allocator type if the pool mask property doesn't enable
the bit of Gralloc BLOB.

Bug: 143180475
Test: make libcodec2_vndk
Test: make libsfplugin_ccodec
Change-Id: I56fcca7f03660bca63a4974aa0f78a6d2a40e585
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 5b2bd7b..03810e9 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -18,6 +18,7 @@
 #define LOG_NDEBUG 0
 #include <utils/Log.h>
 
+#include <C2AllocatorBlob.h>
 #include <C2AllocatorGralloc.h>
 #include <C2AllocatorIon.h>
 #include <C2BufferPriv.h>
@@ -26,6 +27,7 @@
 #include <C2Config.h>
 #include <C2PlatformStorePluginLoader.h>
 #include <C2PlatformSupport.h>
+#include <cutils/properties.h>
 #include <util/C2InterfaceHelper.h>
 
 #include <dlfcn.h>
@@ -71,6 +73,9 @@
     ~C2PlatformAllocatorStoreImpl() override = default;
 
 private:
+    /// returns a shared-singleton blob allocator (gralloc-backed)
+    std::shared_ptr<C2Allocator> fetchBlobAllocator();
+
     /// returns a shared-singleton ion allocator
     std::shared_ptr<C2Allocator> fetchIonAllocator();
 
@@ -93,10 +98,12 @@
 c2_status_t C2PlatformAllocatorStoreImpl::fetchAllocator(
         id_t id, std::shared_ptr<C2Allocator> *const allocator) {
     allocator->reset();
+    if (id == C2AllocatorStore::DEFAULT_LINEAR) {
+        id = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
+    }
     switch (id) {
     // TODO: should we implement a generic registry for all, and use that?
     case C2PlatformAllocatorStore::ION:
-    case C2AllocatorStore::DEFAULT_LINEAR:
         *allocator = fetchIonAllocator();
         break;
 
@@ -109,6 +116,10 @@
         *allocator = fetchBufferQueueAllocator();
         break;
 
+    case C2PlatformAllocatorStore::BLOB:
+        *allocator = fetchBlobAllocator();
+        break;
+
     default:
         // Try to create allocator from platform store plugins.
         c2_status_t res =
@@ -218,6 +229,18 @@
     return allocator;
 }
 
+std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchBlobAllocator() {
+    static std::mutex mutex;
+    static std::weak_ptr<C2Allocator> blobAllocator;
+    std::lock_guard<std::mutex> lock(mutex);
+    std::shared_ptr<C2Allocator> allocator = blobAllocator.lock();
+    if (allocator == nullptr) {
+        allocator = std::make_shared<C2AllocatorBlob>(C2PlatformAllocatorStore::BLOB);
+        blobAllocator = allocator;
+    }
+    return allocator;
+}
+
 std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchGrallocAllocator() {
     static std::mutex mutex;
     static std::weak_ptr<C2Allocator> grallocAllocator;
@@ -288,6 +311,18 @@
     return gPreferredComponentStore ? gPreferredComponentStore : GetCodec2PlatformComponentStore();
 }
 
+int GetCodec2PoolMask() {
+    return property_get_int32(
+            "debug.stagefright.c2-poolmask",
+            1 << C2PlatformAllocatorStore::ION |
+            1 << C2PlatformAllocatorStore::BUFFERQUEUE);
+}
+
+C2PlatformAllocatorStore::id_t GetPreferredLinearAllocatorId(int poolMask) {
+    return ((poolMask >> C2PlatformAllocatorStore::BLOB) & 1) ? C2PlatformAllocatorStore::BLOB
+                                                              : C2PlatformAllocatorStore::ION;
+}
+
 namespace {
 
 class _C2BlockPoolCache {
@@ -304,11 +339,25 @@
         std::shared_ptr<C2Allocator> allocator;
         c2_status_t res = C2_NOT_FOUND;
 
+        if (allocatorId == C2AllocatorStore::DEFAULT_LINEAR) {
+            allocatorId = GetPreferredLinearAllocatorId(GetCodec2PoolMask());
+        }
         switch(allocatorId) {
             case C2PlatformAllocatorStore::ION:
-            case C2AllocatorStore::DEFAULT_LINEAR:
                 res = allocatorStore->fetchAllocator(
-                        C2AllocatorStore::DEFAULT_LINEAR, &allocator);
+                        C2PlatformAllocatorStore::ION, &allocator);
+                if (res == C2_OK) {
+                    std::shared_ptr<C2BlockPool> ptr =
+                            std::make_shared<C2PooledBlockPool>(
+                                    allocator, poolId);
+                    *pool = ptr;
+                    mBlockPools[poolId] = ptr;
+                    mComponents[poolId] = component;
+                }
+                break;
+            case C2PlatformAllocatorStore::BLOB:
+                res = allocatorStore->fetchAllocator(
+                        C2PlatformAllocatorStore::BLOB, &allocator);
                 if (res == C2_OK) {
                     std::shared_ptr<C2BlockPool> ptr =
                             std::make_shared<C2PooledBlockPool>(