entry.c revision 4ee246c55533bdab8ab5fa0f0581744fe58e7c91
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
28LI_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=%lu 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=%lu data=%lu",
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);
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
180LI_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
215LI_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