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