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