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