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