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