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