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