@@ -149,6 +149,7 @@ public class AudioService extends IAudioService.Stub {
149149 private int mMode ;
150150 // protects mRingerMode
151151 private final Object mSettingsLock = new Object ();
152+
152153 private boolean mMediaServerOk ;
153154
154155 private SoundPool mSoundPool ;
@@ -343,6 +344,14 @@ public void onError(int error) {
343344 // Keyguard manager proxy
344345 private KeyguardManager mKeyguardManager ;
345346
347+ // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
348+ // is controlled by Vol keys.
349+ private int mVolumeControlStream = -1 ;
350+ private final Object mForceControlStreamLock = new Object ();
351+ // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system
352+ // server process so in theory it is not necessary to monitor the client death.
353+ // However it is good to be ready for future evolutions.
354+ private ForceControlStreamClient mForceControlStreamClient = null ;
346355
347356 ///////////////////////////////////////////////////////////////////////////
348357 // Construction
@@ -538,8 +547,8 @@ public void adjustVolume(int direction, int flags) {
538547 public void adjustSuggestedStreamVolume (int direction , int suggestedStreamType , int flags ) {
539548
540549 int streamType ;
541- if (( flags & AudioManager . FLAG_FORCE_STREAM ) != 0 ) {
542- streamType = suggestedStreamType ;
550+ if (mVolumeControlStream != - 1 ) {
551+ streamType = mVolumeControlStream ;
543552 } else {
544553 streamType = getActiveStreamType (suggestedStreamType );
545554 }
@@ -682,6 +691,57 @@ public void setStreamVolume(int streamType, int index, int flags) {
682691 sendVolumeUpdate (streamType , oldIndex , index , flags );
683692 }
684693
694+ /** @see AudioManager#forceVolumeControlStream(int) */
695+ public void forceVolumeControlStream (int streamType , IBinder cb ) {
696+ synchronized (mForceControlStreamLock ) {
697+ mVolumeControlStream = streamType ;
698+ if (mVolumeControlStream == -1 ) {
699+ if (mForceControlStreamClient != null ) {
700+ mForceControlStreamClient .release ();
701+ mForceControlStreamClient = null ;
702+ }
703+ } else {
704+ mForceControlStreamClient = new ForceControlStreamClient (cb );
705+ }
706+ }
707+ }
708+
709+ private class ForceControlStreamClient implements IBinder .DeathRecipient {
710+ private IBinder mCb ; // To be notified of client's death
711+
712+ ForceControlStreamClient (IBinder cb ) {
713+ if (cb != null ) {
714+ try {
715+ cb .linkToDeath (this , 0 );
716+ } catch (RemoteException e ) {
717+ // Client has died!
718+ Log .w (TAG , "ForceControlStreamClient() could not link to " +cb +" binder death" );
719+ cb = null ;
720+ }
721+ }
722+ mCb = cb ;
723+ }
724+
725+ public void binderDied () {
726+ synchronized (mForceControlStreamLock ) {
727+ Log .w (TAG , "SCO client died" );
728+ if (mForceControlStreamClient != this ) {
729+ Log .w (TAG , "unregistered control stream client died" );
730+ } else {
731+ mForceControlStreamClient = null ;
732+ mVolumeControlStream = -1 ;
733+ }
734+ }
735+ }
736+
737+ public void release () {
738+ if (mCb != null ) {
739+ mCb .unlinkToDeath (this , 0 );
740+ mCb = null ;
741+ }
742+ }
743+ }
744+
685745 private int findVolumeDelta (int direction , int volume ) {
686746 int delta = 0 ;
687747 if (direction == AudioManager .ADJUST_RAISE ) {
0 commit comments