entry.c revision 262059f71a68edc5e510427c63f5f1623d3672a8
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 24static 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 *this = theOneTrueEngine; 87 if (NULL != this) { 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(&this->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 = this->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 *) this + 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(&this->mObject); 126 // return the shared engine object 127 *pEngine = &this->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 this = (CEngine *) construct(pCEngine_class, exposedMask, NULL); 140 if (NULL == this) { 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(&this->mThreadPool, 0, sizeof(ThreadPool)); 148 memset(&this->mSyncThread, 0, sizeof(pthread_t)); 149#if defined(ANDROID) 150 this->mEqNumPresets = 0; 151 this->mEqPresetNames = NULL; 152#endif 153 // initialize fields related to an interface 154 this->mObject.mLossOfControlMask = lossOfControlGlobal ? ~0 : 0; 155 this->mEngine.mLossOfControlGlobal = lossOfControlGlobal; 156 this->mEngineCapabilities.mThreadSafe = threadSafe; 157 IObject_Publish(&this->mObject); 158 theOneTrueEngine = this; 159 theOneTrueRefCount = 1; 160 // return the new engine object 161 *pEngine = &this->mObject.mItf; 162 163 } while(0); 164 165 if (needToUnlockTheOneTrueMutex) { 166 ok = pthread_mutex_unlock(&theOneTrueMutex); 167 assert(0 == ok); 168 needToUnlockTheOneTrueMutex = false; 169 } 170 171 return result; 172} 173 174 175/** \brief slCreateEngine Function */ 176 177SL_API SLresult SLAPIENTRY slCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions, 178 const SLEngineOption *pEngineOptions, SLuint32 numInterfaces, 179 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 180{ 181 SL_ENTER_GLOBAL 182 183 result = liCreateEngine(pEngine, numOptions, pEngineOptions, numInterfaces, pInterfaceIds, 184 pInterfaceRequired, objectIDtoClass(SL_OBJECTID_ENGINE)); 185 186 SL_LEAVE_GLOBAL 187} 188 189 190/** Internal function for slQuerySupportedEngineInterfaces and xaQuerySupportedEngineInterfaces */ 191 192static SLresult liQueryNumSupportedInterfaces(SLuint32 *pNumSupportedInterfaces, 193 const ClassTable *class__) 194{ 195 SLresult result; 196 if (NULL == pNumSupportedInterfaces) { 197 result = SL_RESULT_PARAMETER_INVALID; 198 } else { 199 assert(NULL != class__); 200 SLuint32 count = 0; 201 SLuint32 i; 202 for (i = 0; i < class__->mInterfaceCount; ++i) { 203 switch (class__->mInterfaces[i].mInterface) { 204 case INTERFACE_IMPLICIT: 205 case INTERFACE_IMPLICIT_PREREALIZE: 206 case INTERFACE_EXPLICIT: 207 case INTERFACE_EXPLICIT_PREREALIZE: 208 case INTERFACE_DYNAMIC: 209 ++count; 210 break; 211 case INTERFACE_UNAVAILABLE: 212 break; 213 default: 214 assert(false); 215 break; 216 } 217 } 218 *pNumSupportedInterfaces = count; 219 result = SL_RESULT_SUCCESS; 220 } 221 return result; 222} 223 224 225/** \brief slQueryNumSupportedEngineInterfaces Function */ 226 227SL_API SLresult SLAPIENTRY slQueryNumSupportedEngineInterfaces(SLuint32 *pNumSupportedInterfaces) 228{ 229 SL_ENTER_GLOBAL 230 231 result = liQueryNumSupportedInterfaces(pNumSupportedInterfaces, 232 objectIDtoClass(SL_OBJECTID_ENGINE)); 233 234 SL_LEAVE_GLOBAL 235} 236 237 238/** Internal function for slQuerySupportedEngineInterfaces and xaQuerySupportedEngineInterfaces */ 239 240static SLresult liQuerySupportedInterfaces(SLuint32 index, SLInterfaceID *pInterfaceId, 241 const ClassTable *class__) 242{ 243 SLresult result; 244 if (NULL == pInterfaceId) { 245 result = SL_RESULT_PARAMETER_INVALID; 246 } else { 247 *pInterfaceId = NULL; 248 assert(NULL != class__); 249 result = SL_RESULT_PARAMETER_INVALID; // will be reset later 250 SLuint32 i; 251 for (i = 0; i < class__->mInterfaceCount; ++i) { 252 switch (class__->mInterfaces[i].mInterface) { 253 case INTERFACE_IMPLICIT: 254 case INTERFACE_IMPLICIT_PREREALIZE: 255 case INTERFACE_EXPLICIT: 256 case INTERFACE_EXPLICIT_PREREALIZE: 257 case INTERFACE_DYNAMIC: 258 break; 259 case INTERFACE_UNAVAILABLE: 260 continue; 261 default: 262 assert(false); 263 break; 264 } 265 if (index == 0) { 266 *pInterfaceId = &SL_IID_array[class__->mInterfaces[i].mMPH]; 267 result = SL_RESULT_SUCCESS; 268 break; 269 } 270 --index; 271 } 272 } 273 return result; 274} 275 276 277/** \brief slQuerySupportedEngineInterfaces Function */ 278 279SL_API SLresult SLAPIENTRY slQuerySupportedEngineInterfaces(SLuint32 index, 280 SLInterfaceID *pInterfaceId) 281{ 282 SL_ENTER_GLOBAL 283 284 result = liQuerySupportedInterfaces(index, pInterfaceId, objectIDtoClass(SL_OBJECTID_ENGINE)); 285 286 SL_LEAVE_GLOBAL 287} 288 289 290/** \brief xaCreateEngine Function */ 291 292XA_API XAresult XAAPIENTRY xaCreateEngine(XAObjectItf *pEngine, XAuint32 numOptions, 293 const XAEngineOption *pEngineOptions, XAuint32 numInterfaces, 294 const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired) 295{ 296 XA_ENTER_GLOBAL 297 298 result = liCreateEngine((SLObjectItf *) pEngine, numOptions, 299 (const SLEngineOption *) pEngineOptions, numInterfaces, 300 (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired, 301 objectIDtoClass(XA_OBJECTID_ENGINE)); 302 303 XA_LEAVE_GLOBAL 304} 305 306 307/** \brief xaQueryNumSupportedEngineInterfaces Function */ 308 309XA_API XAresult XAAPIENTRY xaQueryNumSupportedEngineInterfaces(XAuint32 *pNumSupportedInterfaces) 310{ 311 XA_ENTER_GLOBAL 312 313 result = liQueryNumSupportedInterfaces(pNumSupportedInterfaces, 314 objectIDtoClass(XA_OBJECTID_ENGINE)); 315 316 XA_LEAVE_GLOBAL 317} 318 319 320/** \brief xaQuerySupportedEngineInterfaces Function */ 321 322XA_API XAresult XAAPIENTRY xaQuerySupportedEngineInterfaces(XAuint32 index, 323 XAInterfaceID *pInterfaceId) 324{ 325 XA_ENTER_GLOBAL 326 327 result = liQuerySupportedInterfaces(index, (SLInterfaceID *) pInterfaceId, 328 objectIDtoClass(XA_OBJECTID_ENGINE)); 329 330 XA_LEAVE_GLOBAL 331} 332