Loading media/java/android/media/AudioService.java +56 −23 Original line number Original line Diff line number Diff line Loading @@ -81,6 +81,10 @@ public class AudioService extends IAudioService.Stub { private static final String TAG = "AudioService"; private static final String TAG = "AudioService"; /** Debug remote control client/display feature */ // TODO set to false before release protected static final boolean DEBUG_RC = true; /** How long to delay before persisting a change in volume/ringer mode. */ /** How long to delay before persisting a change in volume/ringer mode. */ private static final int PERSIST_DELAY = 3000; private static final int PERSIST_DELAY = 3000; Loading Loading @@ -3072,7 +3076,7 @@ public class AudioService extends IAudioService.Stub { /** /** * Update the remote control displays with the new "focused" client generation * Update the remote control displays with the new "focused" client generation */ */ private void setNewRcClientOnDisplays_syncAfRcsCurrc(int newClientGeneration, private void setNewRcClientOnDisplays_syncRcsCurrc(int newClientGeneration, ComponentName newClientEventReceiver, boolean clearing) { ComponentName newClientEventReceiver, boolean clearing) { // NOTE: Only one IRemoteControlDisplay supported in this implementation // NOTE: Only one IRemoteControlDisplay supported in this implementation if (mRcDisplay != null) { if (mRcDisplay != null) { Loading @@ -3091,7 +3095,7 @@ public class AudioService extends IAudioService.Stub { /** /** * Update the remote control clients with the new "focused" client generation * Update the remote control clients with the new "focused" client generation */ */ private void setNewRcClientGenerationOnClients_syncAfRcsCurrc(int newClientGeneration) { private void setNewRcClientGenerationOnClients_syncRcsCurrc(int newClientGeneration) { Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); while(stackIterator.hasNext()) { while(stackIterator.hasNext()) { RemoteControlStackEntry se = stackIterator.next(); RemoteControlStackEntry se = stackIterator.next(); Loading @@ -3115,27 +3119,26 @@ public class AudioService extends IAudioService.Stub { * @param clearing true if the new client generation value maps to a remote control update * @param clearing true if the new client generation value maps to a remote control update * where the display should be cleared. * where the display should be cleared. */ */ private void setNewRcClient_syncAfRcsCurrc(int newClientGeneration, private void setNewRcClient_syncRcsCurrc(int newClientGeneration, ComponentName newClientEventReceiver, boolean clearing) { ComponentName newClientEventReceiver, boolean clearing) { // send the new valid client generation ID to all displays // send the new valid client generation ID to all displays setNewRcClientOnDisplays_syncAfRcsCurrc(newClientGeneration, newClientEventReceiver, setNewRcClientOnDisplays_syncRcsCurrc(newClientGeneration, newClientEventReceiver, clearing); clearing); // send the new valid client generation ID to all clients // send the new valid client generation ID to all clients setNewRcClientGenerationOnClients_syncAfRcsCurrc(newClientGeneration); setNewRcClientGenerationOnClients_syncRcsCurrc(newClientGeneration); } } /** /** * Called when processing MSG_RCDISPLAY_CLEAR event * Called when processing MSG_RCDISPLAY_CLEAR event */ */ private void onRcDisplayClear() { private void onRcDisplayClear() { // TODO remove log before release if (DEBUG_RC) Log.i(TAG, "Clear remote control display"); Log.i(TAG, "Clear remote control display"); synchronized(mRCStack) { synchronized(mRCStack) { synchronized(mCurrentRcLock) { synchronized(mCurrentRcLock) { mCurrentRcClientGen++; mCurrentRcClientGen++; // synchronously update the displays and clients with the new client generation // synchronously update the displays and clients with the new client generation setNewRcClient_syncAfRcsCurrc(mCurrentRcClientGen, setNewRcClient_syncRcsCurrc(mCurrentRcClientGen, null /*event receiver*/, true /*clearing*/); null /*event receiver*/, true /*clearing*/); } } } } Loading @@ -3148,13 +3151,12 @@ public class AudioService extends IAudioService.Stub { synchronized(mRCStack) { synchronized(mRCStack) { synchronized(mCurrentRcLock) { synchronized(mCurrentRcLock) { if ((mCurrentRcClient != null) && (mCurrentRcClient.equals(rcse.mRcClient))) { if ((mCurrentRcClient != null) && (mCurrentRcClient.equals(rcse.mRcClient))) { // TODO remove log before release if (DEBUG_RC) Log.i(TAG, "Display/update remote control "); Log.i(TAG, "Display/update remote control "); mCurrentRcClientGen++; mCurrentRcClientGen++; // synchronously update the displays and clients with // synchronously update the displays and clients with // the new client generation // the new client generation setNewRcClient_syncAfRcsCurrc(mCurrentRcClientGen, setNewRcClient_syncRcsCurrc(mCurrentRcClientGen, rcse.mReceiverComponent /*event receiver*/, rcse.mReceiverComponent /*event receiver*/, false /*clearing*/); false /*clearing*/); Loading Loading @@ -3374,6 +3376,13 @@ public class AudioService extends IAudioService.Stub { * of displays if necessary. * of displays if necessary. */ */ private class RcDisplayDeathHandler implements IBinder.DeathRecipient { private class RcDisplayDeathHandler implements IBinder.DeathRecipient { private IBinder mCb; // To be notified of client's death public RcDisplayDeathHandler(IBinder b) { if (DEBUG_RC) Log.i(TAG, "new RcDisplayDeathHandler for "+b); mCb = b; } public void binderDied() { public void binderDied() { synchronized(mRCStack) { synchronized(mRCStack) { Log.w(TAG, "RemoteControl: display died"); Log.w(TAG, "RemoteControl: display died"); Loading @@ -3381,27 +3390,31 @@ public class AudioService extends IAudioService.Stub { } } } } } public void unlinkToRcDisplayDeath() { if (DEBUG_RC) Log.i(TAG, "unlinkToRcDisplayDeath for "+mCb); private void rcDisplay_stopDeathMonitor_syncRcStack() { if (mRcDisplay != null) { // we had a display before, stop monitoring its death IBinder b = mRcDisplay.asBinder(); try { try { b.unlinkToDeath(mRcDisplayDeathHandler, 0); mCb.unlinkToDeath(this, 0); } catch (java.util.NoSuchElementException e) { } catch (java.util.NoSuchElementException e) { // being conservative here // not much we can do here, the display was being unregistered anyway Log.e(TAG, "Error while trying to unlink display death handler " + e); Log.e(TAG, "Encountered " + e + " in unlinkToRcDisplayDeath()"); e.printStackTrace(); e.printStackTrace(); } } } } } private void rcDisplay_stopDeathMonitor_syncRcStack() { if (mRcDisplay != null) { // implies (mRcDisplayDeathHandler != null) // we had a display before, stop monitoring its death mRcDisplayDeathHandler.unlinkToRcDisplayDeath(); } } } private void rcDisplay_startDeathMonitor_syncRcStack() { private void rcDisplay_startDeathMonitor_syncRcStack() { if (mRcDisplay != null) { if (mRcDisplay != null) { // new non-null display, monitor its death // new non-null display, monitor its death IBinder b = mRcDisplay.asBinder(); IBinder b = mRcDisplay.asBinder(); mRcDisplayDeathHandler = new RcDisplayDeathHandler(); mRcDisplayDeathHandler = new RcDisplayDeathHandler(b); try { try { b.linkToDeath(mRcDisplayDeathHandler, 0); b.linkToDeath(mRcDisplayDeathHandler, 0); } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -3412,9 +3425,15 @@ public class AudioService extends IAudioService.Stub { } } } } /** * Register an IRemoteControlDisplay and notify all IRemoteControlClient of the new display. * Since only one IRemoteControlDisplay is supported, this will unregister the previous display. * @param rcd the IRemoteControlDisplay to register. No effect if null. */ public void registerRemoteControlDisplay(IRemoteControlDisplay rcd) { public void registerRemoteControlDisplay(IRemoteControlDisplay rcd) { if (DEBUG_RC) Log.d(TAG, ">>> registerRemoteControlDisplay("+rcd+")"); synchronized(mRCStack) { synchronized(mRCStack) { if (mRcDisplay == rcd) { if ((mRcDisplay == rcd) || (rcd == null)) { return; return; } } // if we had a display before, stop monitoring its death // if we had a display before, stop monitoring its death Loading @@ -3424,6 +3443,8 @@ public class AudioService extends IAudioService.Stub { rcDisplay_startDeathMonitor_syncRcStack(); rcDisplay_startDeathMonitor_syncRcStack(); // let all the remote control clients there is a new display // let all the remote control clients there is a new display // no need to unplug the previous because we only support one display // and the clients don't track the death of the display Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); while(stackIterator.hasNext()) { while(stackIterator.hasNext()) { RemoteControlStackEntry rcse = stackIterator.next(); RemoteControlStackEntry rcse = stackIterator.next(); Loading @@ -3439,8 +3460,20 @@ public class AudioService extends IAudioService.Stub { } } } } /** * Unregister an IRemoteControlDisplay. * Since only one IRemoteControlDisplay is supported, this has no effect if the one to * unregister is not the current one. * @param rcd the IRemoteControlDisplay to unregister. No effect if null. */ public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) { public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) { if (DEBUG_RC) Log.d(TAG, "<<< unregisterRemoteControlDisplay("+rcd+")"); synchronized(mRCStack) { synchronized(mRCStack) { // only one display here, so you can only unregister the current display if ((rcd == null) || (rcd != mRcDisplay)) { if (DEBUG_RC) Log.w(TAG, " trying to unregister unregistered RCD"); return; } // if we had a display before, stop monitoring its death // if we had a display before, stop monitoring its death rcDisplay_stopDeathMonitor_syncRcStack(); rcDisplay_stopDeathMonitor_syncRcStack(); mRcDisplay = null; mRcDisplay = null; Loading Loading
media/java/android/media/AudioService.java +56 −23 Original line number Original line Diff line number Diff line Loading @@ -81,6 +81,10 @@ public class AudioService extends IAudioService.Stub { private static final String TAG = "AudioService"; private static final String TAG = "AudioService"; /** Debug remote control client/display feature */ // TODO set to false before release protected static final boolean DEBUG_RC = true; /** How long to delay before persisting a change in volume/ringer mode. */ /** How long to delay before persisting a change in volume/ringer mode. */ private static final int PERSIST_DELAY = 3000; private static final int PERSIST_DELAY = 3000; Loading Loading @@ -3072,7 +3076,7 @@ public class AudioService extends IAudioService.Stub { /** /** * Update the remote control displays with the new "focused" client generation * Update the remote control displays with the new "focused" client generation */ */ private void setNewRcClientOnDisplays_syncAfRcsCurrc(int newClientGeneration, private void setNewRcClientOnDisplays_syncRcsCurrc(int newClientGeneration, ComponentName newClientEventReceiver, boolean clearing) { ComponentName newClientEventReceiver, boolean clearing) { // NOTE: Only one IRemoteControlDisplay supported in this implementation // NOTE: Only one IRemoteControlDisplay supported in this implementation if (mRcDisplay != null) { if (mRcDisplay != null) { Loading @@ -3091,7 +3095,7 @@ public class AudioService extends IAudioService.Stub { /** /** * Update the remote control clients with the new "focused" client generation * Update the remote control clients with the new "focused" client generation */ */ private void setNewRcClientGenerationOnClients_syncAfRcsCurrc(int newClientGeneration) { private void setNewRcClientGenerationOnClients_syncRcsCurrc(int newClientGeneration) { Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); while(stackIterator.hasNext()) { while(stackIterator.hasNext()) { RemoteControlStackEntry se = stackIterator.next(); RemoteControlStackEntry se = stackIterator.next(); Loading @@ -3115,27 +3119,26 @@ public class AudioService extends IAudioService.Stub { * @param clearing true if the new client generation value maps to a remote control update * @param clearing true if the new client generation value maps to a remote control update * where the display should be cleared. * where the display should be cleared. */ */ private void setNewRcClient_syncAfRcsCurrc(int newClientGeneration, private void setNewRcClient_syncRcsCurrc(int newClientGeneration, ComponentName newClientEventReceiver, boolean clearing) { ComponentName newClientEventReceiver, boolean clearing) { // send the new valid client generation ID to all displays // send the new valid client generation ID to all displays setNewRcClientOnDisplays_syncAfRcsCurrc(newClientGeneration, newClientEventReceiver, setNewRcClientOnDisplays_syncRcsCurrc(newClientGeneration, newClientEventReceiver, clearing); clearing); // send the new valid client generation ID to all clients // send the new valid client generation ID to all clients setNewRcClientGenerationOnClients_syncAfRcsCurrc(newClientGeneration); setNewRcClientGenerationOnClients_syncRcsCurrc(newClientGeneration); } } /** /** * Called when processing MSG_RCDISPLAY_CLEAR event * Called when processing MSG_RCDISPLAY_CLEAR event */ */ private void onRcDisplayClear() { private void onRcDisplayClear() { // TODO remove log before release if (DEBUG_RC) Log.i(TAG, "Clear remote control display"); Log.i(TAG, "Clear remote control display"); synchronized(mRCStack) { synchronized(mRCStack) { synchronized(mCurrentRcLock) { synchronized(mCurrentRcLock) { mCurrentRcClientGen++; mCurrentRcClientGen++; // synchronously update the displays and clients with the new client generation // synchronously update the displays and clients with the new client generation setNewRcClient_syncAfRcsCurrc(mCurrentRcClientGen, setNewRcClient_syncRcsCurrc(mCurrentRcClientGen, null /*event receiver*/, true /*clearing*/); null /*event receiver*/, true /*clearing*/); } } } } Loading @@ -3148,13 +3151,12 @@ public class AudioService extends IAudioService.Stub { synchronized(mRCStack) { synchronized(mRCStack) { synchronized(mCurrentRcLock) { synchronized(mCurrentRcLock) { if ((mCurrentRcClient != null) && (mCurrentRcClient.equals(rcse.mRcClient))) { if ((mCurrentRcClient != null) && (mCurrentRcClient.equals(rcse.mRcClient))) { // TODO remove log before release if (DEBUG_RC) Log.i(TAG, "Display/update remote control "); Log.i(TAG, "Display/update remote control "); mCurrentRcClientGen++; mCurrentRcClientGen++; // synchronously update the displays and clients with // synchronously update the displays and clients with // the new client generation // the new client generation setNewRcClient_syncAfRcsCurrc(mCurrentRcClientGen, setNewRcClient_syncRcsCurrc(mCurrentRcClientGen, rcse.mReceiverComponent /*event receiver*/, rcse.mReceiverComponent /*event receiver*/, false /*clearing*/); false /*clearing*/); Loading Loading @@ -3374,6 +3376,13 @@ public class AudioService extends IAudioService.Stub { * of displays if necessary. * of displays if necessary. */ */ private class RcDisplayDeathHandler implements IBinder.DeathRecipient { private class RcDisplayDeathHandler implements IBinder.DeathRecipient { private IBinder mCb; // To be notified of client's death public RcDisplayDeathHandler(IBinder b) { if (DEBUG_RC) Log.i(TAG, "new RcDisplayDeathHandler for "+b); mCb = b; } public void binderDied() { public void binderDied() { synchronized(mRCStack) { synchronized(mRCStack) { Log.w(TAG, "RemoteControl: display died"); Log.w(TAG, "RemoteControl: display died"); Loading @@ -3381,27 +3390,31 @@ public class AudioService extends IAudioService.Stub { } } } } } public void unlinkToRcDisplayDeath() { if (DEBUG_RC) Log.i(TAG, "unlinkToRcDisplayDeath for "+mCb); private void rcDisplay_stopDeathMonitor_syncRcStack() { if (mRcDisplay != null) { // we had a display before, stop monitoring its death IBinder b = mRcDisplay.asBinder(); try { try { b.unlinkToDeath(mRcDisplayDeathHandler, 0); mCb.unlinkToDeath(this, 0); } catch (java.util.NoSuchElementException e) { } catch (java.util.NoSuchElementException e) { // being conservative here // not much we can do here, the display was being unregistered anyway Log.e(TAG, "Error while trying to unlink display death handler " + e); Log.e(TAG, "Encountered " + e + " in unlinkToRcDisplayDeath()"); e.printStackTrace(); e.printStackTrace(); } } } } } private void rcDisplay_stopDeathMonitor_syncRcStack() { if (mRcDisplay != null) { // implies (mRcDisplayDeathHandler != null) // we had a display before, stop monitoring its death mRcDisplayDeathHandler.unlinkToRcDisplayDeath(); } } } private void rcDisplay_startDeathMonitor_syncRcStack() { private void rcDisplay_startDeathMonitor_syncRcStack() { if (mRcDisplay != null) { if (mRcDisplay != null) { // new non-null display, monitor its death // new non-null display, monitor its death IBinder b = mRcDisplay.asBinder(); IBinder b = mRcDisplay.asBinder(); mRcDisplayDeathHandler = new RcDisplayDeathHandler(); mRcDisplayDeathHandler = new RcDisplayDeathHandler(b); try { try { b.linkToDeath(mRcDisplayDeathHandler, 0); b.linkToDeath(mRcDisplayDeathHandler, 0); } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -3412,9 +3425,15 @@ public class AudioService extends IAudioService.Stub { } } } } /** * Register an IRemoteControlDisplay and notify all IRemoteControlClient of the new display. * Since only one IRemoteControlDisplay is supported, this will unregister the previous display. * @param rcd the IRemoteControlDisplay to register. No effect if null. */ public void registerRemoteControlDisplay(IRemoteControlDisplay rcd) { public void registerRemoteControlDisplay(IRemoteControlDisplay rcd) { if (DEBUG_RC) Log.d(TAG, ">>> registerRemoteControlDisplay("+rcd+")"); synchronized(mRCStack) { synchronized(mRCStack) { if (mRcDisplay == rcd) { if ((mRcDisplay == rcd) || (rcd == null)) { return; return; } } // if we had a display before, stop monitoring its death // if we had a display before, stop monitoring its death Loading @@ -3424,6 +3443,8 @@ public class AudioService extends IAudioService.Stub { rcDisplay_startDeathMonitor_syncRcStack(); rcDisplay_startDeathMonitor_syncRcStack(); // let all the remote control clients there is a new display // let all the remote control clients there is a new display // no need to unplug the previous because we only support one display // and the clients don't track the death of the display Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator(); while(stackIterator.hasNext()) { while(stackIterator.hasNext()) { RemoteControlStackEntry rcse = stackIterator.next(); RemoteControlStackEntry rcse = stackIterator.next(); Loading @@ -3439,8 +3460,20 @@ public class AudioService extends IAudioService.Stub { } } } } /** * Unregister an IRemoteControlDisplay. * Since only one IRemoteControlDisplay is supported, this has no effect if the one to * unregister is not the current one. * @param rcd the IRemoteControlDisplay to unregister. No effect if null. */ public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) { public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) { if (DEBUG_RC) Log.d(TAG, "<<< unregisterRemoteControlDisplay("+rcd+")"); synchronized(mRCStack) { synchronized(mRCStack) { // only one display here, so you can only unregister the current display if ((rcd == null) || (rcd != mRcDisplay)) { if (DEBUG_RC) Log.w(TAG, " trying to unregister unregistered RCD"); return; } // if we had a display before, stop monitoring its death // if we had a display before, stop monitoring its death rcDisplay_stopDeathMonitor_syncRcStack(); rcDisplay_stopDeathMonitor_syncRcStack(); mRcDisplay = null; mRcDisplay = null; Loading