18db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/*
28db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
38db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten *
48db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
58db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * you may not use this file except in compliance with the License.
68db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * You may obtain a copy of the License at
78db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten *
88db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
98db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten *
108db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * Unless required by applicable law or agreed to in writing, software
118db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
128db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * See the License for the specific language governing permissions and
148db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * limitations under the License.
158db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten */
168db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
178db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/* Initial global entry points */
188db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
198db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#include "sles_allinclusive.h"
208db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
214ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi#ifdef ANDROID
224ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi#include <media/stagefright/DataSource.h>
234ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi#include <binder/ProcessState.h>
244ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi#endif
258db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
268db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** \brief Internal code shared by slCreateEngine and xaCreateEngine */
278db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
28527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn KastenLI_API SLresult liCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions,
298db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    const SLEngineOption *pEngineOptions, SLuint32 numInterfaces,
308db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired,
318db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    const ClassTable *pCEngine_class)
328db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{
338db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    SLresult result;
348db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
358db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    int ok;
368db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    ok = pthread_mutex_lock(&theOneTrueMutex);
378db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    assert(0 == ok);
381d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten    bool needToUnlockTheOneTrueMutex = true;
398db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
408db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    do {
418db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
428db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if (NULL == pEngine) {
438db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
448db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            break;
458db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
468db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        *pEngine = NULL;
478db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
488db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if ((0 < numOptions) && (NULL == pEngineOptions)) {
49a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten            SL_LOGE("numOptions=%u and pEngineOptions=NULL", numOptions);
508db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
518db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            break;
528db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
538db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
548db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        // default values
558db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        SLboolean threadSafe = SL_BOOLEAN_TRUE;
568db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        SLboolean lossOfControlGlobal = SL_BOOLEAN_FALSE;
578db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
588db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        // process engine options
598db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        SLuint32 i;
608db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        const SLEngineOption *option = pEngineOptions;
618db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        result = SL_RESULT_SUCCESS;
628db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        for (i = 0; i < numOptions; ++i, ++option) {
638db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            switch (option->feature) {
648db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case SL_ENGINEOPTION_THREADSAFE:
658db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                threadSafe = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize
668db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                break;
678db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case SL_ENGINEOPTION_LOSSOFCONTROL:
688db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                lossOfControlGlobal = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize
698db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                break;
708db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            default:
71a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                SL_LOGE("unknown engine option: feature=%u data=%u",
728db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    option->feature, option->data);
738db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
748db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                break;
758db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            }
768db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
778db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if (SL_RESULT_SUCCESS != result) {
788db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            break;
798db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
808db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
818db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        unsigned exposedMask;
828db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        assert(NULL != pCEngine_class);
838db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        result = checkInterfaces(pCEngine_class, numInterfaces,
8405c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten            pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
858db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if (SL_RESULT_SUCCESS != result) {
868db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            break;
878db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
888db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
891d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        // if an engine already exists, then increment its ref count
90bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        CEngine *thiz = theOneTrueEngine;
91bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (NULL != thiz) {
921d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            assert(0 < theOneTrueRefCount);
931d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            ++theOneTrueRefCount;
941d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten
951d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            // In order to update the engine object, we need to lock it,
961d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            // but that would violate the lock order and potentially deadlock.
971d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            // So we unlock now and note that it should not be unlocked later.
981d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            ok = pthread_mutex_unlock(&theOneTrueMutex);
991d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            assert(0 == ok);
1001d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            needToUnlockTheOneTrueMutex = false;
101bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            object_lock_exclusive(&thiz->mObject);
1021d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten
1031d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            // now expose additional interfaces not requested by the earlier engine create
1041d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            const struct iid_vtable *x = pCEngine_class->mInterfaces;
105bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            SLuint8 *interfaceStateP = thiz->mObject.mInterfaceStates;
1061d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            SLuint32 index;
1071d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            for (index = 0; index < pCEngine_class->mInterfaceCount; ++index, ++x,
1081d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    exposedMask >>= 1, ++interfaceStateP) {
1091d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                switch (*interfaceStateP) {
1101d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                case INTERFACE_EXPOSED:         // previously exposed
1111d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    break;
1121d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                case INTERFACE_INITIALIZED:     // not exposed during the earlier create
1131d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    if (exposedMask & 1) {
1141d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                        const struct MPH_init *mi = &MPH_init_table[x->mMPH];
1151d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                        BoolHook expose = mi->mExpose;
116bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                        if ((NULL == expose) || (*expose)((char *) thiz + x->mOffset)) {
1171d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                            *interfaceStateP = INTERFACE_EXPOSED;
1181d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                        }
1191d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                        // FIXME log or report to application that expose hook failed
1201d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    }
1211d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    break;
1221d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                case INTERFACE_UNINITIALIZED:   // no init hook
1231d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    break;
1241d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                default:                        // impossible
1251d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    assert(false);
1261d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    break;
1271d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                }
1281d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            }
129bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            object_unlock_exclusive(&thiz->mObject);
1301d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            // return the shared engine object
131bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            *pEngine = &thiz->mObject.mItf;
1321d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            break;
1331d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        }
1341d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten
1351d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        // here when creating the first engine reference
1361d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        assert(0 == theOneTrueRefCount);
1371d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten
1381d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten#ifdef ANDROID
1391d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        android::ProcessState::self()->startThreadPool();
1401d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        android::DataSource::RegisterDefaultSniffers();
1411d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten#endif
1421d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten
143bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz = (CEngine *) construct(pCEngine_class, exposedMask, NULL);
144bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        if (NULL == thiz) {
1458db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            result = SL_RESULT_MEMORY_FAILURE;
1468db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            break;
1478db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
1488db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
1498db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        // initialize fields not associated with an interface
1508db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        // mThreadPool is initialized in CEngine_Realize
151bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        memset(&thiz->mThreadPool, 0, sizeof(ThreadPool));
152bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        memset(&thiz->mSyncThread, 0, sizeof(pthread_t));
153faf90312d2156acbf27c62e114fd180708aa7654Glenn Kasten#if defined(ANDROID)
154bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mEqNumPresets = 0;
155bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mEqPresetNames = NULL;
1568db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#endif
1578db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        // initialize fields related to an interface
158bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mObject.mLossOfControlMask = lossOfControlGlobal ? ~0 : 0;
159bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mEngine.mLossOfControlGlobal = lossOfControlGlobal;
160bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mEngineCapabilities.mThreadSafe = threadSafe;
161bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        IObject_Publish(&thiz->mObject);
162bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        theOneTrueEngine = thiz;
1631d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        theOneTrueRefCount = 1;
1648db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        // return the new engine object
165bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        *pEngine = &thiz->mObject.mItf;
1668db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
1678db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    } while(0);
1688db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
1691d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten    if (needToUnlockTheOneTrueMutex) {
1701d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        ok = pthread_mutex_unlock(&theOneTrueMutex);
1711d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        assert(0 == ok);
1721d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten    }
1738db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
1748db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    return result;
1758db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten}
1768db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
1778db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
1788db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** Internal function for slQuerySupportedEngineInterfaces and xaQuerySupportedEngineInterfaces */
1798db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
180527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn KastenLI_API SLresult liQueryNumSupportedInterfaces(SLuint32 *pNumSupportedInterfaces,
181bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        const ClassTable *clazz)
1828db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{
1838db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    SLresult result;
1848db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    if (NULL == pNumSupportedInterfaces) {
1858db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
1868db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    } else {
187bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        assert(NULL != clazz);
1888db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        SLuint32 count = 0;
1898db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        SLuint32 i;
190bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        for (i = 0; i < clazz->mInterfaceCount; ++i) {
191bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            switch (clazz->mInterfaces[i].mInterface) {
1928db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_IMPLICIT:
1938db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_IMPLICIT_PREREALIZE:
1948db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_EXPLICIT:
1958db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_EXPLICIT_PREREALIZE:
1968db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_DYNAMIC:
1978db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                ++count;
1988db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                break;
1998db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_UNAVAILABLE:
2008db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                break;
2018db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            default:
2028db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                assert(false);
2038db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                break;
2048db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            }
2058db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
2068db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        *pNumSupportedInterfaces = count;
2078db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        result = SL_RESULT_SUCCESS;
2088db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
2098db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    return result;
2108db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten}
2118db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
2128db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
2138db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** Internal function for slQuerySupportedEngineInterfaces and xaQuerySupportedEngineInterfaces */
2148db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
215527f8ca99f2938d6569fc25dcf3256985a54dec6Glenn KastenLI_API SLresult liQuerySupportedInterfaces(SLuint32 index, SLInterfaceID *pInterfaceId,
216bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        const ClassTable *clazz)
2178db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{
2188db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    SLresult result;
2198db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    if (NULL == pInterfaceId) {
2208db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
2218db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    } else {
2228db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        *pInterfaceId = NULL;
223bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        assert(NULL != clazz);
2248db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        result = SL_RESULT_PARAMETER_INVALID;   // will be reset later
2258db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        SLuint32 i;
226bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        for (i = 0; i < clazz->mInterfaceCount; ++i) {
227bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            switch (clazz->mInterfaces[i].mInterface) {
2288db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_IMPLICIT:
2298db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_IMPLICIT_PREREALIZE:
2308db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_EXPLICIT:
2318db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_EXPLICIT_PREREALIZE:
2328db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_DYNAMIC:
2338db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                break;
2348db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            case INTERFACE_UNAVAILABLE:
2358db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                continue;
2368db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            default:
2378db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                assert(false);
2388db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                break;
2398db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            }
2408db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            if (index == 0) {
241bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten                *pInterfaceId = &SL_IID_array[clazz->mInterfaces[i].mMPH];
2428db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                result = SL_RESULT_SUCCESS;
2438db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                break;
2448db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            }
2458db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            --index;
2468db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
2478db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
2488db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    return result;
2498db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten}
250