• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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_NDEBUG 0
18 #define LOG_TAG "ApexCodecsLazy"
19 #include <log/log.h>
20 
21 #include <mutex>
22 
23 #include <dlfcn.h>
24 
25 #include <android-base/no_destructor.h>
26 #include <apex/ApexCodecs.h>
27 #include <utils/RWLock.h>
28 
29 using android::RWLock;
30 
31 namespace {
32 
33 // This file provides a lazy interface to libcom.android.media.swcodec.apexcodecs.so
34 // to address early boot dependencies.
35 
36 // Method pointers to libcom.android.media.swcodec.apexcodecs methods are held in an array
37 // which simplifies checking all pointers are initialized.
38 enum MethodIndex {
39     k_ApexCodec_Buffer_clear,
40     k_ApexCodec_Buffer_create,
41     k_ApexCodec_Buffer_destroy,
42     k_ApexCodec_Buffer_getBufferInfo,
43     k_ApexCodec_Buffer_getConfigUpdates,
44     k_ApexCodec_Buffer_getGraphicBuffer,
45     k_ApexCodec_Buffer_getLinearBuffer,
46     k_ApexCodec_Buffer_getType,
47     k_ApexCodec_Buffer_setBufferInfo,
48     k_ApexCodec_Buffer_setConfigUpdates,
49     k_ApexCodec_Buffer_setGraphicBuffer,
50     k_ApexCodec_Buffer_setLinearBuffer,
51     k_ApexCodec_Component_create,
52     k_ApexCodec_Component_destroy,
53     k_ApexCodec_Component_flush,
54     k_ApexCodec_Component_getConfigurable,
55     k_ApexCodec_Component_process,
56     k_ApexCodec_Component_reset,
57     k_ApexCodec_Component_start,
58     k_ApexCodec_Configurable_config,
59     k_ApexCodec_Configurable_query,
60     k_ApexCodec_Configurable_querySupportedParams,
61     k_ApexCodec_Configurable_querySupportedValues,
62     k_ApexCodec_GetComponentStore,
63     k_ApexCodec_ParamDescriptors_destroy,
64     k_ApexCodec_ParamDescriptors_getDescriptor,
65     k_ApexCodec_ParamDescriptors_getIndices,
66     k_ApexCodec_SettingResults_destroy,
67     k_ApexCodec_SettingResults_getResultAtIndex,
68     k_ApexCodec_SupportedValues_destroy,
69     k_ApexCodec_SupportedValues_getTypeAndValues,
70     k_ApexCodec_Traits_get,
71 
72     // Marker for count of methods
73     k_MethodCount
74 };
75 
76 class ApexCodecsLazyLoader {
77 public:
78     ApexCodecsLazyLoader() = default;
79 
Get()80     static ApexCodecsLazyLoader &Get() {
81         static ::android::base::NoDestructor<ApexCodecsLazyLoader> sLoader;
82         return *sLoader;
83     }
84 
getMethodAt(enum MethodIndex index)85     void *getMethodAt(enum MethodIndex index) {
86         RWLock::AutoRLock l(mLock);
87         if (mInit) {
88             return mMethods[index];
89         } else {
90             mLock.unlock();
91             if (!init()) {
92                 return nullptr;
93             }
94             mLock.readLock();
95             return mMethods[index];
96         }
97     }
98 
99 private:
LoadApexCodecs(int dlopen_flags)100     static void* LoadApexCodecs(int dlopen_flags) {
101         return dlopen("libcom.android.media.swcodec.apexcodecs.so", dlopen_flags);
102     }
103 
104     // Initialization and symbol binding.
bindSymbol_l(void * handle,const char * name,enum MethodIndex index)105     void bindSymbol_l(void* handle, const char* name, enum MethodIndex index) {
106         void* symbol = dlsym(handle, name);
107         ALOGI_IF(symbol == nullptr,
108                 "Failed to find symbol '%s' in libcom.android.media.swcodec.apexcodecs.so: %s",
109                  name, dlerror());
110         mMethods[index] = symbol;
111     }
112 
init()113     bool init() {
114         {
115             RWLock::AutoRLock l(mLock);
116             if (mInit) {
117                 return true;
118             }
119         }
120         void* handle = LoadApexCodecs(RTLD_NOW);
121         if (handle == nullptr) {
122             ALOGI("Failed to load libcom.android.media.swcodec.apexcodecs.so: %s", dlerror());
123             return false;
124         }
125 
126         RWLock::AutoWLock l(mLock);
127 #undef BIND_SYMBOL
128 #define BIND_SYMBOL(name) bindSymbol_l(handle, #name, k_##name);
129         BIND_SYMBOL(ApexCodec_Buffer_clear);
130         BIND_SYMBOL(ApexCodec_Buffer_create);
131         BIND_SYMBOL(ApexCodec_Buffer_destroy);
132         BIND_SYMBOL(ApexCodec_Buffer_getBufferInfo);
133         BIND_SYMBOL(ApexCodec_Buffer_getConfigUpdates);
134         BIND_SYMBOL(ApexCodec_Buffer_getGraphicBuffer);
135         BIND_SYMBOL(ApexCodec_Buffer_getLinearBuffer);
136         BIND_SYMBOL(ApexCodec_Buffer_getType);
137         BIND_SYMBOL(ApexCodec_Buffer_setConfigUpdates);
138         BIND_SYMBOL(ApexCodec_Buffer_setGraphicBuffer);
139         BIND_SYMBOL(ApexCodec_Buffer_setLinearBuffer);
140         BIND_SYMBOL(ApexCodec_Component_create);
141         BIND_SYMBOL(ApexCodec_Component_destroy);
142         BIND_SYMBOL(ApexCodec_Component_flush);
143         BIND_SYMBOL(ApexCodec_Component_getConfigurable);
144         BIND_SYMBOL(ApexCodec_Component_process);
145         BIND_SYMBOL(ApexCodec_Component_reset);
146         BIND_SYMBOL(ApexCodec_Component_start);
147         BIND_SYMBOL(ApexCodec_Configurable_config);
148         BIND_SYMBOL(ApexCodec_Configurable_query);
149         BIND_SYMBOL(ApexCodec_Configurable_querySupportedParams);
150         BIND_SYMBOL(ApexCodec_Configurable_querySupportedValues);
151         BIND_SYMBOL(ApexCodec_GetComponentStore);
152         BIND_SYMBOL(ApexCodec_ParamDescriptors_destroy);
153         BIND_SYMBOL(ApexCodec_ParamDescriptors_getDescriptor);
154         BIND_SYMBOL(ApexCodec_ParamDescriptors_getIndices);
155         BIND_SYMBOL(ApexCodec_SettingResults_destroy);
156         BIND_SYMBOL(ApexCodec_SettingResults_getResultAtIndex);
157         BIND_SYMBOL(ApexCodec_SupportedValues_destroy);
158         BIND_SYMBOL(ApexCodec_SupportedValues_getTypeAndValues);
159         BIND_SYMBOL(ApexCodec_Traits_get);
160 #undef BIND_SYMBOL
161 
162         // Check every symbol is bound.
163         for (int i = 0; i < k_MethodCount; ++i) {
164             if (mMethods[i] == nullptr) {
165                 ALOGI("Uninitialized method in "
166                       "libcom.android.media.swcodec.apexcodecs_lazy at index: %d", i);
167                 return false;
168             }
169         }
170         mInit = true;
171         return true;
172     }
173 
174     RWLock mLock;
175     // Table of methods pointers in libcom.android.media.swcodec.apexcodecs APIs.
176     void* mMethods[k_MethodCount];
177     bool mInit{false};
178 };
179 
180 }  // anonymous namespace
181 
182 #define INVOKE_METHOD(name, returnIfNull, args...)                          \
183     do {                                                                    \
184         void* method = ApexCodecsLazyLoader::Get().getMethodAt(k_##name);   \
185         if (!method) return (returnIfNull);                                 \
186         return reinterpret_cast<decltype(&name)>(method)(args);             \
187     } while (0)
188 
189 //
190 // Forwarding for methods in ApexCodecs.h.
191 //
192 
ApexCodec_GetComponentStore()193 ApexCodec_ComponentStore *ApexCodec_GetComponentStore() {
194     INVOKE_METHOD(ApexCodec_GetComponentStore, nullptr);
195 }
196 
ApexCodec_Traits_get(ApexCodec_ComponentStore * store,size_t index)197 ApexCodec_ComponentTraits *ApexCodec_Traits_get(
198         ApexCodec_ComponentStore *store, size_t index) {
199     INVOKE_METHOD(ApexCodec_Traits_get, nullptr, store, index);
200 }
201 
ApexCodec_Buffer_create()202 ApexCodec_Buffer *ApexCodec_Buffer_create() {
203     INVOKE_METHOD(ApexCodec_Buffer_create, nullptr);
204 }
205 
ApexCodec_Buffer_destroy(ApexCodec_Buffer * buffer)206 void ApexCodec_Buffer_destroy(ApexCodec_Buffer *buffer) {
207     INVOKE_METHOD(ApexCodec_Buffer_destroy, void(), buffer);
208 }
209 
ApexCodec_Buffer_clear(ApexCodec_Buffer * buffer)210 void ApexCodec_Buffer_clear(ApexCodec_Buffer *buffer) {
211     INVOKE_METHOD(ApexCodec_Buffer_clear, void(), buffer);
212 }
213 
ApexCodec_Buffer_getType(ApexCodec_Buffer * buffer)214 ApexCodec_BufferType ApexCodec_Buffer_getType(ApexCodec_Buffer *buffer) {
215     INVOKE_METHOD(ApexCodec_Buffer_getType, APEXCODEC_BUFFER_TYPE_EMPTY, buffer);
216 }
217 
ApexCodec_Buffer_setBufferInfo(ApexCodec_Buffer * _Nonnull buffer,ApexCodec_BufferFlags flags,uint64_t frameIndex,uint64_t timestampUs)218 void ApexCodec_Buffer_setBufferInfo(
219         ApexCodec_Buffer *_Nonnull buffer,
220         ApexCodec_BufferFlags flags,
221         uint64_t frameIndex,
222         uint64_t timestampUs) {
223     INVOKE_METHOD(ApexCodec_Buffer_setBufferInfo, void(),
224                   buffer, flags, frameIndex, timestampUs);
225 }
226 
ApexCodec_Buffer_setLinearBuffer(ApexCodec_Buffer * buffer,const ApexCodec_LinearBuffer * linearBuffer)227 ApexCodec_Status ApexCodec_Buffer_setLinearBuffer(
228         ApexCodec_Buffer *buffer,
229         const ApexCodec_LinearBuffer *linearBuffer) {
230     INVOKE_METHOD(ApexCodec_Buffer_setLinearBuffer, APEXCODEC_STATUS_OMITTED,
231                   buffer, linearBuffer);
232 }
233 
ApexCodec_Buffer_setGraphicBuffer(ApexCodec_Buffer * buffer,AHardwareBuffer * graphicBuffer)234 ApexCodec_Status ApexCodec_Buffer_setGraphicBuffer(
235         ApexCodec_Buffer *buffer,
236         AHardwareBuffer *graphicBuffer) {
237     INVOKE_METHOD(ApexCodec_Buffer_setGraphicBuffer, APEXCODEC_STATUS_OMITTED,
238                   buffer, graphicBuffer);
239 }
240 
ApexCodec_Buffer_setConfigUpdates(ApexCodec_Buffer * buffer,const ApexCodec_LinearBuffer * configUpdates)241 ApexCodec_Status ApexCodec_Buffer_setConfigUpdates(
242         ApexCodec_Buffer *buffer,
243         const ApexCodec_LinearBuffer *configUpdates) {
244     INVOKE_METHOD(ApexCodec_Buffer_setConfigUpdates, APEXCODEC_STATUS_OMITTED,
245                   buffer, configUpdates);
246 }
247 
ApexCodec_Buffer_getBufferInfo(ApexCodec_Buffer * buffer,ApexCodec_BufferFlags * outFlags,uint64_t * outFrameIndex,uint64_t * outTimestampUs)248 ApexCodec_Status ApexCodec_Buffer_getBufferInfo(
249         ApexCodec_Buffer *buffer,
250         ApexCodec_BufferFlags *outFlags,
251         uint64_t *outFrameIndex,
252         uint64_t *outTimestampUs) {
253     INVOKE_METHOD(ApexCodec_Buffer_getBufferInfo, APEXCODEC_STATUS_OMITTED,
254                   buffer, outFlags, outFrameIndex, outTimestampUs);
255 }
256 
ApexCodec_Buffer_getLinearBuffer(ApexCodec_Buffer * buffer,ApexCodec_LinearBuffer * outLinearBuffer)257 ApexCodec_Status ApexCodec_Buffer_getLinearBuffer(
258         ApexCodec_Buffer *buffer,
259         ApexCodec_LinearBuffer *outLinearBuffer) {
260     INVOKE_METHOD(ApexCodec_Buffer_getLinearBuffer, APEXCODEC_STATUS_OMITTED,
261                   buffer, outLinearBuffer);
262 }
263 
ApexCodec_Buffer_getGraphicBuffer(ApexCodec_Buffer * buffer,AHardwareBuffer ** outGraphicBuffer)264 ApexCodec_Status ApexCodec_Buffer_getGraphicBuffer(
265         ApexCodec_Buffer *buffer,
266         AHardwareBuffer **outGraphicBuffer) {
267     INVOKE_METHOD(ApexCodec_Buffer_getGraphicBuffer, APEXCODEC_STATUS_OMITTED,
268                   buffer, outGraphicBuffer);
269 }
270 
ApexCodec_Buffer_getConfigUpdates(ApexCodec_Buffer * buffer,ApexCodec_LinearBuffer * outConfigUpdates,bool * outOwnedByClient)271 ApexCodec_Status ApexCodec_Buffer_getConfigUpdates(
272         ApexCodec_Buffer *buffer,
273         ApexCodec_LinearBuffer *outConfigUpdates,
274         bool *outOwnedByClient) {
275     INVOKE_METHOD(ApexCodec_Buffer_getConfigUpdates, APEXCODEC_STATUS_OMITTED,
276                   buffer, outConfigUpdates, outOwnedByClient);
277 }
ApexCodec_Component_create(ApexCodec_ComponentStore * store,const char * name,ApexCodec_Component ** comp)278 ApexCodec_Status ApexCodec_Component_create(
279         ApexCodec_ComponentStore *store, const char *name, ApexCodec_Component **comp) {
280     INVOKE_METHOD(ApexCodec_Component_create, APEXCODEC_STATUS_OMITTED, store, name, comp);
281 }
282 
ApexCodec_Component_destroy(ApexCodec_Component * comp)283 void ApexCodec_Component_destroy(ApexCodec_Component *comp) {
284     INVOKE_METHOD(ApexCodec_Component_destroy, void(), comp);
285 }
286 
ApexCodec_Component_start(ApexCodec_Component * comp)287 ApexCodec_Status ApexCodec_Component_start(ApexCodec_Component *comp) {
288     INVOKE_METHOD(ApexCodec_Component_start, APEXCODEC_STATUS_OMITTED, comp);
289 }
290 
ApexCodec_Component_flush(ApexCodec_Component * comp)291 ApexCodec_Status ApexCodec_Component_flush(ApexCodec_Component *comp) {
292     INVOKE_METHOD(ApexCodec_Component_flush, APEXCODEC_STATUS_OMITTED, comp);
293 }
294 
ApexCodec_Component_reset(ApexCodec_Component * comp)295 ApexCodec_Status ApexCodec_Component_reset(ApexCodec_Component *comp) {
296     INVOKE_METHOD(ApexCodec_Component_reset, APEXCODEC_STATUS_OMITTED, comp);
297 }
298 
ApexCodec_Component_getConfigurable(ApexCodec_Component * comp)299 ApexCodec_Configurable *ApexCodec_Component_getConfigurable(
300         ApexCodec_Component *comp) {
301     INVOKE_METHOD(ApexCodec_Component_getConfigurable, nullptr, comp);
302 }
303 
ApexCodec_SupportedValues_getTypeAndValues(ApexCodec_SupportedValues * supportedValues,ApexCodec_SupportedValuesType * type,ApexCodec_SupportedValuesNumberType * numberType,ApexCodec_Value ** values,uint32_t * numValues)304 ApexCodec_Status ApexCodec_SupportedValues_getTypeAndValues(
305         ApexCodec_SupportedValues *supportedValues,
306         ApexCodec_SupportedValuesType *type,
307         ApexCodec_SupportedValuesNumberType *numberType,
308         ApexCodec_Value **values,
309         uint32_t *numValues) {
310     INVOKE_METHOD(ApexCodec_SupportedValues_getTypeAndValues, APEXCODEC_STATUS_OMITTED,
311                   supportedValues, type, numberType, values, numValues);
312 }
313 
ApexCodec_SupportedValues_destroy(ApexCodec_SupportedValues * values)314 void ApexCodec_SupportedValues_destroy(ApexCodec_SupportedValues *values) {
315     INVOKE_METHOD(ApexCodec_SupportedValues_destroy, void(), values);
316 }
317 
ApexCodec_SettingResults_getResultAtIndex(ApexCodec_SettingResults * results,size_t index,ApexCodec_SettingResultFailure * failure,ApexCodec_ParamFieldValues * field,ApexCodec_ParamFieldValues ** conflicts,size_t * numConflicts)318 ApexCodec_Status ApexCodec_SettingResults_getResultAtIndex(
319         ApexCodec_SettingResults *results,
320         size_t index,
321         ApexCodec_SettingResultFailure *failure,
322         ApexCodec_ParamFieldValues *field,
323         ApexCodec_ParamFieldValues **conflicts,
324         size_t *numConflicts) {
325     INVOKE_METHOD(ApexCodec_SettingResults_getResultAtIndex, APEXCODEC_STATUS_OMITTED,
326                   results, index, failure, field, conflicts, numConflicts);
327 }
328 
ApexCodec_SettingResults_destroy(ApexCodec_SettingResults * results)329 void ApexCodec_SettingResults_destroy(ApexCodec_SettingResults *results) {
330     INVOKE_METHOD(ApexCodec_SettingResults_destroy, void(), results);
331 }
332 
ApexCodec_Component_process(ApexCodec_Component * comp,const ApexCodec_Buffer * input,ApexCodec_Buffer * output,size_t * consumed,size_t * produced)333 ApexCodec_Status ApexCodec_Component_process(
334         ApexCodec_Component *comp,
335         const ApexCodec_Buffer *input,
336         ApexCodec_Buffer *output,
337         size_t *consumed,
338         size_t *produced) {
339     INVOKE_METHOD(ApexCodec_Component_process, APEXCODEC_STATUS_OMITTED,
340                   comp, input, output, consumed, produced);
341 }
342 
ApexCodec_Configurable_config(ApexCodec_Configurable * comp,ApexCodec_LinearBuffer * config,ApexCodec_SettingResults ** results)343 ApexCodec_Status ApexCodec_Configurable_config(
344         ApexCodec_Configurable *comp,
345         ApexCodec_LinearBuffer *config,
346         ApexCodec_SettingResults **results) {
347     INVOKE_METHOD(ApexCodec_Configurable_config, APEXCODEC_STATUS_OMITTED, comp, config, results);
348 }
349 
ApexCodec_Configurable_query(ApexCodec_Configurable * comp,uint32_t indices[],size_t numIndices,ApexCodec_LinearBuffer * config,size_t * writtenOrRequested)350 ApexCodec_Status ApexCodec_Configurable_query(
351         ApexCodec_Configurable *comp,
352         uint32_t indices[],
353         size_t numIndices,
354         ApexCodec_LinearBuffer *config,
355         size_t *writtenOrRequested) {
356     INVOKE_METHOD(ApexCodec_Configurable_query, APEXCODEC_STATUS_OMITTED,
357                   comp, indices, numIndices, config, writtenOrRequested);
358 }
359 
ApexCodec_ParamDescriptors_getIndices(ApexCodec_ParamDescriptors * descriptors,uint32_t ** indices,size_t * numIndices)360 ApexCodec_Status ApexCodec_ParamDescriptors_getIndices(
361         ApexCodec_ParamDescriptors *descriptors,
362         uint32_t **indices,
363         size_t *numIndices) {
364     INVOKE_METHOD(ApexCodec_ParamDescriptors_getIndices, APEXCODEC_STATUS_OMITTED,
365                   descriptors, indices, numIndices);
366 }
367 
ApexCodec_ParamDescriptors_getDescriptor(ApexCodec_ParamDescriptors * descriptors,uint32_t index,ApexCodec_ParamAttribute * attr,const char ** name,uint32_t ** dependencies,size_t * numDependencies)368 ApexCodec_Status ApexCodec_ParamDescriptors_getDescriptor(
369         ApexCodec_ParamDescriptors *descriptors,
370         uint32_t index,
371         ApexCodec_ParamAttribute *attr,
372         const char **name,
373         uint32_t **dependencies,
374         size_t *numDependencies) {
375     INVOKE_METHOD(ApexCodec_ParamDescriptors_getDescriptor, APEXCODEC_STATUS_OMITTED,
376                   descriptors, index, attr, name, dependencies, numDependencies);
377 }
378 
ApexCodec_ParamDescriptors_destroy(ApexCodec_ParamDescriptors * descriptors)379 void ApexCodec_ParamDescriptors_destroy(
380         ApexCodec_ParamDescriptors *descriptors) {
381     INVOKE_METHOD(ApexCodec_ParamDescriptors_destroy, void(), descriptors);
382 }
383 
ApexCodec_Configurable_querySupportedParams(ApexCodec_Configurable * comp,ApexCodec_ParamDescriptors ** descriptors)384 ApexCodec_Status ApexCodec_Configurable_querySupportedParams(
385         ApexCodec_Configurable *comp,
386         ApexCodec_ParamDescriptors **descriptors) {
387     INVOKE_METHOD(ApexCodec_Configurable_querySupportedParams, APEXCODEC_STATUS_OMITTED,
388                   comp, descriptors);
389 }
390 
ApexCodec_Configurable_querySupportedValues(ApexCodec_Configurable * comp,ApexCodec_SupportedValuesQuery * queries,size_t numQueries)391 ApexCodec_Status ApexCodec_Configurable_querySupportedValues(
392         ApexCodec_Configurable *comp,
393         ApexCodec_SupportedValuesQuery *queries,
394         size_t numQueries) {
395     INVOKE_METHOD(ApexCodec_Configurable_querySupportedValues, APEXCODEC_STATUS_OMITTED,
396                   comp, queries, numQueries);
397 }
398