IDynamicInterfaceManagement.cpp revision e5d006b298ce7683d66f7ec86136403cf5fb20d6
161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*
261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * you may not use this file except in compliance with the License.
661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * You may obtain a copy of the License at
761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
1061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Unless required by applicable law or agreed to in writing, software
1161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
1261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * See the License for the specific language governing permissions and
1461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * limitations under the License.
1561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten */
1661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
1761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* DynamicInterfaceManagement implementation */
1861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
1961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#include "sles_allinclusive.h"
2061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
21ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
22510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous AddInterface.
23510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the DynamicInterface, and MPH specifies which interface to add.
24510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
25510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleAdd(void *self, int MPH)
26510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{
27510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
28510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
29d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
30d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    assert(NULL != this);
31d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IObject *thisObject = InterfaceToIObject(this);
32510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != thisObject);
33510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(0 <= MPH && MPH < MPH_MAX);
34510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    const ClassTable *class__ = thisObject->mClass;
35510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != class__);
36510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    int index = class__->mMPH_to_index[MPH];
37510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(0 <= index && index < (int) class__->mInterfaceCount);
38510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
39510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLresult result;
40510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
41510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // check interface state
42510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_exclusive(thisObject);
43276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    SLuint8 state = *interfaceStateP;
44510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (state) {
45510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
46510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_ADDING_1:    // normal case
47510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        {
48510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // change state to indicate we are now adding the interface
49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        *interfaceStateP = INTERFACE_ADDING_2;
50510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_unlock_exclusive(thisObject);
51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
52510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // this section runs with mutex unlocked
53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const struct iid_vtable *x = &class__->mInterfaces[index];
54510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        size_t offset = x->mOffset;
55510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        void *thisItf = (char *) thisObject + offset;
56510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ?
57510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            class__->mSize : x[1].mOffset) - offset;
58510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        memset(thisItf, 0, size);
59d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        // Will never add IObject, so [1] is always defined
60510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        ((void **) thisItf)[1] = thisObject;
61510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        VoidHook init = MPH_init_table[MPH].mInit;
62e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten        if (NULL != init) {
63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            (*init)(thisItf);
64e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten            ((size_t *) thisItf)[0] ^= ~0;
65e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten        }
66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_SUCCESS;
67510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
68510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // re-lock mutex to update state
69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_lock_exclusive(thisObject);
70510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(INTERFACE_ADDING_2 == *interfaceStateP);
71510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_ADDED;
72510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        }
73510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
74510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
75510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_ADDING_1A:   // operation was aborted while on work queue
76510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_OPERATION_ABORTED;
77510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_UNINITIALIZED;
78510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
79510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
80510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:                    // impossible
81510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(SL_BOOLEAN_FALSE);
82510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_INTERNAL_ERROR;
83510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
84510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
85510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
86510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
87510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // mutex is locked, update state
88510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    *interfaceStateP = state;
89510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
90510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Make a copy of these, so we can call the callback with mutex unlocked
91d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    slDynamicInterfaceManagementCallback callback = this->mCallback;
92d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    void *context = this->mContext;
93510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_exclusive(thisObject);
94510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
95510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Note that the mutex is unlocked during the callback
96510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (NULL != callback) {
97510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID
98d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        (*callback)(&this->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid);
99510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
100510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
101510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten}
102510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
103ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1043a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_AddInterface(SLDynamicInterfaceManagementItf self,
1053a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    const SLInterfaceID iid, SLboolean async)
10661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
107ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
108ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
109510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
110ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == iid) {
111ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
112ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
114ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IObject *thisObject = InterfaceToIObject(this);
115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        const ClassTable *class__ = thisObject->mClass;
116ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        int MPH, index;
117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) {
118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_FEATURE_UNSUPPORTED;
119ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
120ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(index < (int) class__->mInterfaceCount);
121ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
122510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
123ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // check interface state
124ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_lock_exclusive(thisObject);
125ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            switch (*interfaceStateP) {
126ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
127ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            case INTERFACE_UNINITIALIZED:   // normal case
128ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                if (async) {
129ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // Asynchronous: mark operation pending and cancellable
130ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_ADDING_1;
131ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_unlock_exclusive(thisObject);
132ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
133ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // this section runs with mutex unlocked
134ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    result = ThreadPool_add(&thisObject->mEngine->mThreadPool, HandleAdd, this,
135ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        MPH);
136ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    if (SL_RESULT_SUCCESS != result) {
137ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        // Engine was destroyed during add, or insufficient memory,
138ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        // so restore mInterfaceStates state to prior value
139ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        object_lock_exclusive(thisObject);
140ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        switch (*interfaceStateP) {
141ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        case INTERFACE_ADDING_1:    // normal
142ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        case INTERFACE_ADDING_1A:   // operation aborted while mutex unlocked
143ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            *interfaceStateP = INTERFACE_UNINITIALIZED;
144ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            break;
145ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        default:                    // unexpected
146ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            // leave state alone
147ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            break;
148ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        }
149ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    }
150ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
151ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                } else {
152ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // Synchronous: mark operation pending to prevent duplication
153ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_ADDING_2;
154ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_unlock_exclusive(thisObject);
155ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
156ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // this section runs with mutex unlocked
157ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    const struct iid_vtable *x = &class__->mInterfaces[index];
158ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    size_t offset = x->mOffset;
159ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ?
160ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        class__->mSize : x[1].mOffset) - offset;
161ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    void *thisItf = (char *) thisObject + offset;
162ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    memset(thisItf, 0, size);
163ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // Will never add IObject, so [1] is always defined
164ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    ((void **) thisItf)[1] = thisObject;
165ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    VoidHook init = MPH_init_table[MPH].mInit;
166e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                    if (NULL != init) {
167ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        (*init)(thisItf);
168e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                        ((size_t *) thisItf)[0] ^= ~0;
169e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten                    }
170ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    result = SL_RESULT_SUCCESS;
171ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
172ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // re-lock mutex to update state
173ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_lock_exclusive(thisObject);
174ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    assert(INTERFACE_ADDING_2 == *interfaceStateP);
175ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_ADDED;
176ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                }
177510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
178ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // mutex is still locked
179ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
180ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
181ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            default:    // disallow adding of (partially) initialized interfaces
182ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                result = SL_RESULT_PRECONDITIONS_VIOLATED;
183ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
184510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
185510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            }
186510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
187510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_unlock_exclusive(thisObject);
188510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
18961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
19061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
191510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
192ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
19361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
19461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
195ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
19661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IDynamicInterfaceManagement_RemoveInterface(
19761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLDynamicInterfaceManagementItf self, const SLInterfaceID iid)
19861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
199ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
200510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
201ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    // validate input parameters
202ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == iid) {
203ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
204ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
205ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
206ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IObject *thisObject = InterfaceToIObject(this);
207ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        const ClassTable *class__ = thisObject->mClass;
208ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        int MPH, index;
209ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) {
210ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
211ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
212ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
213510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
214ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // check interface state
215ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_lock_exclusive(thisObject);
216ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            switch (*interfaceStateP) {
217ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
218ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            case INTERFACE_ADDED:       // normal cases
219ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            case INTERFACE_SUSPENDED:
220ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                {
221ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // Mark operation pending to prevent duplication
222ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                *interfaceStateP = INTERFACE_REMOVING;
223ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                thisObject->mGottenMask &= ~(1 << index);
224ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_unlock_exclusive(thisObject);
225ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
226ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // The deinitialization is done with mutex unlocked
227ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                const struct iid_vtable *x = &class__->mInterfaces[index];
228ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                size_t offset = x->mOffset;
229ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                void *thisItf = (char *) thisObject + offset;
230ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                VoidHook deinit = MPH_init_table[MPH].mDeinit;
231ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                if (NULL != deinit)
232ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    (*deinit)(thisItf);
23391ff8847bf0125c9cc04168396d485269ba6aad8Glenn Kasten#ifndef NDEBUG
234ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ?
235ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    class__->mSize : x[1].mOffset) - offset;
236ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                memset(thisItf, 0x55, size);
23791ff8847bf0125c9cc04168396d485269ba6aad8Glenn Kasten#endif
238ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                result = SL_RESULT_SUCCESS;
239ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
240ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // Note that this was previously locked, but then unlocked for the deinit hook
241ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_lock_exclusive(thisObject);
242ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                assert(INTERFACE_REMOVING == *interfaceStateP);
243ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                *interfaceStateP = INTERFACE_UNINITIALIZED;
244ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                }
245510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
246ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // mutex is still locked
247ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
248510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            default:
250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // disallow removal of non-dynamic interfaces, or interfaces which are
251ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // currently being resumed (will not auto-cancel an asynchronous resume)
252ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                result = SL_RESULT_PRECONDITIONS_VIOLATED;
253ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
254510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
255ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            }
256510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
257ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_unlock_exclusive(thisObject);
258ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
25961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
260510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
261ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
26261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
26361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
264ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
265510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous ResumeInterface.
266510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the DynamicInterface, and MPH specifies which interface to resume.
267510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
268510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleResume(void *self, int MPH)
269510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{
270510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
271510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
272d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
273d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    assert(NULL != this);
274d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IObject *thisObject = InterfaceToIObject(this);
275510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != thisObject);
276510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(0 <= MPH && MPH < MPH_MAX);
277510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    const ClassTable *class__ = thisObject->mClass;
278510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != class__);
279510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    int index = class__->mMPH_to_index[MPH];
280510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(0 <= index && index < (int) class__->mInterfaceCount);
281510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
282510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLresult result;
283510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
284510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // check interface state
285510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_exclusive(thisObject);
286276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    SLuint8 state = *interfaceStateP;
287510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (state) {
288510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
289510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_1:      // normal case
290510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        {
291510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // change state to indicate we are now resuming the interface
292510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        *interfaceStateP = INTERFACE_RESUMING_2;
293510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_unlock_exclusive(thisObject);
294510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
295510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // this section runs with mutex unlocked
296510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const struct iid_vtable *x = &class__->mInterfaces[index];
297510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        size_t offset = x->mOffset;
298510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        void *thisItf = (char *) thisObject + offset;
299510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        VoidHook resume = MPH_init_table[MPH].mResume;
300510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        if (NULL != resume)
301510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            (*resume)(thisItf);
302510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_SUCCESS;
303510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
304510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // re-lock mutex to update state
305510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_lock_exclusive(thisObject);
306510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(INTERFACE_RESUMING_2 == *interfaceStateP);
307510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_ADDED;
308510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        }
309510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
310510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
311510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_1A:     // operation was aborted while on work queue
312510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_OPERATION_ABORTED;
313510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_SUSPENDED;
314510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
315510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
316510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:                        // impossible
317510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(SL_BOOLEAN_FALSE);
318510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_INTERNAL_ERROR;
319510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
320510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
321510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
322510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
323510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // mutex is locked, update state
324510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    *interfaceStateP = state;
325510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
326510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Make a copy of these, so we can call the callback with mutex unlocked
327d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    slDynamicInterfaceManagementCallback callback = this->mCallback;
328d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    void *context = this->mContext;
329510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_exclusive(thisObject);
330510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
331510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Note that the mutex is unlocked during the callback
332510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (NULL != callback) {
333510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID
334d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        (*callback)(&this->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid);
335510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
336510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten}
337510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
338ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
3393a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_ResumeInterface(SLDynamicInterfaceManagementItf self,
34061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const SLInterfaceID iid, SLboolean async)
34161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
342ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
343ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
344510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
345ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == iid) {
346ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
347ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
348ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
349ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IObject *thisObject = InterfaceToIObject(this);
350ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        const ClassTable *class__ = thisObject->mClass;
351ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        int MPH, index;
352ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) {
353ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
354ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
355ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(index < (int) class__->mInterfaceCount);
356ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
357510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
358ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // check interface state
359ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_lock_exclusive(thisObject);
360ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            switch (*interfaceStateP) {
361ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
362ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            case INTERFACE_SUSPENDED:   // normal case
363ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                if (async) {
364ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // Asynchronous: mark operation pending and cancellable
365ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_RESUMING_1;
366ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_unlock_exclusive(thisObject);
367ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
368ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // this section runs with mutex unlocked
369ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    result = ThreadPool_add(&thisObject->mEngine->mThreadPool, HandleResume, this,
370ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        MPH);
371ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    if (SL_RESULT_SUCCESS != result) {
372ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        // Engine was destroyed during resume, or insufficient memory,
373ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        // so restore mInterfaceStates state to prior value
374ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        object_lock_exclusive(thisObject);
375ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        switch (*interfaceStateP) {
376ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        case INTERFACE_RESUMING_1:  // normal
377ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        case INTERFACE_RESUMING_1A: // operation aborted while mutex unlocked
378ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            *interfaceStateP = INTERFACE_SUSPENDED;
379ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            break;
380ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        default:                    // unexpected
381ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            // leave state alone
382ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            break;
383ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        }
384ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    }
385ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
386ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                } else {
387ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // Synchronous: mark operation pending to prevent duplication
388ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_RESUMING_2;
389ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_unlock_exclusive(thisObject);
390ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
391ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // this section runs with mutex unlocked
392ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    const struct iid_vtable *x = &class__->mInterfaces[index];
393ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    size_t offset = x->mOffset;
394ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    void *thisItf = (char *) this + offset;
395ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    VoidHook resume = MPH_init_table[MPH].mResume;
396ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    if (NULL != resume)
397ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        (*resume)(thisItf);
398ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    result = SL_RESULT_SUCCESS;
399ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
400ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // re-lock mutex to update state
401ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_lock_exclusive(thisObject);
402ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    assert(INTERFACE_RESUMING_2 == *interfaceStateP);
403ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_ADDED;
404ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                }
405510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
406ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // mutex is now unlocked
407ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
408510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
409ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            default:    // disallow resumption of non-suspended interfaces
410ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_unlock_exclusive(thisObject);
411ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                result = SL_RESULT_PRECONDITIONS_VIOLATED;
412ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
413510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            }
414510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
415510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_unlock_exclusive(thisObject);
4163a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        }
4173a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    }
418510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
419ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
42061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
42161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
422ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
4233a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_RegisterCallback(SLDynamicInterfaceManagementItf self,
42461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    slDynamicInterfaceManagementCallback callback, void *pContext)
42561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
426ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
427ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
428daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
429d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IObject *thisObject = InterfaceToIObject(this);
43061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(thisObject);
43161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = callback;
43261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = pContext;
43361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(thisObject);
434ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    result = SL_RESULT_SUCCESS;
435ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
436ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
43761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
43861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
439ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
44061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLDynamicInterfaceManagementItf_ IDynamicInterfaceManagement_Itf = {
44161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_AddInterface,
44261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_RemoveInterface,
44361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_ResumeInterface,
44461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_RegisterCallback
44561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten};
44661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
44761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IDynamicInterfaceManagement_init(void *self)
44861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
44961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
45061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mItf = &IDynamicInterfaceManagement_Itf;
45161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = NULL;
45261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = NULL;
45361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
454