IDynamicInterfaceManagement.c revision ed46c29d6a09112dbbf584c82953f63289596fd6
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;
62510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        if (NULL != init)
63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            (*init)(thisItf);
64510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_SUCCESS;
65510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // re-lock mutex to update state
67510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_lock_exclusive(thisObject);
68510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(INTERFACE_ADDING_2 == *interfaceStateP);
69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_ADDED;
70510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        }
71510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
72510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
73510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_ADDING_1A:   // operation was aborted while on work queue
74510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_OPERATION_ABORTED;
75510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_UNINITIALIZED;
76510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
77510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
78510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:                    // impossible
79510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(SL_BOOLEAN_FALSE);
80510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_INTERNAL_ERROR;
81510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
82510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
83510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
84510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
85510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // mutex is locked, update state
86510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    *interfaceStateP = state;
87510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
88510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Make a copy of these, so we can call the callback with mutex unlocked
89d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    slDynamicInterfaceManagementCallback callback = this->mCallback;
90d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    void *context = this->mContext;
91510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_exclusive(thisObject);
92510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
93510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Note that the mutex is unlocked during the callback
94510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (NULL != callback) {
95510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID
96d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        (*callback)(&this->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid);
97510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
98510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
99510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten}
100510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
101ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1023a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_AddInterface(SLDynamicInterfaceManagementItf self,
1033a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    const SLInterfaceID iid, SLboolean async)
10461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
105ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
106ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
107510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
108ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == iid) {
109ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
110ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
111ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
112ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IObject *thisObject = InterfaceToIObject(this);
113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        const ClassTable *class__ = thisObject->mClass;
114ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        int MPH, index;
115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) {
116ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_FEATURE_UNSUPPORTED;
117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(index < (int) class__->mInterfaceCount);
119ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
120510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
121ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // check interface state
122ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_lock_exclusive(thisObject);
123ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            switch (*interfaceStateP) {
124ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
125ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            case INTERFACE_UNINITIALIZED:   // normal case
126ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                if (async) {
127ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // Asynchronous: mark operation pending and cancellable
128ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_ADDING_1;
129ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_unlock_exclusive(thisObject);
130ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
131ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // this section runs with mutex unlocked
132ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    result = ThreadPool_add(&thisObject->mEngine->mThreadPool, HandleAdd, this,
133ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        MPH);
134ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    if (SL_RESULT_SUCCESS != result) {
135ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        // Engine was destroyed during add, or insufficient memory,
136ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        // so restore mInterfaceStates state to prior value
137ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        object_lock_exclusive(thisObject);
138ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        switch (*interfaceStateP) {
139ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        case INTERFACE_ADDING_1:    // normal
140ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        case INTERFACE_ADDING_1A:   // operation aborted while mutex unlocked
141ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            *interfaceStateP = INTERFACE_UNINITIALIZED;
142ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            break;
143ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        default:                    // unexpected
144ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            // leave state alone
145ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            break;
146ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        }
147ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    }
148ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
149ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                } else {
150ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // Synchronous: mark operation pending to prevent duplication
151ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_ADDING_2;
152ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_unlock_exclusive(thisObject);
153ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
154ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // this section runs with mutex unlocked
155ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    const struct iid_vtable *x = &class__->mInterfaces[index];
156ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    size_t offset = x->mOffset;
157ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ?
158ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        class__->mSize : x[1].mOffset) - offset;
159ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    void *thisItf = (char *) thisObject + offset;
160ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    memset(thisItf, 0, size);
161ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // Will never add IObject, so [1] is always defined
162ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    ((void **) thisItf)[1] = thisObject;
163ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    VoidHook init = MPH_init_table[MPH].mInit;
164ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    if (NULL != init)
165ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        (*init)(thisItf);
166ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    result = SL_RESULT_SUCCESS;
167ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
168ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // re-lock mutex to update state
169ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_lock_exclusive(thisObject);
170ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    assert(INTERFACE_ADDING_2 == *interfaceStateP);
171ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_ADDED;
172ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                }
173510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
174ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // mutex is still locked
175ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
176ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
177ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            default:    // disallow adding of (partially) initialized interfaces
178ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                result = SL_RESULT_PRECONDITIONS_VIOLATED;
179ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
180510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
181510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            }
182510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
183510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_unlock_exclusive(thisObject);
184510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
18561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
18661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
187510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
188ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
18961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
19061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
191ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
19261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IDynamicInterfaceManagement_RemoveInterface(
19361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLDynamicInterfaceManagementItf self, const SLInterfaceID iid)
19461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
195ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
196510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
197ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    // validate input parameters
198ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == iid) {
199ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
200ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
201ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
202ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IObject *thisObject = InterfaceToIObject(this);
203ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        const ClassTable *class__ = thisObject->mClass;
204ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        int MPH, index;
205ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) {
206ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
207ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
208ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
209510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
210ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // check interface state
211ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_lock_exclusive(thisObject);
212ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            switch (*interfaceStateP) {
213ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
214ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            case INTERFACE_ADDED:       // normal cases
215ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            case INTERFACE_SUSPENDED:
216ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                {
217ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // Mark operation pending to prevent duplication
218ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                *interfaceStateP = INTERFACE_REMOVING;
219ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                thisObject->mGottenMask &= ~(1 << index);
220ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_unlock_exclusive(thisObject);
221ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
222ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // The deinitialization is done with mutex unlocked
223ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                const struct iid_vtable *x = &class__->mInterfaces[index];
224ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                size_t offset = x->mOffset;
225ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                void *thisItf = (char *) thisObject + offset;
226ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                VoidHook deinit = MPH_init_table[MPH].mDeinit;
227ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                if (NULL != deinit)
228ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    (*deinit)(thisItf);
229ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        #ifndef NDEBUG
230ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ?
231ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    class__->mSize : x[1].mOffset) - offset;
232ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                memset(thisItf, 0x55, size);
233ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        #endif
234ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                result = SL_RESULT_SUCCESS;
235ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
236ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // Note that this was previously locked, but then unlocked for the deinit hook
237ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_lock_exclusive(thisObject);
238ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                assert(INTERFACE_REMOVING == *interfaceStateP);
239ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                *interfaceStateP = INTERFACE_UNINITIALIZED;
240ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                }
241510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
242ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // mutex is still locked
243ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
244510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
245ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            default:
246ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // disallow removal of non-dynamic interfaces, or interfaces which are
247ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // currently being resumed (will not auto-cancel an asynchronous resume)
248ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                result = SL_RESULT_PRECONDITIONS_VIOLATED;
249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
250510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
251ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            }
252510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
253ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_unlock_exclusive(thisObject);
254ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
25561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
256510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
257ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
25861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
25961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
260ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
261510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous ResumeInterface.
262510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the DynamicInterface, and MPH specifies which interface to resume.
263510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
264510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleResume(void *self, int MPH)
265510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{
266510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
267510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
268d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
269d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    assert(NULL != this);
270d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IObject *thisObject = InterfaceToIObject(this);
271510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != thisObject);
272510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(0 <= MPH && MPH < MPH_MAX);
273510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    const ClassTable *class__ = thisObject->mClass;
274510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != class__);
275510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    int index = class__->mMPH_to_index[MPH];
276510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(0 <= index && index < (int) class__->mInterfaceCount);
277510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
278510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLresult result;
279510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
280510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // check interface state
281510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_exclusive(thisObject);
282276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    SLuint8 state = *interfaceStateP;
283510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (state) {
284510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
285510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_1:      // normal case
286510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        {
287510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // change state to indicate we are now resuming the interface
288510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        *interfaceStateP = INTERFACE_RESUMING_2;
289510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_unlock_exclusive(thisObject);
290510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
291510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // this section runs with mutex unlocked
292510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const struct iid_vtable *x = &class__->mInterfaces[index];
293510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        size_t offset = x->mOffset;
294510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        void *thisItf = (char *) thisObject + offset;
295510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        VoidHook resume = MPH_init_table[MPH].mResume;
296510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        if (NULL != resume)
297510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            (*resume)(thisItf);
298510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_SUCCESS;
299510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
300510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // re-lock mutex to update state
301510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_lock_exclusive(thisObject);
302510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(INTERFACE_RESUMING_2 == *interfaceStateP);
303510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_ADDED;
304510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        }
305510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
306510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
307510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_1A:     // operation was aborted while on work queue
308510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_OPERATION_ABORTED;
309510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_SUSPENDED;
310510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
311510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
312510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:                        // impossible
313510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(SL_BOOLEAN_FALSE);
314510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_INTERNAL_ERROR;
315510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
316510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
317510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
318510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
319510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // mutex is locked, update state
320510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    *interfaceStateP = state;
321510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
322510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Make a copy of these, so we can call the callback with mutex unlocked
323d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    slDynamicInterfaceManagementCallback callback = this->mCallback;
324d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    void *context = this->mContext;
325510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_exclusive(thisObject);
326510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
327510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Note that the mutex is unlocked during the callback
328510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (NULL != callback) {
329510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID
330d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        (*callback)(&this->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid);
331510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
332510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten}
333510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
334ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
3353a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_ResumeInterface(SLDynamicInterfaceManagementItf self,
33661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const SLInterfaceID iid, SLboolean async)
33761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
338ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
339ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
340510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
341ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == iid) {
342ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
343ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
344ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
345ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IObject *thisObject = InterfaceToIObject(this);
346ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        const ClassTable *class__ = thisObject->mClass;
347ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        int MPH, index;
348ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) {
349ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
350ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
351ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            assert(index < (int) class__->mInterfaceCount);
352ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
353510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
354ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // check interface state
355ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            object_lock_exclusive(thisObject);
356ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            switch (*interfaceStateP) {
357ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
358ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            case INTERFACE_SUSPENDED:   // normal case
359ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                if (async) {
360ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // Asynchronous: mark operation pending and cancellable
361ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_RESUMING_1;
362ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_unlock_exclusive(thisObject);
363ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
364ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // this section runs with mutex unlocked
365ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    result = ThreadPool_add(&thisObject->mEngine->mThreadPool, HandleResume, this,
366ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        MPH);
367ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    if (SL_RESULT_SUCCESS != result) {
368ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        // Engine was destroyed during resume, or insufficient memory,
369ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        // so restore mInterfaceStates state to prior value
370ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        object_lock_exclusive(thisObject);
371ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        switch (*interfaceStateP) {
372ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        case INTERFACE_RESUMING_1:  // normal
373ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        case INTERFACE_RESUMING_1A: // operation aborted while mutex unlocked
374ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            *interfaceStateP = INTERFACE_SUSPENDED;
375ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            break;
376ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        default:                    // unexpected
377ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            // leave state alone
378ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                            break;
379ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        }
380ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    }
381ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
382ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                } else {
383ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // Synchronous: mark operation pending to prevent duplication
384ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_RESUMING_2;
385ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_unlock_exclusive(thisObject);
386ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
387ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // this section runs with mutex unlocked
388ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    const struct iid_vtable *x = &class__->mInterfaces[index];
389ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    size_t offset = x->mOffset;
390ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    void *thisItf = (char *) this + offset;
391ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    VoidHook resume = MPH_init_table[MPH].mResume;
392ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    if (NULL != resume)
393ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                        (*resume)(thisItf);
394ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    result = SL_RESULT_SUCCESS;
395ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
396ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    // re-lock mutex to update state
397ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    object_lock_exclusive(thisObject);
398ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    assert(INTERFACE_RESUMING_2 == *interfaceStateP);
399ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                    *interfaceStateP = INTERFACE_ADDED;
400ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                }
401510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
402ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                // mutex is now unlocked
403ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
404510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
405ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            default:    // disallow resumption of non-suspended interfaces
406ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                object_unlock_exclusive(thisObject);
407ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                result = SL_RESULT_PRECONDITIONS_VIOLATED;
408ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten                break;
409510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            }
410510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
411510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_unlock_exclusive(thisObject);
4123a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        }
4133a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    }
414510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
415ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
41661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
41761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
418ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
4193a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_RegisterCallback(SLDynamicInterfaceManagementItf self,
42061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    slDynamicInterfaceManagementCallback callback, void *pContext)
42161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
422ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
423ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
424daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
425d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IObject *thisObject = InterfaceToIObject(this);
42661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(thisObject);
42761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = callback;
42861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = pContext;
42961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(thisObject);
430ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    result = SL_RESULT_SUCCESS;
431ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
432ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
43361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
43461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
435ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
43661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLDynamicInterfaceManagementItf_ IDynamicInterfaceManagement_Itf = {
43761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_AddInterface,
43861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_RemoveInterface,
43961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_ResumeInterface,
44061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_RegisterCallback
44161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten};
44261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
44361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IDynamicInterfaceManagement_init(void *self)
44461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
44561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
44661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mItf = &IDynamicInterfaceManagement_Itf;
44761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = NULL;
44861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = NULL;
44961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
450