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 /* Initial global entry points */
     18 
     19 #include "sles_allinclusive.h"
     20 
     21 #ifdef ANDROID
     22 #include <media/stagefright/DataSource.h>
     23 #include <binder/ProcessState.h>
     24 #endif
     25 
     26 /** \brief Internal code shared by slCreateEngine and xaCreateEngine */
     27 
     28 LI_API SLresult liCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions,
     29     const SLEngineOption *pEngineOptions, SLuint32 numInterfaces,
     30     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired,
     31     const ClassTable *pCEngine_class)
     32 {
     33     SLresult result;
     34 
     35     int ok;
     36     ok = pthread_mutex_lock(&theOneTrueMutex);
     37     assert(0 == ok);
     38     bool needToUnlockTheOneTrueMutex = true;
     39 
     40     do {
     41 
     42         if (NULL == pEngine) {
     43             result = SL_RESULT_PARAMETER_INVALID;
     44             break;
     45         }
     46         *pEngine = NULL;
     47 
     48         if ((0 < numOptions) && (NULL == pEngineOptions)) {
     49             SL_LOGE("numOptions=%u and pEngineOptions=NULL", numOptions);
     50             result = SL_RESULT_PARAMETER_INVALID;
     51             break;
     52         }
     53 
     54         // default values
     55         SLboolean threadSafe = SL_BOOLEAN_TRUE;
     56         SLboolean lossOfControlGlobal = SL_BOOLEAN_FALSE;
     57 
     58         // process engine options
     59         SLuint32 i;
     60         const SLEngineOption *option = pEngineOptions;
     61         result = SL_RESULT_SUCCESS;
     62         for (i = 0; i < numOptions; ++i, ++option) {
     63             switch (option->feature) {
     64             case SL_ENGINEOPTION_THREADSAFE:
     65                 threadSafe = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize
     66                 break;
     67             case SL_ENGINEOPTION_LOSSOFCONTROL:
     68                 lossOfControlGlobal = SL_BOOLEAN_FALSE != (SLboolean) option->data; // normalize
     69                 break;
     70             default:
     71                 SL_LOGE("unknown engine option: feature=%u data=%u",
     72                     option->feature, option->data);
     73                 result = SL_RESULT_PARAMETER_INVALID;
     74                 break;
     75             }
     76         }
     77         if (SL_RESULT_SUCCESS != result) {
     78             break;
     79         }
     80 
     81         unsigned exposedMask;
     82         assert(NULL != pCEngine_class);
     83         result = checkInterfaces(pCEngine_class, numInterfaces,
     84             pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
     85         if (SL_RESULT_SUCCESS != result) {
     86             break;
     87         }
     88 
     89         // if an engine already exists, then increment its ref count
     90         CEngine *thiz = theOneTrueEngine;
     91         if (NULL != thiz) {
     92             assert(0 < theOneTrueRefCount);
     93             ++theOneTrueRefCount;
     94 
     95             // In order to update the engine object, we need to lock it,
     96             // but that would violate the lock order and potentially deadlock.
     97             // So we unlock now and note that it should not be unlocked later.
     98             ok = pthread_mutex_unlock(&theOneTrueMutex);
     99             assert(0 == ok);
    100             needToUnlockTheOneTrueMutex = false;
    101             object_lock_exclusive(&thiz->mObject);
    102 
    103             // now expose additional interfaces not requested by the earlier engine create
    104             const struct iid_vtable *x = pCEngine_class->mInterfaces;
    105             SLuint8 *interfaceStateP = thiz->mObject.mInterfaceStates;
    106             SLuint32 index;
    107             for (index = 0; index < pCEngine_class->mInterfaceCount; ++index, ++x,
    108                     exposedMask >>= 1, ++interfaceStateP) {
    109                 switch (*interfaceStateP) {
    110                 case INTERFACE_EXPOSED:         // previously exposed
    111                     break;
    112                 case INTERFACE_INITIALIZED:     // not exposed during the earlier create
    113                     if (exposedMask & 1) {
    114                         const struct MPH_init *mi = &MPH_init_table[x->mMPH];
    115                         BoolHook expose = mi->mExpose;
    116                         if ((NULL == expose) || (*expose)((char *) thiz + x->mOffset)) {
    117                             *interfaceStateP = INTERFACE_EXPOSED;
    118                         }
    119                         // FIXME log or report to application that expose hook failed
    120                     }
    121                     break;
    122                 case INTERFACE_UNINITIALIZED:   // no init hook
    123                     break;
    124                 default:                        // impossible
    125                     assert(false);
    126                     break;
    127                 }
    128             }
    129             object_unlock_exclusive(&thiz->mObject);
    130             // return the shared engine object
    131             *pEngine = &thiz->mObject.mItf;
    132             break;
    133         }
    134 
    135         // here when creating the first engine reference
    136         assert(0 == theOneTrueRefCount);
    137 
    138 #ifdef ANDROID
    139         android::ProcessState::self()->startThreadPool();
    140         android::DataSource::RegisterDefaultSniffers();
    141 #endif
    142 
    143         thiz = (CEngine *) construct(pCEngine_class, exposedMask, NULL);
    144         if (NULL == thiz) {
    145             result = SL_RESULT_MEMORY_FAILURE;
    146             break;
    147         }
    148 
    149         // initialize fields not associated with an interface
    150         // mThreadPool is initialized in CEngine_Realize
    151         memset(&thiz->mThreadPool, 0, sizeof(ThreadPool));
    152         memset(&thiz->mSyncThread, 0, sizeof(pthread_t));
    153 #if defined(ANDROID)
    154         thiz->mEqNumPresets = 0;
    155         thiz->mEqPresetNames = NULL;
    156 #endif
    157         // initialize fields related to an interface
    158         thiz->mObject.mLossOfControlMask = lossOfControlGlobal ? ~0 : 0;
    159         thiz->mEngine.mLossOfControlGlobal = lossOfControlGlobal;
    160         thiz->mEngineCapabilities.mThreadSafe = threadSafe;
    161         IObject_Publish(&thiz->mObject);
    162         theOneTrueEngine = thiz;
    163         theOneTrueRefCount = 1;
    164         // return the new engine object
    165         *pEngine = &thiz->mObject.mItf;
    166 
    167     } while(0);
    168 
    169     if (needToUnlockTheOneTrueMutex) {
    170         ok = pthread_mutex_unlock(&theOneTrueMutex);
    171         assert(0 == ok);
    172     }
    173 
    174     return result;
    175 }
    176 
    177 
    178 /** Internal function for slQuerySupportedEngineInterfaces and xaQuerySupportedEngineInterfaces */
    179 
    180 LI_API SLresult liQueryNumSupportedInterfaces(SLuint32 *pNumSupportedInterfaces,
    181         const ClassTable *clazz)
    182 {
    183     SLresult result;
    184     if (NULL == pNumSupportedInterfaces) {
    185         result = SL_RESULT_PARAMETER_INVALID;
    186     } else {
    187         assert(NULL != clazz);
    188         SLuint32 count = 0;
    189         SLuint32 i;
    190         for (i = 0; i < clazz->mInterfaceCount; ++i) {
    191             switch (clazz->mInterfaces[i].mInterface) {
    192             case INTERFACE_IMPLICIT:
    193             case INTERFACE_IMPLICIT_PREREALIZE:
    194             case INTERFACE_EXPLICIT:
    195             case INTERFACE_EXPLICIT_PREREALIZE:
    196             case INTERFACE_DYNAMIC:
    197                 ++count;
    198                 break;
    199             case INTERFACE_UNAVAILABLE:
    200                 break;
    201             default:
    202                 assert(false);
    203                 break;
    204             }
    205         }
    206         *pNumSupportedInterfaces = count;
    207         result = SL_RESULT_SUCCESS;
    208     }
    209     return result;
    210 }
    211 
    212 
    213 /** Internal function for slQuerySupportedEngineInterfaces and xaQuerySupportedEngineInterfaces */
    214 
    215 LI_API SLresult liQuerySupportedInterfaces(SLuint32 index, SLInterfaceID *pInterfaceId,
    216         const ClassTable *clazz)
    217 {
    218     SLresult result;
    219     if (NULL == pInterfaceId) {
    220         result = SL_RESULT_PARAMETER_INVALID;
    221     } else {
    222         *pInterfaceId = NULL;
    223         assert(NULL != clazz);
    224         result = SL_RESULT_PARAMETER_INVALID;   // will be reset later
    225         SLuint32 i;
    226         for (i = 0; i < clazz->mInterfaceCount; ++i) {
    227             switch (clazz->mInterfaces[i].mInterface) {
    228             case INTERFACE_IMPLICIT:
    229             case INTERFACE_IMPLICIT_PREREALIZE:
    230             case INTERFACE_EXPLICIT:
    231             case INTERFACE_EXPLICIT_PREREALIZE:
    232             case INTERFACE_DYNAMIC:
    233                 break;
    234             case INTERFACE_UNAVAILABLE:
    235                 continue;
    236             default:
    237                 assert(false);
    238                 break;
    239             }
    240             if (index == 0) {
    241                 *pInterfaceId = &SL_IID_array[clazz->mInterfaces[i].mMPH];
    242                 result = SL_RESULT_SUCCESS;
    243                 break;
    244             }
    245             --index;
    246         }
    247     }
    248     return result;
    249 }
    250