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 
liCreateEngine(SLObjectItf * pEngine,SLuint32 numOptions,const SLEngineOption * pEngineOptions,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired,const ClassTable * pCEngine_class)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 
liQueryNumSupportedInterfaces(SLuint32 * pNumSupportedInterfaces,const ClassTable * clazz)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 
liQuerySupportedInterfaces(SLuint32 index,SLInterfaceID * pInterfaceId,const ClassTable * clazz)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