1*bebae9c0SAndroid Build Coastguard Worker /*
2*bebae9c0SAndroid Build Coastguard Worker * Copyright (C) 2010 The Android Open Source Project
3*bebae9c0SAndroid Build Coastguard Worker *
4*bebae9c0SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*bebae9c0SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*bebae9c0SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*bebae9c0SAndroid Build Coastguard Worker *
8*bebae9c0SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*bebae9c0SAndroid Build Coastguard Worker *
10*bebae9c0SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*bebae9c0SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*bebae9c0SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*bebae9c0SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*bebae9c0SAndroid Build Coastguard Worker * limitations under the License.
15*bebae9c0SAndroid Build Coastguard Worker */
16*bebae9c0SAndroid Build Coastguard Worker
17*bebae9c0SAndroid Build Coastguard Worker /* DynamicInterfaceManagement implementation */
18*bebae9c0SAndroid Build Coastguard Worker
19*bebae9c0SAndroid Build Coastguard Worker #include "sles_allinclusive.h"
20*bebae9c0SAndroid Build Coastguard Worker
21*bebae9c0SAndroid Build Coastguard Worker
22*bebae9c0SAndroid Build Coastguard Worker // Called by a worker thread to handle an asynchronous AddInterface.
23*bebae9c0SAndroid Build Coastguard Worker // Parameter self is the DynamicInterface, and MPH specifies which interface to add.
24*bebae9c0SAndroid Build Coastguard Worker
HandleAdd(void * self,void * ignored,int MPH)25*bebae9c0SAndroid Build Coastguard Worker static void HandleAdd(void *self, void *ignored, int MPH)
26*bebae9c0SAndroid Build Coastguard Worker {
27*bebae9c0SAndroid Build Coastguard Worker
28*bebae9c0SAndroid Build Coastguard Worker // validate input parameters
29*bebae9c0SAndroid Build Coastguard Worker IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self;
30*bebae9c0SAndroid Build Coastguard Worker assert(NULL != thiz);
31*bebae9c0SAndroid Build Coastguard Worker IObject *thisObject = InterfaceToIObject(thiz);
32*bebae9c0SAndroid Build Coastguard Worker assert(NULL != thisObject);
33*bebae9c0SAndroid Build Coastguard Worker assert(0 <= MPH && MPH < MPH_MAX);
34*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thisObject->mClass;
35*bebae9c0SAndroid Build Coastguard Worker assert(NULL != clazz);
36*bebae9c0SAndroid Build Coastguard Worker int index = clazz->mMPH_to_index[MPH];
37*bebae9c0SAndroid Build Coastguard Worker assert(0 <= index && index < (int) clazz->mInterfaceCount);
38*bebae9c0SAndroid Build Coastguard Worker SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
39*bebae9c0SAndroid Build Coastguard Worker SLresult result;
40*bebae9c0SAndroid Build Coastguard Worker
41*bebae9c0SAndroid Build Coastguard Worker // check interface state
42*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
43*bebae9c0SAndroid Build Coastguard Worker SLuint8 state = *interfaceStateP;
44*bebae9c0SAndroid Build Coastguard Worker switch (state) {
45*bebae9c0SAndroid Build Coastguard Worker
46*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_1: // normal case
47*bebae9c0SAndroid Build Coastguard Worker {
48*bebae9c0SAndroid Build Coastguard Worker // change state to indicate we are now adding the interface
49*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_ADDING_2;
50*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
51*bebae9c0SAndroid Build Coastguard Worker
52*bebae9c0SAndroid Build Coastguard Worker // this section runs with mutex unlocked
53*bebae9c0SAndroid Build Coastguard Worker const struct iid_vtable *x = &clazz->mInterfaces[index];
54*bebae9c0SAndroid Build Coastguard Worker size_t offset = x->mOffset;
55*bebae9c0SAndroid Build Coastguard Worker void *thisItf = (char *) thisObject + offset;
56*bebae9c0SAndroid Build Coastguard Worker BoolHook expose = MPH_init_table[MPH].mExpose;
57*bebae9c0SAndroid Build Coastguard Worker // call the optional expose hook
58*bebae9c0SAndroid Build Coastguard Worker if ((NULL == expose) || (*expose)(thisItf)) {
59*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
60*bebae9c0SAndroid Build Coastguard Worker } else {
61*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_FEATURE_UNSUPPORTED;
62*bebae9c0SAndroid Build Coastguard Worker }
63*bebae9c0SAndroid Build Coastguard Worker
64*bebae9c0SAndroid Build Coastguard Worker // re-lock mutex to update state
65*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
66*bebae9c0SAndroid Build Coastguard Worker assert(INTERFACE_ADDING_2 == *interfaceStateP);
67*bebae9c0SAndroid Build Coastguard Worker if (SL_RESULT_SUCCESS == result) {
68*bebae9c0SAndroid Build Coastguard Worker ((size_t *) thisItf)[0] ^= ~0;
69*bebae9c0SAndroid Build Coastguard Worker state = INTERFACE_ADDED;
70*bebae9c0SAndroid Build Coastguard Worker } else {
71*bebae9c0SAndroid Build Coastguard Worker state = INTERFACE_INITIALIZED;
72*bebae9c0SAndroid Build Coastguard Worker }
73*bebae9c0SAndroid Build Coastguard Worker }
74*bebae9c0SAndroid Build Coastguard Worker break;
75*bebae9c0SAndroid Build Coastguard Worker
76*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_1A: // operation was aborted while on work queue
77*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_OPERATION_ABORTED;
78*bebae9c0SAndroid Build Coastguard Worker state = INTERFACE_INITIALIZED;
79*bebae9c0SAndroid Build Coastguard Worker break;
80*bebae9c0SAndroid Build Coastguard Worker
81*bebae9c0SAndroid Build Coastguard Worker default: // impossible
82*bebae9c0SAndroid Build Coastguard Worker assert(SL_BOOLEAN_FALSE);
83*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_INTERNAL_ERROR;
84*bebae9c0SAndroid Build Coastguard Worker break;
85*bebae9c0SAndroid Build Coastguard Worker
86*bebae9c0SAndroid Build Coastguard Worker }
87*bebae9c0SAndroid Build Coastguard Worker
88*bebae9c0SAndroid Build Coastguard Worker // mutex is locked, update state
89*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = state;
90*bebae9c0SAndroid Build Coastguard Worker
91*bebae9c0SAndroid Build Coastguard Worker // Make a copy of these, so we can call the callback with mutex unlocked
92*bebae9c0SAndroid Build Coastguard Worker slDynamicInterfaceManagementCallback callback = thiz->mCallback;
93*bebae9c0SAndroid Build Coastguard Worker void *context = thiz->mContext;
94*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
95*bebae9c0SAndroid Build Coastguard Worker
96*bebae9c0SAndroid Build Coastguard Worker // Note that the mutex is unlocked during the callback
97*bebae9c0SAndroid Build Coastguard Worker if (NULL != callback) {
98*bebae9c0SAndroid Build Coastguard Worker const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID
99*bebae9c0SAndroid Build Coastguard Worker (*callback)(&thiz->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid);
100*bebae9c0SAndroid Build Coastguard Worker }
101*bebae9c0SAndroid Build Coastguard Worker
102*bebae9c0SAndroid Build Coastguard Worker }
103*bebae9c0SAndroid Build Coastguard Worker
104*bebae9c0SAndroid Build Coastguard Worker
IDynamicInterfaceManagement_AddInterface(SLDynamicInterfaceManagementItf self,const SLInterfaceID iid,SLboolean async)105*bebae9c0SAndroid Build Coastguard Worker static SLresult IDynamicInterfaceManagement_AddInterface(SLDynamicInterfaceManagementItf self,
106*bebae9c0SAndroid Build Coastguard Worker const SLInterfaceID iid, SLboolean async)
107*bebae9c0SAndroid Build Coastguard Worker {
108*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
109*bebae9c0SAndroid Build Coastguard Worker
110*bebae9c0SAndroid Build Coastguard Worker // validate input parameters
111*bebae9c0SAndroid Build Coastguard Worker if (NULL == iid) {
112*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PARAMETER_INVALID;
113*bebae9c0SAndroid Build Coastguard Worker } else {
114*bebae9c0SAndroid Build Coastguard Worker IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self;
115*bebae9c0SAndroid Build Coastguard Worker IObject *thisObject = InterfaceToIObject(thiz);
116*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thisObject->mClass;
117*bebae9c0SAndroid Build Coastguard Worker int MPH, index;
118*bebae9c0SAndroid Build Coastguard Worker if ((0 > (MPH = IID_to_MPH(iid))) ||
119*bebae9c0SAndroid Build Coastguard Worker // no need to check for an initialization hook
120*bebae9c0SAndroid Build Coastguard Worker // (NULL == MPH_init_table[MPH].mInit) ||
121*bebae9c0SAndroid Build Coastguard Worker (0 > (index = clazz->mMPH_to_index[MPH]))) {
122*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_FEATURE_UNSUPPORTED;
123*bebae9c0SAndroid Build Coastguard Worker } else {
124*bebae9c0SAndroid Build Coastguard Worker assert(index < (int) clazz->mInterfaceCount);
125*bebae9c0SAndroid Build Coastguard Worker SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
126*bebae9c0SAndroid Build Coastguard Worker
127*bebae9c0SAndroid Build Coastguard Worker // check interface state
128*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
129*bebae9c0SAndroid Build Coastguard Worker switch (*interfaceStateP) {
130*bebae9c0SAndroid Build Coastguard Worker
131*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_INITIALIZED: // normal case
132*bebae9c0SAndroid Build Coastguard Worker if (async) {
133*bebae9c0SAndroid Build Coastguard Worker // Asynchronous: mark operation pending and cancellable
134*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_ADDING_1;
135*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
136*bebae9c0SAndroid Build Coastguard Worker
137*bebae9c0SAndroid Build Coastguard Worker // this section runs with mutex unlocked
138*bebae9c0SAndroid Build Coastguard Worker result = ThreadPool_add_ppi(&thisObject->mEngine->mThreadPool, HandleAdd, thiz,
139*bebae9c0SAndroid Build Coastguard Worker NULL, MPH);
140*bebae9c0SAndroid Build Coastguard Worker if (SL_RESULT_SUCCESS != result) {
141*bebae9c0SAndroid Build Coastguard Worker // Engine was destroyed during add, or insufficient memory,
142*bebae9c0SAndroid Build Coastguard Worker // so restore mInterfaceStates state to prior value
143*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
144*bebae9c0SAndroid Build Coastguard Worker switch (*interfaceStateP) {
145*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_1: // normal
146*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDING_1A: // operation aborted while mutex unlocked
147*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_INITIALIZED;
148*bebae9c0SAndroid Build Coastguard Worker break;
149*bebae9c0SAndroid Build Coastguard Worker default: // unexpected
150*bebae9c0SAndroid Build Coastguard Worker // leave state alone
151*bebae9c0SAndroid Build Coastguard Worker break;
152*bebae9c0SAndroid Build Coastguard Worker }
153*bebae9c0SAndroid Build Coastguard Worker }
154*bebae9c0SAndroid Build Coastguard Worker
155*bebae9c0SAndroid Build Coastguard Worker } else {
156*bebae9c0SAndroid Build Coastguard Worker // Synchronous: mark operation pending to prevent duplication
157*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_ADDING_2;
158*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
159*bebae9c0SAndroid Build Coastguard Worker
160*bebae9c0SAndroid Build Coastguard Worker // this section runs with mutex unlocked
161*bebae9c0SAndroid Build Coastguard Worker const struct iid_vtable *x = &clazz->mInterfaces[index];
162*bebae9c0SAndroid Build Coastguard Worker size_t offset = x->mOffset;
163*bebae9c0SAndroid Build Coastguard Worker void *thisItf = (char *) thisObject + offset;
164*bebae9c0SAndroid Build Coastguard Worker // call the optional expose hook
165*bebae9c0SAndroid Build Coastguard Worker BoolHook expose = MPH_init_table[MPH].mExpose;
166*bebae9c0SAndroid Build Coastguard Worker if ((NULL == expose) || (*expose)(thisItf)) {
167*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
168*bebae9c0SAndroid Build Coastguard Worker } else {
169*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_FEATURE_UNSUPPORTED;
170*bebae9c0SAndroid Build Coastguard Worker }
171*bebae9c0SAndroid Build Coastguard Worker
172*bebae9c0SAndroid Build Coastguard Worker // re-lock mutex to update state
173*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
174*bebae9c0SAndroid Build Coastguard Worker assert(INTERFACE_ADDING_2 == *interfaceStateP);
175*bebae9c0SAndroid Build Coastguard Worker if (SL_RESULT_SUCCESS == result) {
176*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_ADDED;
177*bebae9c0SAndroid Build Coastguard Worker } else {
178*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_INITIALIZED;
179*bebae9c0SAndroid Build Coastguard Worker }
180*bebae9c0SAndroid Build Coastguard Worker }
181*bebae9c0SAndroid Build Coastguard Worker
182*bebae9c0SAndroid Build Coastguard Worker // mutex is still locked
183*bebae9c0SAndroid Build Coastguard Worker break;
184*bebae9c0SAndroid Build Coastguard Worker
185*bebae9c0SAndroid Build Coastguard Worker default: // disallow adding of (partially) initialized interfaces
186*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PRECONDITIONS_VIOLATED;
187*bebae9c0SAndroid Build Coastguard Worker break;
188*bebae9c0SAndroid Build Coastguard Worker
189*bebae9c0SAndroid Build Coastguard Worker }
190*bebae9c0SAndroid Build Coastguard Worker
191*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
192*bebae9c0SAndroid Build Coastguard Worker
193*bebae9c0SAndroid Build Coastguard Worker }
194*bebae9c0SAndroid Build Coastguard Worker }
195*bebae9c0SAndroid Build Coastguard Worker
196*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
197*bebae9c0SAndroid Build Coastguard Worker }
198*bebae9c0SAndroid Build Coastguard Worker
199*bebae9c0SAndroid Build Coastguard Worker
IDynamicInterfaceManagement_RemoveInterface(SLDynamicInterfaceManagementItf self,const SLInterfaceID iid)200*bebae9c0SAndroid Build Coastguard Worker static SLresult IDynamicInterfaceManagement_RemoveInterface(
201*bebae9c0SAndroid Build Coastguard Worker SLDynamicInterfaceManagementItf self, const SLInterfaceID iid)
202*bebae9c0SAndroid Build Coastguard Worker {
203*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
204*bebae9c0SAndroid Build Coastguard Worker
205*bebae9c0SAndroid Build Coastguard Worker #if USE_PROFILES & USE_PROFILES_BASE
206*bebae9c0SAndroid Build Coastguard Worker // validate input parameters
207*bebae9c0SAndroid Build Coastguard Worker if (NULL == iid) {
208*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PARAMETER_INVALID;
209*bebae9c0SAndroid Build Coastguard Worker } else {
210*bebae9c0SAndroid Build Coastguard Worker IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self;
211*bebae9c0SAndroid Build Coastguard Worker IObject *thisObject = InterfaceToIObject(thiz);
212*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thisObject->mClass;
213*bebae9c0SAndroid Build Coastguard Worker int MPH, index;
214*bebae9c0SAndroid Build Coastguard Worker if ((0 > (MPH = IID_to_MPH(iid))) ||
215*bebae9c0SAndroid Build Coastguard Worker // no need to check for an initialization hook
216*bebae9c0SAndroid Build Coastguard Worker // (NULL == MPH_init_table[MPH].mInit) ||
217*bebae9c0SAndroid Build Coastguard Worker (0 > (index = clazz->mMPH_to_index[MPH]))) {
218*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PRECONDITIONS_VIOLATED;
219*bebae9c0SAndroid Build Coastguard Worker } else {
220*bebae9c0SAndroid Build Coastguard Worker SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
221*bebae9c0SAndroid Build Coastguard Worker
222*bebae9c0SAndroid Build Coastguard Worker // check interface state
223*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
224*bebae9c0SAndroid Build Coastguard Worker switch (*interfaceStateP) {
225*bebae9c0SAndroid Build Coastguard Worker
226*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_ADDED: // normal cases
227*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_SUSPENDED:
228*bebae9c0SAndroid Build Coastguard Worker {
229*bebae9c0SAndroid Build Coastguard Worker // Compute address of the interface
230*bebae9c0SAndroid Build Coastguard Worker const struct iid_vtable *x = &clazz->mInterfaces[index];
231*bebae9c0SAndroid Build Coastguard Worker size_t offset = x->mOffset;
232*bebae9c0SAndroid Build Coastguard Worker void *thisItf = (char *) thisObject + offset;
233*bebae9c0SAndroid Build Coastguard Worker
234*bebae9c0SAndroid Build Coastguard Worker // Mark operation pending (not necessary; remove is synchronous with mutex locked)
235*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_REMOVING;
236*bebae9c0SAndroid Build Coastguard Worker
237*bebae9c0SAndroid Build Coastguard Worker // Check if application ever called Object::GetInterface
238*bebae9c0SAndroid Build Coastguard Worker unsigned mask = 1 << index;
239*bebae9c0SAndroid Build Coastguard Worker if (thisObject->mGottenMask & mask) {
240*bebae9c0SAndroid Build Coastguard Worker thisObject->mGottenMask &= ~mask;
241*bebae9c0SAndroid Build Coastguard Worker // This trickery invalidates the v-table
242*bebae9c0SAndroid Build Coastguard Worker ((size_t *) thisItf)[0] ^= ~0;
243*bebae9c0SAndroid Build Coastguard Worker }
244*bebae9c0SAndroid Build Coastguard Worker
245*bebae9c0SAndroid Build Coastguard Worker // The remove hook is called with mutex locked
246*bebae9c0SAndroid Build Coastguard Worker VoidHook remove = MPH_init_table[MPH].mRemove;
247*bebae9c0SAndroid Build Coastguard Worker if (NULL != remove) {
248*bebae9c0SAndroid Build Coastguard Worker (*remove)(thisItf);
249*bebae9c0SAndroid Build Coastguard Worker }
250*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
251*bebae9c0SAndroid Build Coastguard Worker
252*bebae9c0SAndroid Build Coastguard Worker assert(INTERFACE_REMOVING == *interfaceStateP);
253*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_INITIALIZED;
254*bebae9c0SAndroid Build Coastguard Worker }
255*bebae9c0SAndroid Build Coastguard Worker
256*bebae9c0SAndroid Build Coastguard Worker // mutex is still locked
257*bebae9c0SAndroid Build Coastguard Worker break;
258*bebae9c0SAndroid Build Coastguard Worker
259*bebae9c0SAndroid Build Coastguard Worker default:
260*bebae9c0SAndroid Build Coastguard Worker // disallow removal of non-dynamic interfaces, or interfaces which are
261*bebae9c0SAndroid Build Coastguard Worker // currently being resumed (will not auto-cancel an asynchronous resume)
262*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PRECONDITIONS_VIOLATED;
263*bebae9c0SAndroid Build Coastguard Worker break;
264*bebae9c0SAndroid Build Coastguard Worker
265*bebae9c0SAndroid Build Coastguard Worker }
266*bebae9c0SAndroid Build Coastguard Worker
267*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
268*bebae9c0SAndroid Build Coastguard Worker }
269*bebae9c0SAndroid Build Coastguard Worker }
270*bebae9c0SAndroid Build Coastguard Worker #else
271*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_FEATURE_UNSUPPORTED;
272*bebae9c0SAndroid Build Coastguard Worker #endif
273*bebae9c0SAndroid Build Coastguard Worker
274*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
275*bebae9c0SAndroid Build Coastguard Worker }
276*bebae9c0SAndroid Build Coastguard Worker
277*bebae9c0SAndroid Build Coastguard Worker
278*bebae9c0SAndroid Build Coastguard Worker // Called by a worker thread to handle an asynchronous ResumeInterface.
279*bebae9c0SAndroid Build Coastguard Worker // Parameter self is the DynamicInterface, and MPH specifies which interface to resume.
280*bebae9c0SAndroid Build Coastguard Worker
HandleResume(void * self,void * ignored,int MPH)281*bebae9c0SAndroid Build Coastguard Worker static void HandleResume(void *self, void *ignored, int MPH)
282*bebae9c0SAndroid Build Coastguard Worker {
283*bebae9c0SAndroid Build Coastguard Worker
284*bebae9c0SAndroid Build Coastguard Worker // validate input parameters
285*bebae9c0SAndroid Build Coastguard Worker IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self;
286*bebae9c0SAndroid Build Coastguard Worker assert(NULL != thiz);
287*bebae9c0SAndroid Build Coastguard Worker IObject *thisObject = InterfaceToIObject(thiz);
288*bebae9c0SAndroid Build Coastguard Worker assert(NULL != thisObject);
289*bebae9c0SAndroid Build Coastguard Worker assert(0 <= MPH && MPH < MPH_MAX);
290*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thisObject->mClass;
291*bebae9c0SAndroid Build Coastguard Worker assert(NULL != clazz);
292*bebae9c0SAndroid Build Coastguard Worker int index = clazz->mMPH_to_index[MPH];
293*bebae9c0SAndroid Build Coastguard Worker assert(0 <= index && index < (int) clazz->mInterfaceCount);
294*bebae9c0SAndroid Build Coastguard Worker SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
295*bebae9c0SAndroid Build Coastguard Worker SLresult result;
296*bebae9c0SAndroid Build Coastguard Worker
297*bebae9c0SAndroid Build Coastguard Worker // check interface state
298*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
299*bebae9c0SAndroid Build Coastguard Worker SLuint8 state = *interfaceStateP;
300*bebae9c0SAndroid Build Coastguard Worker switch (state) {
301*bebae9c0SAndroid Build Coastguard Worker
302*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_1: // normal case
303*bebae9c0SAndroid Build Coastguard Worker {
304*bebae9c0SAndroid Build Coastguard Worker // change state to indicate we are now resuming the interface
305*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_RESUMING_2;
306*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
307*bebae9c0SAndroid Build Coastguard Worker
308*bebae9c0SAndroid Build Coastguard Worker // this section runs with mutex unlocked
309*bebae9c0SAndroid Build Coastguard Worker const struct iid_vtable *x = &clazz->mInterfaces[index];
310*bebae9c0SAndroid Build Coastguard Worker size_t offset = x->mOffset;
311*bebae9c0SAndroid Build Coastguard Worker void *thisItf = (char *) thisObject + offset;
312*bebae9c0SAndroid Build Coastguard Worker VoidHook resume = MPH_init_table[MPH].mResume;
313*bebae9c0SAndroid Build Coastguard Worker if (NULL != resume) {
314*bebae9c0SAndroid Build Coastguard Worker (*resume)(thisItf);
315*bebae9c0SAndroid Build Coastguard Worker }
316*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
317*bebae9c0SAndroid Build Coastguard Worker
318*bebae9c0SAndroid Build Coastguard Worker // re-lock mutex to update state
319*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
320*bebae9c0SAndroid Build Coastguard Worker assert(INTERFACE_RESUMING_2 == *interfaceStateP);
321*bebae9c0SAndroid Build Coastguard Worker state = INTERFACE_ADDED;
322*bebae9c0SAndroid Build Coastguard Worker }
323*bebae9c0SAndroid Build Coastguard Worker break;
324*bebae9c0SAndroid Build Coastguard Worker
325*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_1A: // operation was aborted while on work queue
326*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_OPERATION_ABORTED;
327*bebae9c0SAndroid Build Coastguard Worker state = INTERFACE_SUSPENDED;
328*bebae9c0SAndroid Build Coastguard Worker break;
329*bebae9c0SAndroid Build Coastguard Worker
330*bebae9c0SAndroid Build Coastguard Worker default: // impossible
331*bebae9c0SAndroid Build Coastguard Worker assert(SL_BOOLEAN_FALSE);
332*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_INTERNAL_ERROR;
333*bebae9c0SAndroid Build Coastguard Worker break;
334*bebae9c0SAndroid Build Coastguard Worker
335*bebae9c0SAndroid Build Coastguard Worker }
336*bebae9c0SAndroid Build Coastguard Worker
337*bebae9c0SAndroid Build Coastguard Worker // mutex is locked, update state
338*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = state;
339*bebae9c0SAndroid Build Coastguard Worker
340*bebae9c0SAndroid Build Coastguard Worker // Make a copy of these, so we can call the callback with mutex unlocked
341*bebae9c0SAndroid Build Coastguard Worker slDynamicInterfaceManagementCallback callback = thiz->mCallback;
342*bebae9c0SAndroid Build Coastguard Worker void *context = thiz->mContext;
343*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
344*bebae9c0SAndroid Build Coastguard Worker
345*bebae9c0SAndroid Build Coastguard Worker // Note that the mutex is unlocked during the callback
346*bebae9c0SAndroid Build Coastguard Worker if (NULL != callback) {
347*bebae9c0SAndroid Build Coastguard Worker const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID
348*bebae9c0SAndroid Build Coastguard Worker (*callback)(&thiz->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid);
349*bebae9c0SAndroid Build Coastguard Worker }
350*bebae9c0SAndroid Build Coastguard Worker }
351*bebae9c0SAndroid Build Coastguard Worker
352*bebae9c0SAndroid Build Coastguard Worker
IDynamicInterfaceManagement_ResumeInterface(SLDynamicInterfaceManagementItf self,const SLInterfaceID iid,SLboolean async)353*bebae9c0SAndroid Build Coastguard Worker static SLresult IDynamicInterfaceManagement_ResumeInterface(SLDynamicInterfaceManagementItf self,
354*bebae9c0SAndroid Build Coastguard Worker const SLInterfaceID iid, SLboolean async)
355*bebae9c0SAndroid Build Coastguard Worker {
356*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
357*bebae9c0SAndroid Build Coastguard Worker
358*bebae9c0SAndroid Build Coastguard Worker // validate input parameters
359*bebae9c0SAndroid Build Coastguard Worker if (NULL == iid) {
360*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PARAMETER_INVALID;
361*bebae9c0SAndroid Build Coastguard Worker } else {
362*bebae9c0SAndroid Build Coastguard Worker IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self;
363*bebae9c0SAndroid Build Coastguard Worker IObject *thisObject = InterfaceToIObject(thiz);
364*bebae9c0SAndroid Build Coastguard Worker const ClassTable *clazz = thisObject->mClass;
365*bebae9c0SAndroid Build Coastguard Worker int MPH, index;
366*bebae9c0SAndroid Build Coastguard Worker if ((0 > (MPH = IID_to_MPH(iid))) ||
367*bebae9c0SAndroid Build Coastguard Worker // no need to check for an initialization hook
368*bebae9c0SAndroid Build Coastguard Worker // (NULL == MPH_init_table[MPH].mInit) ||
369*bebae9c0SAndroid Build Coastguard Worker (0 > (index = clazz->mMPH_to_index[MPH]))) {
370*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PRECONDITIONS_VIOLATED;
371*bebae9c0SAndroid Build Coastguard Worker } else {
372*bebae9c0SAndroid Build Coastguard Worker assert(index < (int) clazz->mInterfaceCount);
373*bebae9c0SAndroid Build Coastguard Worker SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
374*bebae9c0SAndroid Build Coastguard Worker
375*bebae9c0SAndroid Build Coastguard Worker // check interface state
376*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
377*bebae9c0SAndroid Build Coastguard Worker switch (*interfaceStateP) {
378*bebae9c0SAndroid Build Coastguard Worker
379*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_SUSPENDED: // normal case
380*bebae9c0SAndroid Build Coastguard Worker if (async) {
381*bebae9c0SAndroid Build Coastguard Worker // Asynchronous: mark operation pending and cancellable
382*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_RESUMING_1;
383*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
384*bebae9c0SAndroid Build Coastguard Worker
385*bebae9c0SAndroid Build Coastguard Worker // this section runs with mutex unlocked
386*bebae9c0SAndroid Build Coastguard Worker result = ThreadPool_add_ppi(&thisObject->mEngine->mThreadPool, HandleResume,
387*bebae9c0SAndroid Build Coastguard Worker thiz, NULL, MPH);
388*bebae9c0SAndroid Build Coastguard Worker if (SL_RESULT_SUCCESS != result) {
389*bebae9c0SAndroid Build Coastguard Worker // Engine was destroyed during resume, or insufficient memory,
390*bebae9c0SAndroid Build Coastguard Worker // so restore mInterfaceStates state to prior value
391*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
392*bebae9c0SAndroid Build Coastguard Worker switch (*interfaceStateP) {
393*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_1: // normal
394*bebae9c0SAndroid Build Coastguard Worker case INTERFACE_RESUMING_1A: // operation aborted while mutex unlocked
395*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_SUSPENDED;
396*bebae9c0SAndroid Build Coastguard Worker break;
397*bebae9c0SAndroid Build Coastguard Worker default: // unexpected
398*bebae9c0SAndroid Build Coastguard Worker // leave state alone
399*bebae9c0SAndroid Build Coastguard Worker break;
400*bebae9c0SAndroid Build Coastguard Worker }
401*bebae9c0SAndroid Build Coastguard Worker }
402*bebae9c0SAndroid Build Coastguard Worker
403*bebae9c0SAndroid Build Coastguard Worker } else {
404*bebae9c0SAndroid Build Coastguard Worker // Synchronous: mark operation pending to prevent duplication
405*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_RESUMING_2;
406*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
407*bebae9c0SAndroid Build Coastguard Worker
408*bebae9c0SAndroid Build Coastguard Worker // this section runs with mutex unlocked
409*bebae9c0SAndroid Build Coastguard Worker const struct iid_vtable *x = &clazz->mInterfaces[index];
410*bebae9c0SAndroid Build Coastguard Worker size_t offset = x->mOffset;
411*bebae9c0SAndroid Build Coastguard Worker void *thisItf = (char *) thiz + offset;
412*bebae9c0SAndroid Build Coastguard Worker VoidHook resume = MPH_init_table[MPH].mResume;
413*bebae9c0SAndroid Build Coastguard Worker if (NULL != resume) {
414*bebae9c0SAndroid Build Coastguard Worker (*resume)(thisItf);
415*bebae9c0SAndroid Build Coastguard Worker }
416*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
417*bebae9c0SAndroid Build Coastguard Worker
418*bebae9c0SAndroid Build Coastguard Worker // re-lock mutex to update state
419*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
420*bebae9c0SAndroid Build Coastguard Worker assert(INTERFACE_RESUMING_2 == *interfaceStateP);
421*bebae9c0SAndroid Build Coastguard Worker *interfaceStateP = INTERFACE_ADDED;
422*bebae9c0SAndroid Build Coastguard Worker }
423*bebae9c0SAndroid Build Coastguard Worker
424*bebae9c0SAndroid Build Coastguard Worker // mutex is now locked
425*bebae9c0SAndroid Build Coastguard Worker break;
426*bebae9c0SAndroid Build Coastguard Worker
427*bebae9c0SAndroid Build Coastguard Worker default: // disallow resumption of non-suspended interfaces
428*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_PRECONDITIONS_VIOLATED;
429*bebae9c0SAndroid Build Coastguard Worker break;
430*bebae9c0SAndroid Build Coastguard Worker }
431*bebae9c0SAndroid Build Coastguard Worker
432*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
433*bebae9c0SAndroid Build Coastguard Worker }
434*bebae9c0SAndroid Build Coastguard Worker }
435*bebae9c0SAndroid Build Coastguard Worker
436*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
437*bebae9c0SAndroid Build Coastguard Worker }
438*bebae9c0SAndroid Build Coastguard Worker
439*bebae9c0SAndroid Build Coastguard Worker
IDynamicInterfaceManagement_RegisterCallback(SLDynamicInterfaceManagementItf self,slDynamicInterfaceManagementCallback callback,void * pContext)440*bebae9c0SAndroid Build Coastguard Worker static SLresult IDynamicInterfaceManagement_RegisterCallback(SLDynamicInterfaceManagementItf self,
441*bebae9c0SAndroid Build Coastguard Worker slDynamicInterfaceManagementCallback callback, void *pContext)
442*bebae9c0SAndroid Build Coastguard Worker {
443*bebae9c0SAndroid Build Coastguard Worker SL_ENTER_INTERFACE
444*bebae9c0SAndroid Build Coastguard Worker
445*bebae9c0SAndroid Build Coastguard Worker IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self;
446*bebae9c0SAndroid Build Coastguard Worker IObject *thisObject = InterfaceToIObject(thiz);
447*bebae9c0SAndroid Build Coastguard Worker object_lock_exclusive(thisObject);
448*bebae9c0SAndroid Build Coastguard Worker thiz->mCallback = callback;
449*bebae9c0SAndroid Build Coastguard Worker thiz->mContext = pContext;
450*bebae9c0SAndroid Build Coastguard Worker object_unlock_exclusive(thisObject);
451*bebae9c0SAndroid Build Coastguard Worker result = SL_RESULT_SUCCESS;
452*bebae9c0SAndroid Build Coastguard Worker
453*bebae9c0SAndroid Build Coastguard Worker SL_LEAVE_INTERFACE
454*bebae9c0SAndroid Build Coastguard Worker }
455*bebae9c0SAndroid Build Coastguard Worker
456*bebae9c0SAndroid Build Coastguard Worker
457*bebae9c0SAndroid Build Coastguard Worker static const struct SLDynamicInterfaceManagementItf_ IDynamicInterfaceManagement_Itf = {
458*bebae9c0SAndroid Build Coastguard Worker IDynamicInterfaceManagement_AddInterface,
459*bebae9c0SAndroid Build Coastguard Worker IDynamicInterfaceManagement_RemoveInterface,
460*bebae9c0SAndroid Build Coastguard Worker IDynamicInterfaceManagement_ResumeInterface,
461*bebae9c0SAndroid Build Coastguard Worker IDynamicInterfaceManagement_RegisterCallback
462*bebae9c0SAndroid Build Coastguard Worker };
463*bebae9c0SAndroid Build Coastguard Worker
IDynamicInterfaceManagement_init(void * self)464*bebae9c0SAndroid Build Coastguard Worker void IDynamicInterfaceManagement_init(void *self)
465*bebae9c0SAndroid Build Coastguard Worker {
466*bebae9c0SAndroid Build Coastguard Worker IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self;
467*bebae9c0SAndroid Build Coastguard Worker thiz->mItf = &IDynamicInterfaceManagement_Itf;
468*bebae9c0SAndroid Build Coastguard Worker thiz->mCallback = NULL;
469*bebae9c0SAndroid Build Coastguard Worker thiz->mContext = NULL;
470*bebae9c0SAndroid Build Coastguard Worker }
471