IDynamicInterfaceManagement.cpp revision 276cab2d983b892d1b634474b6249f6bec400c76
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
21510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous AddInterface.
22510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the DynamicInterface, and MPH specifies which interface to add.
23510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
24510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleAdd(void *self, int MPH)
25510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{
26510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
27510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
28d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
29d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    assert(NULL != this);
30d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IObject *thisObject = InterfaceToIObject(this);
31510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != thisObject);
32510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(0 <= MPH && MPH < MPH_MAX);
33510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    const ClassTable *class__ = thisObject->mClass;
34510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != class__);
35510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    int index = class__->mMPH_to_index[MPH];
36510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(0 <= index && index < (int) class__->mInterfaceCount);
37510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
38510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLresult result;
39510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
40510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // check interface state
41510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_exclusive(thisObject);
42276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    SLuint8 state = *interfaceStateP;
43510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (state) {
44510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
45510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_ADDING_1:    // normal case
46510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        {
47510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // change state to indicate we are now adding the interface
48510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        *interfaceStateP = INTERFACE_ADDING_2;
49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_unlock_exclusive(thisObject);
50510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // this section runs with mutex unlocked
52510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const struct iid_vtable *x = &class__->mInterfaces[index];
53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        size_t offset = x->mOffset;
54510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        void *thisItf = (char *) thisObject + offset;
55510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ?
56510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            class__->mSize : x[1].mOffset) - offset;
57510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        memset(thisItf, 0, size);
58d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        // Will never add IObject, so [1] is always defined
59510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        ((void **) thisItf)[1] = thisObject;
60510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        VoidHook init = MPH_init_table[MPH].mInit;
61510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        if (NULL != init)
62510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            (*init)(thisItf);
63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_SUCCESS;
64510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
65510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // re-lock mutex to update state
66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_lock_exclusive(thisObject);
67510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(INTERFACE_ADDING_2 == *interfaceStateP);
68510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_ADDED;
69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        }
70510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
71510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
72510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_ADDING_1A:   // operation was aborted while on work queue
73510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_OPERATION_ABORTED;
74510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_UNINITIALIZED;
75510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
76510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
77510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:                    // impossible
78510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(SL_BOOLEAN_FALSE);
79510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_INTERNAL_ERROR;
80510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
81510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
82510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
83510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
84510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // mutex is locked, update state
85510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    *interfaceStateP = state;
86510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
87510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Make a copy of these, so we can call the callback with mutex unlocked
88d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    slDynamicInterfaceManagementCallback callback = this->mCallback;
89d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    void *context = this->mContext;
90510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_exclusive(thisObject);
91510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
92510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Note that the mutex is unlocked during the callback
93510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (NULL != callback) {
94510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID
95d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        (*callback)(&this->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid);
96510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
97510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
98510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten}
99510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
1003a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_AddInterface(SLDynamicInterfaceManagementItf self,
1013a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    const SLInterfaceID iid, SLboolean async)
10261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
103510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
10461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == iid)
10561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
106daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
107d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IObject *thisObject = InterfaceToIObject(this);
10861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const ClassTable *class__ = thisObject->mClass;
10961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    int MPH, index;
110daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH])))
11161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_FEATURE_UNSUPPORTED;
112510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(index < (int) class__->mInterfaceCount);
113510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
11461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLresult result;
115510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
116510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // check interface state
11761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(thisObject);
118510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (*interfaceStateP) {
119510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
120510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_UNINITIALIZED:   // normal case
1213a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        if (async) {
122510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // Asynchronous: mark operation pending and cancellable
123510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP = INTERFACE_ADDING_1;
124510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_unlock_exclusive(thisObject);
125510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
126510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // this section runs with mutex unlocked
127510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            result = ThreadPool_add(&thisObject->mEngine->mThreadPool, HandleAdd, this, MPH);
128510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            if (SL_RESULT_SUCCESS != result) {
129510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                // Engine was destroyed during add, or insufficient memory,
130510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                // so restore mInterfaceStates state to prior value
131510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                object_lock_exclusive(thisObject);
132510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                switch (*interfaceStateP) {
133510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                case INTERFACE_ADDING_1:    // normal
134510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                case INTERFACE_ADDING_1A:   // operation aborted while mutex unlocked
135510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                    *interfaceStateP = INTERFACE_UNINITIALIZED;
136510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                    break;
137510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                default:                    // unexpected
138510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                    // leave state alone
139510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                    break;
140510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                }
141510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            }
142510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
143510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        } else {
144510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // Synchronous: mark operation pending to prevent duplication
145510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP = INTERFACE_ADDING_2;
146510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_unlock_exclusive(thisObject);
147510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
148510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // this section runs with mutex unlocked
149510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            const struct iid_vtable *x = &class__->mInterfaces[index];
150510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            size_t offset = x->mOffset;
151510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ?
152510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                class__->mSize : x[1].mOffset) - offset;
153510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            void *thisItf = (char *) thisObject + offset;
154510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            memset(thisItf, 0, size);
155d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten            // Will never add IObject, so [1] is always defined
156510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            ((void **) thisItf)[1] = thisObject;
157510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            VoidHook init = MPH_init_table[MPH].mInit;
158510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            if (NULL != init)
159510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                (*init)(thisItf);
160510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            result = SL_RESULT_SUCCESS;
161510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
162510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // re-lock mutex to update state
163510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_lock_exclusive(thisObject);
164510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            assert(INTERFACE_ADDING_2 == *interfaceStateP);
165510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP = INTERFACE_ADDED;
16661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
167510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
168510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // mutex is still locked
169510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
170510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
171510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:    // disallow adding of (partially) initialized interfaces
172510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
173510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
174510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
17561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
176510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
17761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(thisObject);
17861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return result;
17961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
18061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
18161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IDynamicInterfaceManagement_RemoveInterface(
18261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLDynamicInterfaceManagementItf self, const SLInterfaceID iid)
18361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
184510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
18561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == iid)
18661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
187daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
188d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IObject *thisObject = InterfaceToIObject(this);
18961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const ClassTable *class__ = thisObject->mClass;
190510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    int MPH, index;
191510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH])))
19261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PRECONDITIONS_VIOLATED;
193510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLresult result;
194510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
195510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
196510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // check interface state
19761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(thisObject);
198510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (*interfaceStateP) {
199510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
200510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_ADDED:       // normal cases
201510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_SUSPENDED:
202510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        {
203510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // Mark operation pending to prevent duplication
204510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        *interfaceStateP = INTERFACE_REMOVING;
205510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        thisObject->mGottenMask &= ~(1 << index);
206d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        object_unlock_exclusive(thisObject);
207510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
208d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        // The deinitialization is done with mutex unlocked
209510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const struct iid_vtable *x = &class__->mInterfaces[index];
210510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        size_t offset = x->mOffset;
211510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        void *thisItf = (char *) thisObject + offset;
212510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        VoidHook deinit = MPH_init_table[MPH].mDeinit;
21361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (NULL != deinit)
21461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            (*deinit)(thisItf);
21561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#ifndef NDEBUG
216510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ?
217510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            class__->mSize : x[1].mOffset) - offset;
21861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        memset(thisItf, 0x55, size);
21961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#endif
220510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_SUCCESS;
221510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
222d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        // Note that this was previously locked, but then unlocked for the deinit hook
223d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten        object_lock_exclusive(thisObject);
224510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(INTERFACE_REMOVING == *interfaceStateP);
225510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        *interfaceStateP = INTERFACE_UNINITIALIZED;
226510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        }
227510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
228510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // mutex is still locked
229510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
230510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
231510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:
232510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // disallow removal of non-dynamic interfaces, or interfaces which are
233510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // currently being resumed (will not auto-cancel an asynchronous resume)
234510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
235510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
236510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
23761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
238510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
23961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(thisObject);
24061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return result;
24161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
24261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
243510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous ResumeInterface.
244510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the DynamicInterface, and MPH specifies which interface to resume.
245510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
246510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleResume(void *self, int MPH)
247510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{
248510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
249510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
250d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
251d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    assert(NULL != this);
252d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IObject *thisObject = InterfaceToIObject(this);
253510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != thisObject);
254510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(0 <= MPH && MPH < MPH_MAX);
255510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    const ClassTable *class__ = thisObject->mClass;
256510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(NULL != class__);
257510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    int index = class__->mMPH_to_index[MPH];
258510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(0 <= index && index < (int) class__->mInterfaceCount);
259510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
260510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLresult result;
261510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
262510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // check interface state
263510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_exclusive(thisObject);
264276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten    SLuint8 state = *interfaceStateP;
265510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (state) {
266510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
267510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_1:      // normal case
268510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        {
269510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // change state to indicate we are now resuming the interface
270510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        *interfaceStateP = INTERFACE_RESUMING_2;
271510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_unlock_exclusive(thisObject);
272510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
273510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // this section runs with mutex unlocked
274510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const struct iid_vtable *x = &class__->mInterfaces[index];
275510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        size_t offset = x->mOffset;
276510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        void *thisItf = (char *) thisObject + offset;
277510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        VoidHook resume = MPH_init_table[MPH].mResume;
278510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        if (NULL != resume)
279510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            (*resume)(thisItf);
280510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_SUCCESS;
281510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
282510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // re-lock mutex to update state
283510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_lock_exclusive(thisObject);
284510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(INTERFACE_RESUMING_2 == *interfaceStateP);
285510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_ADDED;
286510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        }
287510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
288510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
289510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_1A:     // operation was aborted while on work queue
290510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_OPERATION_ABORTED;
291510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        state = INTERFACE_SUSPENDED;
292510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
293510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
294510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:                        // impossible
295510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        assert(SL_BOOLEAN_FALSE);
296510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_INTERNAL_ERROR;
297510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
298510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
299510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
300510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
301510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // mutex is locked, update state
302510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    *interfaceStateP = state;
303510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
304510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Make a copy of these, so we can call the callback with mutex unlocked
305d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    slDynamicInterfaceManagementCallback callback = this->mCallback;
306d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    void *context = this->mContext;
307510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_exclusive(thisObject);
308510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
309510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // Note that the mutex is unlocked during the callback
310510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (NULL != callback) {
311510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID
312d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten        (*callback)(&this->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid);
313510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
314510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten}
315510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
3163a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_ResumeInterface(SLDynamicInterfaceManagementItf self,
31761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const SLInterfaceID iid, SLboolean async)
31861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
319510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // validate input parameters
32061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == iid)
32161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
322daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
323d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IObject *thisObject = InterfaceToIObject(this);
32461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const ClassTable *class__ = thisObject->mClass;
325510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    int MPH, index;
326510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH])))
32761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PRECONDITIONS_VIOLATED;
328510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(index < (int) class__->mInterfaceCount);
329510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index];
3303a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    SLresult result;
331510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
332510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    // check interface state
333510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_exclusive(thisObject);
334510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (*interfaceStateP) {
335510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
336510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_SUSPENDED:   // normal case
3373a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        if (async) {
338510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // Asynchronous: mark operation pending and cancellable
339510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP = INTERFACE_RESUMING_1;
340510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_unlock_exclusive(thisObject);
341510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
342510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // this section runs with mutex unlocked
343510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            result = ThreadPool_add(&thisObject->mEngine->mThreadPool, HandleResume, this, MPH);
344510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            if (SL_RESULT_SUCCESS != result) {
345510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                // Engine was destroyed during resume, or insufficient memory,
346510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                // so restore mInterfaceStates state to prior value
347510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                object_lock_exclusive(thisObject);
348510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                switch (*interfaceStateP) {
349510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                case INTERFACE_RESUMING_1:  // normal
350510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                case INTERFACE_RESUMING_1A: // operation aborted while mutex unlocked
351510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                    *interfaceStateP = INTERFACE_SUSPENDED;
352510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                    break;
353510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                default:                    // unexpected
354510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                    // leave state alone
355510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                    break;
356510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                }
357510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            }
358510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
359510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        } else {
360510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // Synchronous: mark operation pending to prevent duplication
361510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP = INTERFACE_RESUMING_2;
362510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_unlock_exclusive(thisObject);
363510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
364510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // this section runs with mutex unlocked
365510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            const struct iid_vtable *x = &class__->mInterfaces[index];
366510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            size_t offset = x->mOffset;
367510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            void *thisItf = (char *) this + offset;
368510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            VoidHook resume = MPH_init_table[MPH].mResume;
369510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            if (NULL != resume)
370510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten                (*resume)(thisItf);
371510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            result = SL_RESULT_SUCCESS;
372510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
373510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            // re-lock mutex to update state
374510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            object_lock_exclusive(thisObject);
375510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            assert(INTERFACE_RESUMING_2 == *interfaceStateP);
376510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            *interfaceStateP = INTERFACE_ADDED;
3773a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        }
378510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
379510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        // mutex is now unlocked
380510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
381510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
382510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:    // disallow resumption of non-suspended interfaces
383510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        object_unlock_exclusive(thisObject);
384510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
385510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
3863a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    }
387510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
388510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_exclusive(thisObject);
38961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return result;
39061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
39161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
3923a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_RegisterCallback(SLDynamicInterfaceManagementItf self,
39361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    slDynamicInterfaceManagementCallback callback, void *pContext)
39461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
395daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
396d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten    IObject *thisObject = InterfaceToIObject(this);
39761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(thisObject);
39861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = callback;
39961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = pContext;
40061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(thisObject);
40161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
40261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
40361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
40461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLDynamicInterfaceManagementItf_ IDynamicInterfaceManagement_Itf = {
40561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_AddInterface,
40661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_RemoveInterface,
40761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_ResumeInterface,
40861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement_RegisterCallback
40961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten};
41061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
41161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IDynamicInterfaceManagement_init(void *self)
41261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
41361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self;
41461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mItf = &IDynamicInterfaceManagement_Itf;
41561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = NULL;
41661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = NULL;
41761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
418