IDynamicInterfaceManagement.cpp revision 510f3671f716f6835282e4b0fd0275c20e9dadd8
1ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff/* 2ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * Copyright (C) 2010 The Android Open Source Project 3ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * 4ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * Licensed under the Apache License, Version 2.0 (the "License"); 5ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * you may not use this file except in compliance with the License. 6ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * You may obtain a copy of the License at 7ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * 8ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * http://www.apache.org/licenses/LICENSE-2.0 9ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * 10ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * Unless required by applicable law or agreed to in writing, software 11ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * distributed under the License is distributed on an "AS IS" BASIS, 12ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * See the License for the specific language governing permissions and 14ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * limitations under the License. 15ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff */ 16ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff 17ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff/* DynamicInterfaceManagement implementation */ 18ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff 19fd31b9d46ea09dc7d74ddc03ab7e5ecfbe80b3dcHugo Benichi#include "sles_allinclusive.h" 20fd31b9d46ea09dc7d74ddc03ab7e5ecfbe80b3dcHugo Benichi 21fd31b9d46ea09dc7d74ddc03ab7e5ecfbe80b3dcHugo Benichi// Called by a worker thread to handle an asynchronous AddInterface. 22fd31b9d46ea09dc7d74ddc03ab7e5ecfbe80b3dcHugo Benichi// Parameter self is the DynamicInterface, and MPH specifies which interface to add. 23fd31b9d46ea09dc7d74ddc03ab7e5ecfbe80b3dcHugo Benichi 24fd31b9d46ea09dc7d74ddc03ab7e5ecfbe80b3dcHugo Benichistatic void HandleAdd(void *self, int MPH) 25fd31b9d46ea09dc7d74ddc03ab7e5ecfbe80b3dcHugo Benichi{ 26fd31b9d46ea09dc7d74ddc03ab7e5ecfbe80b3dcHugo Benichi 27fd31b9d46ea09dc7d74ddc03ab7e5ecfbe80b3dcHugo Benichi // validate input parameters 28ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff IDynamicInterfaceManagement *thisDIM = (IDynamicInterfaceManagement *) self; 29ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff assert(NULL != thisDIM); 308c6c2c3c929acad783b9a56b8d9efa597d0ae609Lorenzo Colitti IObject *thisObject = thisDIM->mThis; 31ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff assert(NULL != thisObject); 32b979f79158f9c470fa09ff3b96d72db274262201Robert Greenwalt assert(0 <= MPH && MPH < MPH_MAX); 33befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline const ClassTable *class__ = thisObject->mClass; 34ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff assert(NULL != class__); 35ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff int index = class__->mMPH_to_index[MPH]; 36ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff assert(0 <= index && index < (int) class__->mInterfaceCount); 37ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index]; 38ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff SLresult result; 39e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti 4064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // check interface state 4164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti object_lock_exclusive(thisObject); 4264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti SLuint32 state = *interfaceStateP; 4364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti switch (state) { 4464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 457dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti case INTERFACE_ADDING_1: // normal case 467dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti { 477dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti // change state to indicate we are now adding the interface 487dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti *interfaceStateP = INTERFACE_ADDING_2; 497dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti object_unlock_exclusive(thisObject); 507dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti 517dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti // this section runs with mutex unlocked 52ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff const struct iid_vtable *x = &class__->mInterfaces[index]; 53ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff size_t offset = x->mOffset; 54ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff void *thisItf = (char *) thisObject + offset; 55ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ? 56ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff class__->mSize : x[1].mOffset) - offset; 576eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti memset(thisItf, 0, size); 58ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff ((void **) thisItf)[1] = thisObject; 59ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff VoidHook init = MPH_init_table[MPH].mInit; 60e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti if (NULL != init) 61ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff (*init)(thisItf); 626eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti result = SL_RESULT_SUCCESS; 63ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff 6464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // re-lock mutex to update state 6564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti object_lock_exclusive(thisObject); 6664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti assert(INTERFACE_ADDING_2 == *interfaceStateP); 6764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti state = INTERFACE_ADDED; 6864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti } 6964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti break; 7064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 7164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti case INTERFACE_ADDING_1A: // operation was aborted while on work queue 7264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti result = SL_RESULT_OPERATION_ABORTED; 7364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti state = INTERFACE_UNINITIALIZED; 7464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti break; 7564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 7664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti default: // impossible 7764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti assert(SL_BOOLEAN_FALSE); 7864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti result = SL_RESULT_INTERNAL_ERROR; 791dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi break; 8064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 8164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti } 8264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 8364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // mutex is locked, update state 8464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti *interfaceStateP = state; 8564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 8664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // Make a copy of these, so we can call the callback with mutex unlocked 8764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti slDynamicInterfaceManagementCallback callback = thisDIM->mCallback; 8864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti void *context = thisDIM->mContext; 8964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti object_unlock_exclusive(thisObject); 9064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 9164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // Note that the mutex is unlocked during the callback 9264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti if (NULL != callback) { 9364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID 9464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti (*callback)(&thisDIM->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid); 9564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti } 9664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 9764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti} 98befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline 99befe778c73e48417942fc31c06509bac8e5ca0d2Erik Klinestatic SLresult IDynamicInterfaceManagement_AddInterface(SLDynamicInterfaceManagementItf self, 100befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline const SLInterfaceID iid, SLboolean async) 101befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline{ 102befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline // validate input parameters 103befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline if (NULL == iid) 1041dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi return SL_RESULT_PARAMETER_INVALID; 105befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self; 1061eb8c69bed1615e9502e94b1a676773ed28abfd9Erik Kline IObject *thisObject = this->mThis; 107befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline const ClassTable *class__ = thisObject->mClass; 108befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline int MPH, index; 109befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) 110befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline return SL_RESULT_FEATURE_UNSUPPORTED; 111befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline assert(index < (int) class__->mInterfaceCount); 1121dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index]; 1131dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi SLresult result; 1141dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi 1151dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi // check interface state 1161dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi object_lock_exclusive(thisObject); 1171dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi switch (*interfaceStateP) { 1181dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi 1191dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi case INTERFACE_UNINITIALIZED: // normal case 1201dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi if (async) { 1211dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi // Asynchronous: mark operation pending and cancellable 1221dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi *interfaceStateP = INTERFACE_ADDING_1; 1231dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi object_unlock_exclusive(thisObject); 1241dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi 1251dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi // this section runs with mutex unlocked 1261dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi result = ThreadPool_add(&thisObject->mEngine->mThreadPool, HandleAdd, this, MPH); 1271dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi if (SL_RESULT_SUCCESS != result) { 12864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // Engine was destroyed during add, or insufficient memory, 12964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // so restore mInterfaceStates state to prior value 13064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti object_lock_exclusive(thisObject); 13164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti switch (*interfaceStateP) { 13264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti case INTERFACE_ADDING_1: // normal 13364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti case INTERFACE_ADDING_1A: // operation aborted while mutex unlocked 1341dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi *interfaceStateP = INTERFACE_UNINITIALIZED; 135b979f79158f9c470fa09ff3b96d72db274262201Robert Greenwalt break; 136b979f79158f9c470fa09ff3b96d72db274262201Robert Greenwalt default: // unexpected 1376eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti // leave state alone 138b979f79158f9c470fa09ff3b96d72db274262201Robert Greenwalt break; 139ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff } 14096ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff } 14164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 14264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti } else { 14364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // Synchronous: mark operation pending to prevent duplication 14464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti *interfaceStateP = INTERFACE_ADDING_2; 14564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti object_unlock_exclusive(thisObject); 14664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 14764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // this section runs with mutex unlocked 14864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti const struct iid_vtable *x = &class__->mInterfaces[index]; 14964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti size_t offset = x->mOffset; 150fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ? 151fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt class__->mSize : x[1].mOffset) - offset; 152fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt void *thisItf = (char *) thisObject + offset; 153fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt memset(thisItf, 0, size); 15464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti ((void **) thisItf)[1] = thisObject; 15564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti VoidHook init = MPH_init_table[MPH].mInit; 15664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti if (NULL != init) 157ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff (*init)(thisItf); 158ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff result = SL_RESULT_SUCCESS; 159e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti 160e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti // re-lock mutex to update state 16164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti object_lock_exclusive(thisObject); 162e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti assert(INTERFACE_ADDING_2 == *interfaceStateP); 163e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti *interfaceStateP = INTERFACE_ADDED; 164fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt } 165e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti 1666eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti // mutex is still locked 16764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti break; 16864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 1696eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti default: // disallow adding of (partially) initialized interfaces 1706eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti result = SL_RESULT_PRECONDITIONS_VIOLATED; 171e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti break; 172e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti 17364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti } 174e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti 175fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt object_unlock_exclusive(thisObject); 176e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti return result; 177ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff} 17864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 1796eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colittistatic SLresult IDynamicInterfaceManagement_RemoveInterface( 1806eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti SLDynamicInterfaceManagementItf self, const SLInterfaceID iid) 1816eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti{ 1826eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti // validate input parameters 1836eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti if (NULL == iid) 18464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti return SL_RESULT_PARAMETER_INVALID; 1856eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self; 186fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt IObject *thisObject = (IObject *) this->mThis; 1876eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti const ClassTable *class__ = thisObject->mClass; 1886eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti int MPH, index; 18964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) 19064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti return SL_RESULT_PRECONDITIONS_VIOLATED; 19164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti SLresult result; 19264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index]; 19364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 19464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // check interface state 19564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti object_lock_exclusive(thisObject); 19664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti switch (*interfaceStateP) { 19764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 19864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti case INTERFACE_ADDED: // normal cases 199fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt case INTERFACE_SUSPENDED: 20064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti { 20164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // Mark operation pending to prevent duplication 2028c6c2c3c929acad783b9a56b8d9efa597d0ae609Lorenzo Colitti *interfaceStateP = INTERFACE_REMOVING; 2031dfb6b67555d04973dfb9d1100dfc1c6a5200633Hugo Benichi thisObject->mGottenMask &= ~(1 << index); 2048c6c2c3c929acad783b9a56b8d9efa597d0ae609Lorenzo Colitti object_unlock_exclusive(thisObject); 2058c6c2c3c929acad783b9a56b8d9efa597d0ae609Lorenzo Colitti 206ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff // The deinitialization is done with mutex unlocked 207ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff const struct iid_vtable *x = &class__->mInterfaces[index]; 20864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti size_t offset = x->mOffset; 20964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti void *thisItf = (char *) thisObject + offset; 21064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti VoidHook deinit = MPH_init_table[MPH].mDeinit; 21164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti if (NULL != deinit) 21264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti (*deinit)(thisItf); 213ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff#ifndef NDEBUG 214ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff size_t size = ((SLuint32) (index + 1) == class__->mInterfaceCount ? 215e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti class__->mSize : x[1].mOffset) - offset; 216ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff memset(thisItf, 0x55, size); 217ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff#endif 218ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff result = SL_RESULT_SUCCESS; 21964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 2207dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti // Note that this was previously locked, but then unlocked for the deinit hook 2217dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti object_lock_exclusive(thisObject); 2227dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti assert(INTERFACE_REMOVING == *interfaceStateP); 223ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff *interfaceStateP = INTERFACE_UNINITIALIZED; 224ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff } 225ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff 226ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff // mutex is still locked 227ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff break; 228ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff 229ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff default: 230ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff // disallow removal of non-dynamic interfaces, or interfaces which are 231ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff // currently being resumed (will not auto-cancel an asynchronous resume) 232ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff result = SL_RESULT_PRECONDITIONS_VIOLATED; 233ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff break; 23464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 23564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti } 23664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 237ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff object_unlock_exclusive(thisObject); 238ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff return result; 239e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti} 240e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti 2414e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang// Called by a worker thread to handle an asynchronous ResumeInterface. 242e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti// Parameter self is the DynamicInterface, and MPH specifies which interface to resume. 2434e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang 24464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colittistatic void HandleResume(void *self, int MPH) 24564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti{ 24664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 24764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // validate input parameters 248fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt IDynamicInterfaceManagement *thisDIM = (IDynamicInterfaceManagement *) self; 249fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt assert(NULL != thisDIM); 250fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt IObject *thisObject = thisDIM->mThis; 251fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt assert(NULL != thisObject); 25264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti assert(0 <= MPH && MPH < MPH_MAX); 25364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti const ClassTable *class__ = thisObject->mClass; 25464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti assert(NULL != class__); 25564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti int index = class__->mMPH_to_index[MPH]; 2567dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti assert(0 <= index && index < (int) class__->mInterfaceCount); 25764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index]; 25864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti SLresult result; 25964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 2604e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang // check interface state 2614e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang object_lock_exclusive(thisObject); 262ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff SLuint32 state = *interfaceStateP; 263fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt switch (state) { 264ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff 265ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff case INTERFACE_RESUMING_1: // normal case 266ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff { 267ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff // change state to indicate we are now resuming the interface 268ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff *interfaceStateP = INTERFACE_RESUMING_2; 269ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff object_unlock_exclusive(thisObject); 270fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt 271ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff // this section runs with mutex unlocked 2727dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti const struct iid_vtable *x = &class__->mInterfaces[index]; 27396ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff size_t offset = x->mOffset; 274ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff void *thisItf = (char *) thisObject + offset; 275ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff VoidHook resume = MPH_init_table[MPH].mResume; 276ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff if (NULL != resume) 2777dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti (*resume)(thisItf); 2787dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti result = SL_RESULT_SUCCESS; 2797dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti 2807dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti // re-lock mutex to update state 2817dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti object_lock_exclusive(thisObject); 2827dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti assert(INTERFACE_RESUMING_2 == *interfaceStateP); 2837dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti state = INTERFACE_ADDED; 2847dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti } 2857dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti break; 286fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt 28764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti case INTERFACE_RESUMING_1A: // operation was aborted while on work queue 28864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti result = SL_RESULT_OPERATION_ABORTED; 28964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti state = INTERFACE_SUSPENDED; 29064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti break; 29164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 29264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti default: // impossible 293fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt assert(SL_BOOLEAN_FALSE); 29464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti result = SL_RESULT_INTERNAL_ERROR; 29564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti break; 29664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 29764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti } 29864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 29964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // mutex is locked, update state 30064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti *interfaceStateP = state; 301fd202e6f84ab0ee6a64aa81f94c3039eb10f8e17Robert Greenwalt 30264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // Make a copy of these, so we can call the callback with mutex unlocked 30364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti slDynamicInterfaceManagementCallback callback = thisDIM->mCallback; 304befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline void *context = thisDIM->mContext; 305befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline object_unlock_exclusive(thisObject); 306befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline 307befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline // Note that the mutex is unlocked during the callback 308befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline if (NULL != callback) { 309befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID 31064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti (*callback)(&thisDIM->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid); 311befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline } 312befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline} 313befe778c73e48417942fc31c06509bac8e5ca0d2Erik Kline 31464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colittistatic SLresult IDynamicInterfaceManagement_ResumeInterface(SLDynamicInterfaceManagementItf self, 31564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti const SLInterfaceID iid, SLboolean async) 31664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti{ 317e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti // validate input parameters 318ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff if (NULL == iid) 319ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff return SL_RESULT_PARAMETER_INVALID; 320ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self; 321ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff IObject *thisObject = (IObject *) this->mThis; 322ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff const ClassTable *class__ = thisObject->mClass; 323ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff int MPH, index; 324ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) 325ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff return SL_RESULT_PRECONDITIONS_VIOLATED; 326ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff assert(index < (int) class__->mInterfaceCount); 327e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index]; 328e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti SLresult result; 32964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti 33064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti // check interface state 331ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff object_lock_exclusive(thisObject); 332ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff switch (*interfaceStateP) { 333ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff 334ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff case INTERFACE_SUSPENDED: // normal case 335ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff if (async) { 336ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff // Asynchronous: mark operation pending and cancellable 337ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff *interfaceStateP = INTERFACE_RESUMING_1; 338ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff object_unlock_exclusive(thisObject); 339ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff 340e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti // this section runs with mutex unlocked 341e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti result = ThreadPool_add(&thisObject->mEngine->mThreadPool, HandleResume, this, MPH); 342e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti if (SL_RESULT_SUCCESS != result) { 343e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti // Engine was destroyed during resume, or insufficient memory, 344e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti // so restore mInterfaceStates state to prior value 345e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti object_lock_exclusive(thisObject); 346ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff switch (*interfaceStateP) { 347e1ad1849f3a65c1ff06919351ef1d73e9bc8854eLorenzo Colitti case INTERFACE_RESUMING_1: // normal 34864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti case INTERFACE_RESUMING_1A: // operation aborted while mutex unlocked 34964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti *interfaceStateP = INTERFACE_SUSPENDED; 35064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti break; 351ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff default: // unexpected 352ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff // leave state alone 353ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff break; 354ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff } 355ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff } 356ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff 357ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff } else { 358 // Synchronous: mark operation pending to prevent duplication 359 *interfaceStateP = INTERFACE_RESUMING_2; 360 object_unlock_exclusive(thisObject); 361 362 // this section runs with mutex unlocked 363 const struct iid_vtable *x = &class__->mInterfaces[index]; 364 size_t offset = x->mOffset; 365 void *thisItf = (char *) this + offset; 366 VoidHook resume = MPH_init_table[MPH].mResume; 367 if (NULL != resume) 368 (*resume)(thisItf); 369 result = SL_RESULT_SUCCESS; 370 371 // re-lock mutex to update state 372 object_lock_exclusive(thisObject); 373 assert(INTERFACE_RESUMING_2 == *interfaceStateP); 374 *interfaceStateP = INTERFACE_ADDED; 375 } 376 377 // mutex is now unlocked 378 break; 379 380 default: // disallow resumption of non-suspended interfaces 381 object_unlock_exclusive(thisObject); 382 result = SL_RESULT_PRECONDITIONS_VIOLATED; 383 break; 384 } 385 386 object_unlock_exclusive(thisObject); 387 return result; 388} 389 390static SLresult IDynamicInterfaceManagement_RegisterCallback(SLDynamicInterfaceManagementItf self, 391 slDynamicInterfaceManagementCallback callback, void *pContext) 392{ 393 IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self; 394 IObject *thisObject = this->mThis; 395 object_lock_exclusive(thisObject); 396 this->mCallback = callback; 397 this->mContext = pContext; 398 object_unlock_exclusive(thisObject); 399 return SL_RESULT_SUCCESS; 400} 401 402static const struct SLDynamicInterfaceManagementItf_ IDynamicInterfaceManagement_Itf = { 403 IDynamicInterfaceManagement_AddInterface, 404 IDynamicInterfaceManagement_RemoveInterface, 405 IDynamicInterfaceManagement_ResumeInterface, 406 IDynamicInterfaceManagement_RegisterCallback 407}; 408 409void IDynamicInterfaceManagement_init(void *self) 410{ 411 IDynamicInterfaceManagement *this = (IDynamicInterfaceManagement *) self; 412 this->mItf = &IDynamicInterfaceManagement_Itf; 413 this->mCallback = NULL; 414 this->mContext = NULL; 415} 416