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