xref: /aosp_15_r20/frameworks/av/services/audioflinger/afutils/AllocatorFactory.h (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2 **
3 ** Copyright 2022, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include <mediautils/SharedMemoryAllocator.h>
19 
20 #pragma once
21 
22 // TODO how do we appropriately restrict visibility of this header?
23 // It should only be included in AudioFlinger.h
24 // We will make everything internal linkage for now.
25 namespace android {
26 namespace AllocatorFactory {
27 namespace {
28 // TODO make sure these are appropriate
29 constexpr inline size_t MAX_MEMORY_SIZE = 1024 * 1024 * 100;                  // 100 MiB
30 constexpr inline size_t DED_SIZE = (MAX_MEMORY_SIZE * 4) / 10;                // 40 MiB
31 constexpr inline size_t SHARED_SIZE = MAX_MEMORY_SIZE - DED_SIZE;             // 60 MiB
32 constexpr inline size_t SHARED_SIZE_LARGE = (SHARED_SIZE * 4) / 6;            // 40 MiB
33 constexpr inline size_t SHARED_SIZE_SMALL = SHARED_SIZE - SHARED_SIZE_LARGE;  // 20 MiB
34 constexpr inline size_t SMALL_THRESHOLD = 1024 * 40;                          // 40 KiB
35 
36 template <typename Policy>
getSharedPool()37 inline auto getSharedPool() {
38     using namespace mediautils;
39     return std::make_shared<LockedAllocator<PolicyAllocator<MemoryHeapBaseAllocator, Policy>>>();
40 }
41 
42 // The following pools are global but lazy initialized. Stored in shared_ptr since they are
43 // referred by clients, but they could also be leaked.
44 
45 // Pool from which every client gets their dedicated, exclusive quota.
getDedicated()46 inline auto getDedicated() {
47     using namespace mediautils;
48     static const auto allocator = getSharedPool<SizePolicy<DED_SIZE>>();
49     return allocator;
50 }
51 
52 // Pool from which clients with large allocation sizes can fall back to when their dedicated
53 // allocation is surpassed. More likely to fill.
getSharedLarge()54 inline auto getSharedLarge() {
55     using namespace mediautils;
56     static const auto allocator = getSharedPool<SizePolicy<SHARED_SIZE_LARGE>>();
57     return allocator;
58 }
59 
60 // Pool from which clients with reasonable allocation sizes can fall back to when
61 // their dedicated allocation is surpassed, so that small buffer clients are always served.
getSharedSmall()62 inline auto getSharedSmall() {
63     using namespace mediautils;
64     static const auto allocator =
65             getSharedPool<SizePolicy<SHARED_SIZE_SMALL, 0, SMALL_THRESHOLD>>();
66     return allocator;
67 }
68 
69 template <typename Policy, typename Allocator>
wrapWithPolicySnooping(Allocator allocator,std::string_view name)70 inline auto wrapWithPolicySnooping(Allocator allocator, std::string_view name) {
71     using namespace mediautils;
72     return SnoopingAllocator{PolicyAllocator{IndirectAllocator{allocator}, Policy{}}, name};
73 }
74 
75 // A reasonable upper bound on how many clients we expect, and how many pieces to slice
76 // the dedicate pool.
77 constexpr inline size_t CLIENT_BOUND = 32;
78 // Maximum amount of shared pools a single client can take (50%).
79 constexpr inline size_t ADV_THRESHOLD_INV = 2;
80 
getClientAllocator()81 inline auto getClientAllocator() {
82     using namespace mediautils;
83     const auto makeDedPool = []() {
84         return wrapWithPolicySnooping<SizePolicy<DED_SIZE / CLIENT_BOUND>>(getDedicated(),
85                                                                            "Dedicated Pool");
86     };
87     const auto makeLargeShared = []() {
88         return wrapWithPolicySnooping<SizePolicy<SHARED_SIZE_LARGE / ADV_THRESHOLD_INV>>(
89                 getSharedLarge(), "Large Shared");
90     };
91     const auto makeSmallShared = []() {
92         return wrapWithPolicySnooping<SizePolicy<SHARED_SIZE_SMALL / ADV_THRESHOLD_INV>>(
93                 getSharedSmall(), "Small Shared");
94     };
95 
96     return ScopedAllocator{std::make_shared<
97             FallbackAllocator<decltype(makeDedPool()),
98                               decltype(FallbackAllocator(makeLargeShared(), makeSmallShared()))>>(
99             makeDedPool(), FallbackAllocator{makeLargeShared(), makeSmallShared()})};
100 }
101 
102 using ClientAllocator = decltype(getClientAllocator());
103 }  // namespace
104 }  // namespace AllocatorFactory
105 }  // namespace android
106