1/*
2 * Copyright (C) 2010 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/* OpenSL ES private and global functions not associated with an interface or class */
18
19#include "sles_allinclusive.h"
20
21
22/** \brief Return true if the specified interface exists and has been initialized for this object.
23 *  Returns false if the class does not support this kind of interface, or the class supports the
24 *  interface but this particular object has not had the interface exposed at object creation time
25 *  or by DynamicInterface::AddInterface. Note that the return value is not affected by whether
26 *  the application has requested access to the interface with Object::GetInterface. Assumes on
27 *  entry that the object is locked for either shared or exclusive access.
28 */
29
30bool IsInterfaceInitialized(IObject *thiz, unsigned MPH)
31{
32    assert(NULL != thiz);
33    assert( /* (MPH_MIN <= MPH) && */ (MPH < (unsigned) MPH_MAX));
34    const ClassTable *clazz = thiz->mClass;
35    assert(NULL != clazz);
36    int index;
37    if (0 > (index = clazz->mMPH_to_index[MPH])) {
38        return false;
39    }
40    assert(MAX_INDEX >= clazz->mInterfaceCount);
41    assert(clazz->mInterfaceCount > (unsigned) index);
42    switch (thiz->mInterfaceStates[index]) {
43    case INTERFACE_EXPOSED:
44    case INTERFACE_ADDED:
45        return true;
46    default:
47        return false;
48    }
49}
50
51
52/** \brief Map an IObject to it's "object ID" (which is really a class ID) */
53
54SLuint32 IObjectToObjectID(IObject *thiz)
55{
56    assert(NULL != thiz);
57    // Note this returns the OpenSL ES object ID in preference to the OpenMAX AL if both available
58    const ClassTable *clazz = thiz->mClass;
59    assert(NULL != clazz);
60    SLuint32 id = clazz->mSLObjectID;
61    if (!id) {
62        id = clazz->mXAObjectID;
63    }
64    return id;
65}
66
67
68/** \brief Acquire a strong reference to an object.
69 *  Check that object has the specified "object ID" (which is really a class ID) and is in the
70 *  realized state.  If so, then acquire a strong reference to it and return true.
71 *  Otherwise return false.
72 */
73
74SLresult AcquireStrongRef(IObject *object, SLuint32 expectedObjectID)
75{
76    if (NULL == object) {
77        return SL_RESULT_PARAMETER_INVALID;
78    }
79    // NTH additional validity checks on address here
80    SLresult result;
81    object_lock_exclusive(object);
82    SLuint32 actualObjectID = IObjectToObjectID(object);
83    if (expectedObjectID != actualObjectID) {
84        SL_LOGE("object %p has object ID %u but expected %u", object, actualObjectID,
85            expectedObjectID);
86        result = SL_RESULT_PARAMETER_INVALID;
87    } else if (SL_OBJECT_STATE_REALIZED != object->mState) {
88        SL_LOGE("object %p with object ID %u is not realized", object, actualObjectID);
89        result = SL_RESULT_PRECONDITIONS_VIOLATED;
90    } else {
91        ++object->mStrongRefCount;
92        result = SL_RESULT_SUCCESS;
93    }
94    object_unlock_exclusive(object);
95    return result;
96}
97
98
99/** \brief Release a strong reference to an object.
100 *  Entry condition: the object is locked.
101 *  Exit condition: the object is unlocked.
102 *  Finishes the destroy if needed.
103 */
104
105void ReleaseStrongRefAndUnlockExclusive(IObject *object)
106{
107#ifdef USE_DEBUG
108    assert(pthread_equal(pthread_self(), object->mOwner));
109#endif
110    assert(0 < object->mStrongRefCount);
111    if ((0 == --object->mStrongRefCount) && (SL_OBJECT_STATE_DESTROYING == object->mState)) {
112        // FIXME do the destroy here - merge with IDestroy
113        // but can't do this until we move Destroy to the sync thread
114        // as Destroy is now a blocking operation, and to avoid a race
115    } else {
116        object_unlock_exclusive(object);
117    }
118}
119
120
121/** \brief Release a strong reference to an object.
122 *  Entry condition: the object is unlocked.
123 *  Exit condition: the object is unlocked.
124 *  Finishes the destroy if needed.
125 */
126
127void ReleaseStrongRef(IObject *object)
128{
129    assert(NULL != object);
130    object_lock_exclusive(object);
131    ReleaseStrongRefAndUnlockExclusive(object);
132}
133
134
135/** \brief Convert POSIX pthread error code to OpenSL ES result code */
136
137SLresult err_to_result(int err)
138{
139    if (EAGAIN == err || ENOMEM == err) {
140        return SL_RESULT_RESOURCE_ERROR;
141    }
142    if (0 != err) {
143        return SL_RESULT_INTERNAL_ERROR;
144    }
145    return SL_RESULT_SUCCESS;
146}
147
148
149/** \brief Check the interface IDs passed into a Create operation */
150
151SLresult checkInterfaces(const ClassTable *clazz, SLuint32 numInterfaces,
152    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired,
153    unsigned *pExposedMask, unsigned *pRequiredMask)
154{
155    assert(NULL != clazz && NULL != pExposedMask);
156    // Initially no interfaces are exposed
157    unsigned exposedMask = 0;
158    unsigned requiredMask = 0;
159    const struct iid_vtable *interfaces = clazz->mInterfaces;
160    SLuint32 interfaceCount = clazz->mInterfaceCount;
161    SLuint32 i;
162    // Expose all implicit interfaces
163    for (i = 0; i < interfaceCount; ++i) {
164        switch (interfaces[i].mInterface) {
165        case INTERFACE_IMPLICIT:
166        case INTERFACE_IMPLICIT_PREREALIZE:
167            // there must be an initialization hook present
168            if (NULL != MPH_init_table[interfaces[i].mMPH].mInit) {
169                exposedMask |= 1 << i;
170            }
171            break;
172        case INTERFACE_EXPLICIT:
173        case INTERFACE_DYNAMIC:
174        case INTERFACE_UNAVAILABLE:
175        case INTERFACE_EXPLICIT_PREREALIZE:
176            break;
177        default:
178            assert(false);
179            break;
180        }
181    }
182    if (0 < numInterfaces) {
183        if (NULL == pInterfaceIds || NULL == pInterfaceRequired) {
184            return SL_RESULT_PARAMETER_INVALID;
185        }
186        bool anyRequiredButUnsupported = false;
187        // Loop for each requested interface
188        for (i = 0; i < numInterfaces; ++i) {
189            SLInterfaceID iid = pInterfaceIds[i];
190            if (NULL == iid) {
191                return SL_RESULT_PARAMETER_INVALID;
192            }
193            SLboolean isRequired = pInterfaceRequired[i];
194            int MPH, index;
195            if ((0 > (MPH = IID_to_MPH(iid))) ||
196                    // there must be an initialization hook present
197                    (NULL == MPH_init_table[MPH].mInit) ||
198                    (0 > (index = clazz->mMPH_to_index[MPH])) ||
199                    (INTERFACE_UNAVAILABLE == interfaces[index].mInterface)) {
200                // Here if interface was not found, or is not available for this object type
201                if (isRequired) {
202                    // Application said it required the interface, so give up
203                    SL_LOGE("class %s interface %u required but unavailable MPH=%d",
204                            clazz->mName, i, MPH);
205                    anyRequiredButUnsupported = true;
206                }
207                // Application said it didn't really need the interface, so ignore with warning
208                SL_LOGW("class %s interface %u requested but unavailable MPH=%d",
209                        clazz->mName, i, MPH);
210                continue;
211            }
212            if (isRequired) {
213                requiredMask |= (1 << index);
214            }
215            // The requested interface was both found and available, so expose it
216            exposedMask |= (1 << index);
217            // Note that we ignore duplicate requests, including equal and aliased IDs
218        }
219        if (anyRequiredButUnsupported) {
220            return SL_RESULT_FEATURE_UNSUPPORTED;
221        }
222    }
223    *pExposedMask = exposedMask;
224    if (NULL != pRequiredMask) {
225        *pRequiredMask = requiredMask;
226    }
227    return SL_RESULT_SUCCESS;
228}
229
230
231/* Interface initialization hooks */
232
233extern void
234    I3DCommit_init(void *),
235    I3DDoppler_init(void *),
236    I3DGrouping_init(void *),
237    I3DLocation_init(void *),
238    I3DMacroscopic_init(void *),
239    I3DSource_init(void *),
240    IAndroidAcousticEchoCancellation_init(void *),
241    IAndroidAutomaticGainControl_init(void *),
242    IAndroidConfiguration_init(void *),
243    IAndroidEffect_init(void *),
244    IAndroidEffectCapabilities_init(void *),
245    IAndroidEffectSend_init(void *),
246    IAndroidBufferQueue_init(void *),
247    IAudioDecoderCapabilities_init(void *),
248    IAudioEncoder_init(void *),
249    IAudioEncoderCapabilities_init(void *),
250    IAudioIODeviceCapabilities_init(void *),
251    IBassBoost_init(void *),
252    IBufferQueue_init(void *),
253    IDeviceVolume_init(void *),
254    IDynamicInterfaceManagement_init(void *),
255    IDynamicSource_init(void *),
256    IEffectSend_init(void *),
257    IEngine_init(void *),
258    IEngineCapabilities_init(void *),
259    IEnvironmentalReverb_init(void *),
260    IEqualizer_init(void *),
261    ILEDArray_init(void *),
262    IMIDIMessage_init(void *),
263    IMIDIMuteSolo_init(void *),
264    IMIDITempo_init(void *),
265    IMIDITime_init(void *),
266    IMetadataExtraction_init(void *),
267    IMetadataTraversal_init(void *),
268    IMuteSolo_init(void *),
269    IAndroidNoiseSuppression_init(void *),
270    IObject_init(void *),
271    IOutputMix_init(void *),
272    IOutputMixExt_init(void *),
273    IPitch_init(void *),
274    IPlay_init(void *),
275    IPlaybackRate_init(void *),
276    IPrefetchStatus_init(void *),
277    IPresetReverb_init(void *),
278    IRatePitch_init(void *),
279    IRecord_init(void *),
280    ISeek_init(void *),
281    IThreadSync_init(void *),
282    IVibra_init(void *),
283    IVirtualizer_init(void *),
284    IVisualization_init(void *),
285    IVolume_init(void *);
286
287extern void
288    I3DGrouping_deinit(void *),
289    IAndroidAcousticEchoCancellation_deinit(void *),
290    IAndroidAutomaticGainControl_deinit(void *),
291    IAndroidEffect_deinit(void *),
292    IAndroidEffectCapabilities_deinit(void *),
293    IAndroidBufferQueue_deinit(void *),
294    IAndroidNoiseSuppression_deinit(void*),
295    IBassBoost_deinit(void *),
296    IBufferQueue_deinit(void *),
297    IEngine_deinit(void *),
298    IEnvironmentalReverb_deinit(void *),
299    IEqualizer_deinit(void *),
300    IObject_deinit(void *),
301    IPresetReverb_deinit(void *),
302    IThreadSync_deinit(void *),
303    IVirtualizer_deinit(void *);
304
305extern bool
306    IAndroidAcousticEchoCancellation_Expose(void *),
307    IAndroidAutomaticGainControl_Expose(void *),
308    IAndroidEffectCapabilities_Expose(void *),
309    IAndroidNoiseSuppression_Expose(void *),
310    IBassBoost_Expose(void *),
311    IEnvironmentalReverb_Expose(void *),
312    IEqualizer_Expose(void *),
313    IPresetReverb_Expose(void *),
314    IVirtualizer_Expose(void *);
315
316extern void
317    IXAEngine_init(void *),
318    IStreamInformation_init(void*),
319    IVideoDecoderCapabilities_init(void *);
320
321extern void
322    IXAEngine_deinit(void *),
323    IStreamInformation_deinit(void *),
324    IVideoDecoderCapabilities_deinit(void *);
325
326extern bool
327    IVideoDecoderCapabilities_expose(void *);
328
329#if !(USE_PROFILES & USE_PROFILES_MUSIC)
330#define IDynamicSource_init         NULL
331#define IMetadataTraversal_init     NULL
332#define IVisualization_init         NULL
333#endif
334
335#if !(USE_PROFILES & USE_PROFILES_GAME)
336#define I3DCommit_init      NULL
337#define I3DDoppler_init     NULL
338#define I3DGrouping_init    NULL
339#define I3DLocation_init    NULL
340#define I3DMacroscopic_init NULL
341#define I3DSource_init      NULL
342#define IMIDIMessage_init   NULL
343#define IMIDIMuteSolo_init  NULL
344#define IMIDITempo_init     NULL
345#define IMIDITime_init      NULL
346#define IPitch_init         NULL
347#define IRatePitch_init     NULL
348#define I3DGrouping_deinit  NULL
349#endif
350
351#if !(USE_PROFILES & USE_PROFILES_BASE)
352#define IAudioDecoderCapabilities_init   NULL
353#define IAudioEncoderCapabilities_init   NULL
354#define IAudioEncoder_init               NULL
355#define IAudioIODeviceCapabilities_init  NULL
356#define IDeviceVolume_init               NULL
357#define IEngineCapabilities_init         NULL
358#define IThreadSync_init                 NULL
359#define IThreadSync_deinit               NULL
360#endif
361
362#if !(USE_PROFILES & USE_PROFILES_OPTIONAL)
363#define ILEDArray_init  NULL
364#define IVibra_init     NULL
365#endif
366
367#ifndef ANDROID
368#define IAndroidConfiguration_init        NULL
369#define IAndroidEffect_init               NULL
370#define IAndroidEffectCapabilities_init   NULL
371#define IAndroidEffectSend_init           NULL
372#define IAndroidEffect_deinit             NULL
373#define IAndroidEffectCapabilities_deinit NULL
374#define IAndroidEffectCapabilities_Expose NULL
375#define IAndroidBufferQueue_init          NULL
376#define IStreamInformation_init           NULL
377#define IAndroidBufferQueue_deinit        NULL
378#define IStreamInformation_deinit         NULL
379#endif
380
381#ifndef USE_OUTPUTMIXEXT
382#define IOutputMixExt_init  NULL
383#endif
384
385
386/*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = {
387    { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL, NULL, NULL },
388    { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL, NULL, NULL },
389    { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, I3DGrouping_deinit, NULL, NULL },
390    { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL, NULL, NULL },
391    { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL, NULL, NULL },
392    { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL, NULL, NULL },
393    { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL, NULL, NULL },
394    { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL, NULL, NULL },
395    { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL, NULL, NULL },
396    { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL, NULL,
397        NULL },
398    { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, IBassBoost_deinit, IBassBoost_Expose, NULL },
399    { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, IBufferQueue_deinit, NULL, NULL },
400    { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL, NULL, NULL },
401    { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL, NULL,
402        NULL },
403    { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL, NULL, NULL },
404    { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL, NULL, NULL },
405    { /* MPH_ENGINE, */ IEngine_init, NULL, IEngine_deinit, NULL, NULL },
406    { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL, NULL, NULL },
407    { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, IEnvironmentalReverb_deinit,
408        IEnvironmentalReverb_Expose, NULL },
409    { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, IEqualizer_deinit, IEqualizer_Expose, NULL },
410    { /* MPH_LED, */ ILEDArray_init, NULL, NULL, NULL, NULL },
411    { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL, NULL, NULL },
412    { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL, NULL, NULL },
413    { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL, NULL, NULL },
414    { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL, NULL, NULL },
415    { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL, NULL, NULL },
416    { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL, NULL, NULL },
417    { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL, NULL, NULL },
418    { /* MPH_NULL, */ NULL, NULL, NULL, NULL, NULL },
419    { /* MPH_OBJECT, */ IObject_init, NULL, IObject_deinit, NULL, NULL },
420    { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL, NULL, NULL },
421    { /* MPH_PITCH, */ IPitch_init, NULL, NULL, NULL, NULL },
422    { /* MPH_PLAY, */ IPlay_init, NULL, NULL, NULL, NULL },
423    { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL, NULL, NULL },
424    { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
425    { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, IPresetReverb_deinit,
426        IPresetReverb_Expose, NULL },
427    { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL, NULL, NULL },
428    { /* MPH_RECORD, */ IRecord_init, NULL, NULL, NULL, NULL },
429    { /* MPH_SEEK, */ ISeek_init, NULL, NULL, NULL, NULL },
430    { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, IThreadSync_deinit, NULL, NULL },
431    { /* MPH_VIBRA, */ IVibra_init, NULL, NULL, NULL, NULL },
432    { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, IVirtualizer_deinit, IVirtualizer_Expose,
433        NULL },
434    { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL, NULL, NULL },
435    { /* MPH_VOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
436// Wilhelm desktop extended interfaces
437    { /* MPH_OUTPUTMIXEXT, */ IOutputMixExt_init, NULL, NULL, NULL, NULL },
438// Android API level 9 extended interfaces
439    { /* MPH_ANDROIDEFFECT */ IAndroidEffect_init, NULL, IAndroidEffect_deinit, NULL, NULL },
440    { /* MPH_ANDROIDEFFECTCAPABILITIES */ IAndroidEffectCapabilities_init, NULL,
441        IAndroidEffectCapabilities_deinit, IAndroidEffectCapabilities_Expose, NULL },
442    { /* MPH_ANDROIDEFFECTSEND */ IAndroidEffectSend_init, NULL, NULL, NULL, NULL },
443    { /* MPH_ANDROIDCONFIGURATION */ IAndroidConfiguration_init, NULL, NULL, NULL, NULL },
444    { /* MPH_ANDROIDSIMPLEBUFFERQUEUE */ IBufferQueue_init /* alias */, NULL, NULL, NULL, NULL },
445// Android API level 10 extended interfaces
446    { /* MPH_ANDROIDBUFFERQUEUESOURCE */ IAndroidBufferQueue_init, NULL, IAndroidBufferQueue_deinit,
447        NULL, NULL },
448// OpenMAX AL 1.0.1 interfaces
449    { /* MPH_XAAUDIODECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
450    { /* MPH_XAAUDIOENCODER */ NULL, NULL, NULL, NULL, NULL },
451    { /* MPH_XAAUDIOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
452    { /* MPH_XAAUDIOIODEVICECAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
453    { /* MPH_XACAMERA */ NULL, NULL, NULL, NULL, NULL },
454    { /* MPH_XACAMERACAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
455    { /* MPH_XACONFIGEXTENSION */ NULL, NULL, NULL, NULL, NULL },
456    { /* MPH_XADEVICEVOLUME */ NULL, NULL, NULL, NULL, NULL },
457    { /* MPH_XADYNAMICINTERFACEMANAGEMENT 59 */ NULL, NULL, NULL, NULL, NULL },
458    { /* MPH_XADYNAMICSOURCE */ NULL, NULL, NULL, NULL, NULL },
459    { /* MPH_XAENGINE */ IXAEngine_init, NULL, IXAEngine_deinit, NULL, NULL },
460    { /* MPH_XAEQUALIZER */ NULL, NULL, NULL, NULL, NULL },
461    { /* MPH_XAIMAGECONTROLS */ NULL, NULL, NULL, NULL, NULL },
462    { /* MPH_XAIMAGEDECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
463    { /* MPH_XAIMAGEEFFECTS */ NULL, NULL, NULL, NULL, NULL },
464    { /* MPH_XAIMAGEENCODER */ NULL, NULL, NULL, NULL, NULL },
465    { /* MPH_XAIMAGEENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
466    { /* MPH_XALED */ NULL, NULL, NULL, NULL, NULL },
467    { /* MPH_XAMETADATAEXTRACTION */ NULL, NULL, NULL, NULL, NULL },
468    { /* MPH_XAMETADATAINSERTION */ NULL, NULL, NULL, NULL, NULL },
469    { /* MPH_XAMETADATATRAVERSAL */ NULL, NULL, NULL, NULL, NULL },
470//  { /* MPH_XANULL */ NULL, NULL, NULL, NULL, NULL },
471    { /* MPH_XAOBJECT */ IObject_init, NULL, IObject_deinit, NULL, NULL },
472    { /* MPH_XAOUTPUTMIX */ NULL, NULL, NULL, NULL, NULL },
473    { /* MPH_XAPLAY */ IPlay_init, NULL, NULL, NULL, NULL },
474    { /* MPH_XAPLAYBACKRATE */ NULL, NULL, NULL, NULL, NULL },
475    { /* MPH_XAPREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
476    { /* MPH_XARADIO */ NULL, NULL, NULL, NULL, NULL },
477    { /* MPH_XARDS */ NULL, NULL, NULL, NULL, NULL },
478    { /* MPH_XARECORD */ NULL, NULL, NULL, NULL, NULL },
479    { /* MPH_XASEEK */ ISeek_init, NULL, NULL, NULL, NULL },
480    { /* MPH_XASNAPSHOT */ NULL, NULL, NULL, NULL, NULL },
481    { /* MPH_XASTREAMINFORMATION */ IStreamInformation_init, NULL, IStreamInformation_deinit,
482        NULL, NULL },
483    { /* MPH_XATHREADSYNC */ NULL, NULL, NULL, NULL, NULL },
484    { /* MPH_XAVIBRA */ NULL, NULL, NULL, NULL, NULL },
485    { /* MPH_XAVIDEODECODERCAPABILITIES */ IVideoDecoderCapabilities_init, NULL,
486            IVideoDecoderCapabilities_deinit, IVideoDecoderCapabilities_expose, NULL },
487    { /* MPH_XAVIDEOENCODER */ NULL, NULL, NULL, NULL, NULL },
488    { /* MPH_XAVIDEOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
489    { /* MPH_XAVIDEOPOSTPROCESSING */ NULL, NULL, NULL, NULL, NULL },
490    { /* MPH_XAVOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
491    { /* MPH_ANDROIDACOUSTICECHOCANCELLATION, */ IAndroidAcousticEchoCancellation_init, NULL,
492            IAndroidAcousticEchoCancellation_deinit, IAndroidAcousticEchoCancellation_Expose,
493            NULL },
494    { /* MPH_ANDROIDAUTOMATICGAINCONTROL, */ IAndroidAutomaticGainControl_init, NULL,
495            IAndroidAutomaticGainControl_deinit, IAndroidAutomaticGainControl_Expose, NULL },
496    { /* MPH_ANDROIDNOISESUPPRESSION, */ IAndroidNoiseSuppression_init, NULL,
497            IAndroidNoiseSuppression_deinit, IAndroidNoiseSuppression_Expose, NULL },
498};
499
500
501/** \brief Construct a new instance of the specified class, exposing selected interfaces */
502
503IObject *construct(const ClassTable *clazz, unsigned exposedMask, SLEngineItf engine)
504{
505    IObject *thiz;
506    // Do not change this to malloc; we depend on the object being memset to zero
507    thiz = (IObject *) calloc(1, clazz->mSize);
508    if (NULL != thiz) {
509        SL_LOGV("construct %s at %p", clazz->mName, thiz);
510        unsigned lossOfControlMask = 0;
511        // a NULL engine means we are constructing the engine
512        IEngine *thisEngine = (IEngine *) engine;
513        if (NULL == thisEngine) {
514            // thisEngine = &((CEngine *) thiz)->mEngine;
515            thiz->mEngine = (CEngine *) thiz;
516        } else {
517            thiz->mEngine = (CEngine *) thisEngine->mThis;
518            interface_lock_exclusive(thisEngine);
519            if (MAX_INSTANCE <= thisEngine->mInstanceCount) {
520                SL_LOGE("Too many objects");
521                interface_unlock_exclusive(thisEngine);
522                free(thiz);
523                return NULL;
524            }
525            // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet
526            ++thisEngine->mInstanceCount;
527            assert(((unsigned) ~0) != thisEngine->mInstanceMask);
528            interface_unlock_exclusive(thisEngine);
529            // const, no lock needed
530            if (thisEngine->mLossOfControlGlobal) {
531                lossOfControlMask = ~0;
532            }
533        }
534        thiz->mLossOfControlMask = lossOfControlMask;
535        thiz->mClass = clazz;
536        const struct iid_vtable *x = clazz->mInterfaces;
537        SLuint8 *interfaceStateP = thiz->mInterfaceStates;
538        SLuint32 index;
539        for (index = 0; index < clazz->mInterfaceCount; ++index, ++x, exposedMask >>= 1) {
540            SLuint8 state;
541            // initialize all interfaces with init hooks, even if not exposed
542            const struct MPH_init *mi = &MPH_init_table[x->mMPH];
543            VoidHook init = mi->mInit;
544            if (NULL != init) {
545                void *self = (char *) thiz + x->mOffset;
546                // IObject does not have an mThis, so [1] is not always defined
547                if (index) {
548                    ((IObject **) self)[1] = thiz;
549                }
550                // call the initialization hook
551                (*init)(self);
552                // IObject does not require a call to GetInterface
553                if (index) {
554                    // This trickery invalidates the v-table until GetInterface
555                    ((size_t *) self)[0] ^= ~0;
556                }
557                // if interface is exposed, also call the optional expose hook
558                BoolHook expose;
559                state = (exposedMask & 1) && ((NULL == (expose = mi->mExpose)) || (*expose)(self)) ?
560                        INTERFACE_EXPOSED : INTERFACE_INITIALIZED;
561                // FIXME log or report to application if an expose hook on a
562                // required explicit interface fails at creation time
563            } else {
564                state = INTERFACE_UNINITIALIZED;
565            }
566            *interfaceStateP++ = state;
567        }
568        // note that the new object is not yet published; creator must call IObject_Publish
569    }
570    return thiz;
571}
572