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 /** \file CEngine.c Engine class */ 18 19 #include "sles_allinclusive.h" 20 #ifdef ANDROID 21 #include <binder/IServiceManager.h> 22 #include <utils/StrongPointer.h> 23 #include <audiomanager/AudioManager.h> 24 #include <audiomanager/IAudioManager.h> 25 #endif 26 27 /* This implementation supports at most one engine, identical for both OpenSL ES and OpenMAX AL */ 28 29 CEngine *theOneTrueEngine = NULL; 30 pthread_mutex_t theOneTrueMutex = PTHREAD_MUTEX_INITIALIZER; 31 unsigned theOneTrueRefCount = 0; 32 // incremented by slCreateEngine or xaCreateEngine, decremented by Object::Destroy on engine 33 34 35 /** \brief Called by dlopen when .so is loaded */ 36 37 __attribute__((constructor)) static void onDlOpen(void) 38 { 39 } 40 41 42 /** \brief Called by dlclose when .so is unloaded */ 43 44 __attribute__((destructor)) static void onDlClose(void) 45 { 46 // a memory barrier would be sufficient, but the mutex is easier 47 (void) pthread_mutex_lock(&theOneTrueMutex); 48 if ((NULL != theOneTrueEngine) || (0 < theOneTrueRefCount)) { 49 SL_LOGE("Object::Destroy omitted for engine %p", theOneTrueEngine); 50 } 51 (void) pthread_mutex_unlock(&theOneTrueMutex); 52 } 53 54 55 /** \brief Hook called by Object::Realize when an engine is realized */ 56 57 SLresult CEngine_Realize(void *self, SLboolean async) 58 { 59 CEngine *thiz = (CEngine *) self; 60 SLresult result; 61 #ifndef ANDROID 62 // create the sync thread 63 int err = pthread_create(&thiz->mSyncThread, (const pthread_attr_t *) NULL, sync_start, thiz); 64 result = err_to_result(err); 65 if (SL_RESULT_SUCCESS != result) 66 return result; 67 #endif 68 // initialize the thread pool for asynchronous operations 69 result = ThreadPool_init(&thiz->mThreadPool, 0, 0); 70 if (SL_RESULT_SUCCESS != result) { 71 thiz->mEngine.mShutdown = SL_BOOLEAN_TRUE; 72 (void) pthread_join(thiz->mSyncThread, (void **) NULL); 73 return result; 74 } 75 #ifdef ANDROID 76 // use checkService() to avoid blocking if audio service is not up yet 77 android::sp<android::IBinder> binder = 78 android::defaultServiceManager()->checkService(android::String16("audio")); 79 if (binder == 0) { 80 SL_LOGE("CEngine_Realize: binding to audio service failed, service up?"); 81 } else { 82 thiz->mAudioManager = android::interface_cast<android::IAudioManager>(binder); 83 } 84 #endif 85 #ifdef USE_SDL 86 SDL_open(&thiz->mEngine); 87 #endif 88 return SL_RESULT_SUCCESS; 89 } 90 91 92 /** \brief Hook called by Object::Resume when an engine is resumed */ 93 94 SLresult CEngine_Resume(void *self, SLboolean async) 95 { 96 return SL_RESULT_SUCCESS; 97 } 98 99 100 /** \brief Hook called by Object::Destroy when an engine is destroyed */ 101 102 void CEngine_Destroy(void *self) 103 { 104 CEngine *thiz = (CEngine *) self; 105 106 // Verify that there are no extant objects 107 unsigned instanceCount = thiz->mEngine.mInstanceCount; 108 unsigned instanceMask = thiz->mEngine.mInstanceMask; 109 if ((0 < instanceCount) || (0 != instanceMask)) { 110 SL_LOGE("Object::Destroy(%p) for engine ignored; %u total active objects", 111 thiz, instanceCount); 112 while (0 != instanceMask) { 113 unsigned i = ctz(instanceMask); 114 assert(MAX_INSTANCE > i); 115 SL_LOGE("Object::Destroy(%p) for engine ignored; active object ID %u at %p", 116 thiz, i + 1, thiz->mEngine.mInstances[i]); 117 instanceMask &= ~(1 << i); 118 } 119 } 120 121 // If engine was created but not realized, there will be no sync thread yet 122 pthread_t zero; 123 memset(&zero, 0, sizeof(pthread_t)); 124 if (0 != memcmp(&zero, &thiz->mSyncThread, sizeof(pthread_t))) { 125 126 // Announce to the sync thread that engine is shutting down; it polls so should see it soon 127 thiz->mEngine.mShutdown = SL_BOOLEAN_TRUE; 128 // Wait for the sync thread to acknowledge the shutdown 129 while (!thiz->mEngine.mShutdownAck) { 130 object_cond_wait(&thiz->mObject); 131 } 132 // The sync thread should have exited by now, so collect it by joining 133 (void) pthread_join(thiz->mSyncThread, (void **) NULL); 134 135 } 136 137 // Shutdown the thread pool used for asynchronous operations (there should not be any) 138 ThreadPool_deinit(&thiz->mThreadPool); 139 140 #if defined(ANDROID) 141 if (thiz->mAudioManager != 0) { 142 thiz->mAudioManager.clear(); 143 } 144 145 // free equalizer preset names 146 if (NULL != thiz->mEqPresetNames) { 147 for (unsigned i = 0; i < thiz->mEqNumPresets; ++i) { 148 if (NULL != thiz->mEqPresetNames[i]) { 149 delete[] thiz->mEqPresetNames[i]; 150 thiz->mEqPresetNames[i] = NULL; 151 } 152 } 153 delete[] thiz->mEqPresetNames; 154 thiz->mEqPresetNames = NULL; 155 } 156 thiz->mEqNumPresets = 0; 157 #endif 158 159 #ifdef USE_SDL 160 SDL_close(); 161 #endif 162 163 } 164 165 166 /** \brief Hook called by Object::Destroy before an engine is about to be destroyed */ 167 168 predestroy_t CEngine_PreDestroy(void *self) 169 { 170 predestroy_t ret; 171 (void) pthread_mutex_lock(&theOneTrueMutex); 172 assert(self == theOneTrueEngine); 173 switch (theOneTrueRefCount) { 174 case 0: 175 assert(false); 176 ret = predestroy_error; 177 break; 178 case 1: 179 ret = predestroy_ok; 180 break; 181 default: 182 --theOneTrueRefCount; 183 ret = predestroy_again; 184 break; 185 } 186 (void) pthread_mutex_unlock(&theOneTrueMutex); 187 return ret; 188 } 189 190 191 /** \brief Called by IObject::Destroy after engine is destroyed. The parameter refers to the 192 * previous engine, which is now undefined memory. 193 */ 194 195 void CEngine_Destroyed(CEngine *self) 196 { 197 int ok; 198 ok = pthread_mutex_lock(&theOneTrueMutex); 199 assert(0 == ok); 200 assert(self == theOneTrueEngine); 201 theOneTrueEngine = NULL; 202 assert(1 == theOneTrueRefCount); 203 theOneTrueRefCount = 0; 204 ok = pthread_mutex_unlock(&theOneTrueMutex); 205 assert(0 == ok); 206 } 207