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