Home | History | Annotate | Download | only in src
      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 
     30 bool 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 
     54 SLuint32 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 
     74 SLresult 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 
    105 void 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 
    127 void 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 
    137 SLresult 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 
    151 SLresult 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 
    233 extern 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 
    287 extern 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     IAndroidConfiguration_deinit(void *);
    305 
    306 extern bool
    307     IAndroidAcousticEchoCancellation_Expose(void *),
    308     IAndroidAutomaticGainControl_Expose(void *),
    309     IAndroidEffectCapabilities_Expose(void *),
    310     IAndroidNoiseSuppression_Expose(void *),
    311     IBassBoost_Expose(void *),
    312     IEnvironmentalReverb_Expose(void *),
    313     IEqualizer_Expose(void *),
    314     IPresetReverb_Expose(void *),
    315     IVirtualizer_Expose(void *);
    316 
    317 extern void
    318     IXAEngine_init(void *),
    319     IStreamInformation_init(void*),
    320     IVideoDecoderCapabilities_init(void *);
    321 
    322 extern void
    323     IXAEngine_deinit(void *),
    324     IStreamInformation_deinit(void *),
    325     IVideoDecoderCapabilities_deinit(void *);
    326 
    327 extern bool
    328     IVideoDecoderCapabilities_expose(void *);
    329 
    330 #if !(USE_PROFILES & USE_PROFILES_MUSIC)
    331 #define IDynamicSource_init         NULL
    332 #define IMetadataTraversal_init     NULL
    333 #define IVisualization_init         NULL
    334 #endif
    335 
    336 #if !(USE_PROFILES & USE_PROFILES_GAME)
    337 #define I3DCommit_init      NULL
    338 #define I3DDoppler_init     NULL
    339 #define I3DGrouping_init    NULL
    340 #define I3DLocation_init    NULL
    341 #define I3DMacroscopic_init NULL
    342 #define I3DSource_init      NULL
    343 #define IMIDIMessage_init   NULL
    344 #define IMIDIMuteSolo_init  NULL
    345 #define IMIDITempo_init     NULL
    346 #define IMIDITime_init      NULL
    347 #define IPitch_init         NULL
    348 #define IRatePitch_init     NULL
    349 #define I3DGrouping_deinit  NULL
    350 #endif
    351 
    352 #if !(USE_PROFILES & USE_PROFILES_BASE)
    353 #define IAudioDecoderCapabilities_init   NULL
    354 #define IAudioEncoderCapabilities_init   NULL
    355 #define IAudioEncoder_init               NULL
    356 #define IAudioIODeviceCapabilities_init  NULL
    357 #define IDeviceVolume_init               NULL
    358 #define IEngineCapabilities_init         NULL
    359 #define IThreadSync_init                 NULL
    360 #define IThreadSync_deinit               NULL
    361 #endif
    362 
    363 #if !(USE_PROFILES & USE_PROFILES_OPTIONAL)
    364 #define ILEDArray_init  NULL
    365 #define IVibra_init     NULL
    366 #endif
    367 
    368 #ifndef ANDROID
    369 #define IAndroidConfiguration_init        NULL
    370 #define IAndroidConfiguration_deinit      NULL
    371 #define IAndroidEffect_init               NULL
    372 #define IAndroidEffectCapabilities_init   NULL
    373 #define IAndroidEffectSend_init           NULL
    374 #define IAndroidEffect_deinit             NULL
    375 #define IAndroidEffectCapabilities_deinit NULL
    376 #define IAndroidEffectCapabilities_Expose NULL
    377 #define IAndroidBufferQueue_init          NULL
    378 #define IStreamInformation_init           NULL
    379 #define IAndroidBufferQueue_deinit        NULL
    380 #define IStreamInformation_deinit         NULL
    381 #endif
    382 
    383 #ifndef USE_OUTPUTMIXEXT
    384 #define IOutputMixExt_init  NULL
    385 #endif
    386 
    387 
    388 /*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = {
    389     { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL, NULL, NULL, NULL },
    390     { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL, NULL, NULL, NULL },
    391     { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL, I3DGrouping_deinit, NULL, NULL },
    392     { /* MPH_3DLOCATION, */ I3DLocation_init, NULL, NULL, NULL, NULL },
    393     { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL, NULL, NULL, NULL },
    394     { /* MPH_3DSOURCE, */ I3DSource_init, NULL, NULL, NULL, NULL },
    395     { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL, NULL, NULL, NULL },
    396     { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL, NULL, NULL, NULL },
    397     { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL, NULL, NULL, NULL },
    398     { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, NULL, NULL, NULL,
    399         NULL },
    400     { /* MPH_BASSBOOST, */ IBassBoost_init, NULL, IBassBoost_deinit, IBassBoost_Expose, NULL },
    401     { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL, IBufferQueue_deinit, NULL, NULL },
    402     { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL, NULL, NULL, NULL },
    403     { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, NULL, NULL, NULL,
    404         NULL },
    405     { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL, NULL, NULL, NULL },
    406     { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL, NULL, NULL, NULL },
    407     { /* MPH_ENGINE, */ IEngine_init, NULL, IEngine_deinit, NULL, NULL },
    408     { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL, NULL, NULL, NULL },
    409     { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL, IEnvironmentalReverb_deinit,
    410         IEnvironmentalReverb_Expose, NULL },
    411     { /* MPH_EQUALIZER, */ IEqualizer_init, NULL, IEqualizer_deinit, IEqualizer_Expose, NULL },
    412     { /* MPH_LED, */ ILEDArray_init, NULL, NULL, NULL, NULL },
    413     { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL, NULL, NULL, NULL },
    414     { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL, NULL, NULL, NULL },
    415     { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL, NULL, NULL, NULL },
    416     { /* MPH_MIDITIME, */ IMIDITime_init, NULL, NULL, NULL, NULL },
    417     { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL, NULL, NULL, NULL },
    418     { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL, NULL, NULL, NULL },
    419     { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL, NULL, NULL, NULL },
    420     { /* MPH_NULL, */ NULL, NULL, NULL, NULL, NULL },
    421     { /* MPH_OBJECT, */ IObject_init, NULL, IObject_deinit, NULL, NULL },
    422     { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL, NULL, NULL, NULL },
    423     { /* MPH_PITCH, */ IPitch_init, NULL, NULL, NULL, NULL },
    424     { /* MPH_PLAY, */ IPlay_init, NULL, NULL, NULL, NULL },
    425     { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL, NULL, NULL, NULL },
    426     { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
    427     { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL, IPresetReverb_deinit,
    428         IPresetReverb_Expose, NULL },
    429     { /* MPH_RATEPITCH, */ IRatePitch_init, NULL, NULL, NULL, NULL },
    430     { /* MPH_RECORD, */ IRecord_init, NULL, NULL, NULL, NULL },
    431     { /* MPH_SEEK, */ ISeek_init, NULL, NULL, NULL, NULL },
    432     { /* MPH_THREADSYNC, */ IThreadSync_init, NULL, IThreadSync_deinit, NULL, NULL },
    433     { /* MPH_VIBRA, */ IVibra_init, NULL, NULL, NULL, NULL },
    434     { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL, IVirtualizer_deinit, IVirtualizer_Expose,
    435         NULL },
    436     { /* MPH_VISUALIZATION, */ IVisualization_init, NULL, NULL, NULL, NULL },
    437     { /* MPH_VOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
    438 // Wilhelm desktop extended interfaces
    439     { /* MPH_OUTPUTMIXEXT, */ IOutputMixExt_init, NULL, NULL, NULL, NULL },
    440 // Android API level 9 extended interfaces
    441     { /* MPH_ANDROIDEFFECT */ IAndroidEffect_init, NULL, IAndroidEffect_deinit, NULL, NULL },
    442     { /* MPH_ANDROIDEFFECTCAPABILITIES */ IAndroidEffectCapabilities_init, NULL,
    443         IAndroidEffectCapabilities_deinit, IAndroidEffectCapabilities_Expose, NULL },
    444     { /* MPH_ANDROIDEFFECTSEND */ IAndroidEffectSend_init, NULL, NULL, NULL, NULL },
    445     { /* MPH_ANDROIDCONFIGURATION */ IAndroidConfiguration_init, NULL, IAndroidConfiguration_deinit,
    446             NULL, NULL },
    447     { /* MPH_ANDROIDSIMPLEBUFFERQUEUE */ IBufferQueue_init /* alias */, NULL, NULL, NULL, NULL },
    448 // Android API level 10 extended interfaces
    449     { /* MPH_ANDROIDBUFFERQUEUESOURCE */ IAndroidBufferQueue_init, NULL, IAndroidBufferQueue_deinit,
    450         NULL, NULL },
    451 // OpenMAX AL 1.0.1 interfaces
    452     { /* MPH_XAAUDIODECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
    453     { /* MPH_XAAUDIOENCODER */ NULL, NULL, NULL, NULL, NULL },
    454     { /* MPH_XAAUDIOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
    455     { /* MPH_XAAUDIOIODEVICECAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
    456     { /* MPH_XACAMERA */ NULL, NULL, NULL, NULL, NULL },
    457     { /* MPH_XACAMERACAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
    458     { /* MPH_XACONFIGEXTENSION */ NULL, NULL, NULL, NULL, NULL },
    459     { /* MPH_XADEVICEVOLUME */ NULL, NULL, NULL, NULL, NULL },
    460     { /* MPH_XADYNAMICINTERFACEMANAGEMENT 59 */ NULL, NULL, NULL, NULL, NULL },
    461     { /* MPH_XADYNAMICSOURCE */ NULL, NULL, NULL, NULL, NULL },
    462     { /* MPH_XAENGINE */ IXAEngine_init, NULL, IXAEngine_deinit, NULL, NULL },
    463     { /* MPH_XAEQUALIZER */ NULL, NULL, NULL, NULL, NULL },
    464     { /* MPH_XAIMAGECONTROLS */ NULL, NULL, NULL, NULL, NULL },
    465     { /* MPH_XAIMAGEDECODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
    466     { /* MPH_XAIMAGEEFFECTS */ NULL, NULL, NULL, NULL, NULL },
    467     { /* MPH_XAIMAGEENCODER */ NULL, NULL, NULL, NULL, NULL },
    468     { /* MPH_XAIMAGEENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
    469     { /* MPH_XALED */ NULL, NULL, NULL, NULL, NULL },
    470     { /* MPH_XAMETADATAEXTRACTION */ NULL, NULL, NULL, NULL, NULL },
    471     { /* MPH_XAMETADATAINSERTION */ NULL, NULL, NULL, NULL, NULL },
    472     { /* MPH_XAMETADATATRAVERSAL */ NULL, NULL, NULL, NULL, NULL },
    473 //  { /* MPH_XANULL */ NULL, NULL, NULL, NULL, NULL },
    474     { /* MPH_XAOBJECT */ IObject_init, NULL, IObject_deinit, NULL, NULL },
    475     { /* MPH_XAOUTPUTMIX */ NULL, NULL, NULL, NULL, NULL },
    476     { /* MPH_XAPLAY */ IPlay_init, NULL, NULL, NULL, NULL },
    477     { /* MPH_XAPLAYBACKRATE */ NULL, NULL, NULL, NULL, NULL },
    478     { /* MPH_XAPREFETCHSTATUS, */ IPrefetchStatus_init, NULL, NULL, NULL, NULL },
    479     { /* MPH_XARADIO */ NULL, NULL, NULL, NULL, NULL },
    480     { /* MPH_XARDS */ NULL, NULL, NULL, NULL, NULL },
    481     { /* MPH_XARECORD */ NULL, NULL, NULL, NULL, NULL },
    482     { /* MPH_XASEEK */ ISeek_init, NULL, NULL, NULL, NULL },
    483     { /* MPH_XASNAPSHOT */ NULL, NULL, NULL, NULL, NULL },
    484     { /* MPH_XASTREAMINFORMATION */ IStreamInformation_init, NULL, IStreamInformation_deinit,
    485         NULL, NULL },
    486     { /* MPH_XATHREADSYNC */ NULL, NULL, NULL, NULL, NULL },
    487     { /* MPH_XAVIBRA */ NULL, NULL, NULL, NULL, NULL },
    488     { /* MPH_XAVIDEODECODERCAPABILITIES */ IVideoDecoderCapabilities_init, NULL,
    489             IVideoDecoderCapabilities_deinit, IVideoDecoderCapabilities_expose, NULL },
    490     { /* MPH_XAVIDEOENCODER */ NULL, NULL, NULL, NULL, NULL },
    491     { /* MPH_XAVIDEOENCODERCAPABILITIES */ NULL, NULL, NULL, NULL, NULL },
    492     { /* MPH_XAVIDEOPOSTPROCESSING */ NULL, NULL, NULL, NULL, NULL },
    493     { /* MPH_XAVOLUME, */ IVolume_init, NULL, NULL, NULL, NULL },
    494     { /* MPH_ANDROIDACOUSTICECHOCANCELLATION, */ IAndroidAcousticEchoCancellation_init, NULL,
    495             IAndroidAcousticEchoCancellation_deinit, IAndroidAcousticEchoCancellation_Expose,
    496             NULL },
    497     { /* MPH_ANDROIDAUTOMATICGAINCONTROL, */ IAndroidAutomaticGainControl_init, NULL,
    498             IAndroidAutomaticGainControl_deinit, IAndroidAutomaticGainControl_Expose, NULL },
    499     { /* MPH_ANDROIDNOISESUPPRESSION, */ IAndroidNoiseSuppression_init, NULL,
    500             IAndroidNoiseSuppression_deinit, IAndroidNoiseSuppression_Expose, NULL },
    501 };
    502 
    503 
    504 /** \brief Construct a new instance of the specified class, exposing selected interfaces */
    505 
    506 IObject *construct(const ClassTable *clazz, unsigned exposedMask, SLEngineItf engine)
    507 {
    508     IObject *thiz;
    509     // Do not change this to malloc; we depend on the object being memset to zero
    510     thiz = (IObject *) calloc(1, clazz->mSize);
    511     if (NULL != thiz) {
    512         SL_LOGV("construct %s at %p", clazz->mName, thiz);
    513         unsigned lossOfControlMask = 0;
    514         // a NULL engine means we are constructing the engine
    515         IEngine *thisEngine = (IEngine *) engine;
    516         if (NULL == thisEngine) {
    517             // thisEngine = &((CEngine *) thiz)->mEngine;
    518             thiz->mEngine = (CEngine *) thiz;
    519         } else {
    520             thiz->mEngine = (CEngine *) thisEngine->mThis;
    521             interface_lock_exclusive(thisEngine);
    522             if (MAX_INSTANCE <= thisEngine->mInstanceCount) {
    523                 SL_LOGE("Too many objects");
    524                 interface_unlock_exclusive(thisEngine);
    525                 free(thiz);
    526                 return NULL;
    527             }
    528             // pre-allocate a pending slot, but don't assign bit from mInstanceMask yet
    529             ++thisEngine->mInstanceCount;
    530             assert(((unsigned) ~0) != thisEngine->mInstanceMask);
    531             interface_unlock_exclusive(thisEngine);
    532             // const, no lock needed
    533             if (thisEngine->mLossOfControlGlobal) {
    534                 lossOfControlMask = ~0;
    535             }
    536         }
    537         thiz->mLossOfControlMask = lossOfControlMask;
    538         thiz->mClass = clazz;
    539         const struct iid_vtable *x = clazz->mInterfaces;
    540         SLuint8 *interfaceStateP = thiz->mInterfaceStates;
    541         SLuint32 index;
    542         for (index = 0; index < clazz->mInterfaceCount; ++index, ++x, exposedMask >>= 1) {
    543             SLuint8 state;
    544             // initialize all interfaces with init hooks, even if not exposed
    545             const struct MPH_init *mi = &MPH_init_table[x->mMPH];
    546             VoidHook init = mi->mInit;
    547             if (NULL != init) {
    548                 void *self = (char *) thiz + x->mOffset;
    549                 // IObject does not have an mThis, so [1] is not always defined
    550                 if (index) {
    551                     ((IObject **) self)[1] = thiz;
    552                 }
    553                 // call the initialization hook
    554                 (*init)(self);
    555                 // IObject does not require a call to GetInterface
    556                 if (index) {
    557                     // This trickery invalidates the v-table until GetInterface
    558                     ((size_t *) self)[0] ^= ~0;
    559                 }
    560                 // if interface is exposed, also call the optional expose hook
    561                 BoolHook expose;
    562                 state = (exposedMask & 1) && ((NULL == (expose = mi->mExpose)) || (*expose)(self)) ?
    563                         INTERFACE_EXPOSED : INTERFACE_INITIALIZED;
    564                 // FIXME log or report to application if an expose hook on a
    565                 // required explicit interface fails at creation time
    566             } else {
    567                 state = INTERFACE_UNINITIALIZED;
    568             }
    569             *interfaceStateP++ = state;
    570         }
    571         // note that the new object is not yet published; creator must call IObject_Publish
    572     }
    573     return thiz;
    574 }
    575