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
27LI_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
178LI_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
213LI_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