@@ -343,9 +343,8 @@ public AudioService(Context context) {
343343 readPersistedSettings ();
344344 mSettingsObserver = new SettingsObserver ();
345345 createStreamStates ();
346- // Call setMode() to initialize mSetModeDeathHandlers
347- mMode = AudioSystem .MODE_INVALID ;
348- setMode (AudioSystem .MODE_NORMAL , null );
346+
347+ mMode = AudioSystem .MODE_NORMAL ;
349348 mMediaServerOk = true ;
350349
351350 // Call setRingerModeInt() to apply correct mute
@@ -768,37 +767,27 @@ private class SetModeDeathHandler implements IBinder.DeathRecipient {
768767 private int mPid ;
769768 private int mMode = AudioSystem .MODE_NORMAL ; // Current mode set by this client
770769
771- SetModeDeathHandler (IBinder cb ) {
770+ SetModeDeathHandler (IBinder cb , int pid ) {
772771 mCb = cb ;
773- mPid = Binder . getCallingPid () ;
772+ mPid = pid ;
774773 }
775774
776775 public void binderDied () {
776+ IBinder newModeOwner = null ;
777777 synchronized (mSetModeDeathHandlers ) {
778778 Log .w (TAG , "setMode() client died" );
779779 int index = mSetModeDeathHandlers .indexOf (this );
780780 if (index < 0 ) {
781781 Log .w (TAG , "unregistered setMode() client died" );
782782 } else {
783- mSetModeDeathHandlers .remove (this );
784- // If dead client was a the top of client list,
785- // apply next mode in the stack
786- if (index == 0 ) {
787- // mSetModeDeathHandlers is never empty as the initial entry
788- // created when AudioService starts is never removed
789- SetModeDeathHandler hdlr = mSetModeDeathHandlers .get (0 );
790- int mode = hdlr .getMode ();
791- if (AudioService .this .mMode != mode ) {
792- if (AudioSystem .setPhoneState (mode ) == AudioSystem .AUDIO_STATUS_OK ) {
793- AudioService .this .mMode = mode ;
794- if (mode != AudioSystem .MODE_NORMAL ) {
795- disconnectBluetoothSco (mCb );
796- }
797- }
798- }
799- }
783+ newModeOwner = setModeInt (AudioSystem .MODE_NORMAL , mCb , mPid );
800784 }
801785 }
786+ // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
787+ // SCO connections not started by the application changing the mode
788+ if (newModeOwner != null ) {
789+ disconnectBluetoothSco (newModeOwner );
790+ }
802791 }
803792
804793 public int getPid () {
@@ -828,60 +817,97 @@ public void setMode(int mode, IBinder cb) {
828817 return ;
829818 }
830819
831- synchronized (mSettingsLock ) {
820+ IBinder newModeOwner = null ;
821+ synchronized (mSetModeDeathHandlers ) {
832822 if (mode == AudioSystem .MODE_CURRENT ) {
833823 mode = mMode ;
834824 }
835- if (mode != mMode ) {
825+ newModeOwner = setModeInt (mode , cb , Binder .getCallingPid ());
826+ }
827+ // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
828+ // SCO connections not started by the application changing the mode
829+ if (newModeOwner != null ) {
830+ disconnectBluetoothSco (newModeOwner );
831+ }
832+ }
836833
837- // automatically handle audio focus for mode changes
838- handleFocusForCalls (mMode , mode , cb );
834+ // must be called synchronized on mSetModeDeathHandlers
835+ // setModeInt() returns a non null IBInder if the audio mode was successfully set to
836+ // any mode other than NORMAL.
837+ IBinder setModeInt (int mode , IBinder cb , int pid ) {
838+ IBinder newModeOwner = null ;
839+ if (cb == null ) {
840+ Log .e (TAG , "setModeInt() called with null binder" );
841+ return newModeOwner ;
842+ }
839843
840- if (AudioSystem .setPhoneState (mode ) == AudioSystem .AUDIO_STATUS_OK ) {
841- mMode = mode ;
844+ SetModeDeathHandler hdlr = null ;
845+ Iterator iter = mSetModeDeathHandlers .iterator ();
846+ while (iter .hasNext ()) {
847+ SetModeDeathHandler h = (SetModeDeathHandler )iter .next ();
848+ if (h .getPid () == pid ) {
849+ hdlr = h ;
850+ // Remove from client list so that it is re-inserted at top of list
851+ iter .remove ();
852+ hdlr .getBinder ().unlinkToDeath (hdlr , 0 );
853+ break ;
854+ }
855+ }
856+ int status = AudioSystem .AUDIO_STATUS_OK ;
857+ do {
858+ if (mode == AudioSystem .MODE_NORMAL ) {
859+ // get new mode from client at top the list if any
860+ if (!mSetModeDeathHandlers .isEmpty ()) {
861+ hdlr = mSetModeDeathHandlers .get (0 );
862+ cb = hdlr .getBinder ();
863+ mode = hdlr .getMode ();
864+ }
865+ } else {
866+ if (hdlr == null ) {
867+ hdlr = new SetModeDeathHandler (cb , pid );
868+ }
869+ // Register for client death notification
870+ try {
871+ cb .linkToDeath (hdlr , 0 );
872+ } catch (RemoteException e ) {
873+ // Client has died!
874+ Log .w (TAG , "setMode() could not link to " +cb +" binder death" );
875+ }
842876
843- synchronized (mSetModeDeathHandlers ) {
844- SetModeDeathHandler hdlr = null ;
845- Iterator iter = mSetModeDeathHandlers .iterator ();
846- while (iter .hasNext ()) {
847- SetModeDeathHandler h = (SetModeDeathHandler )iter .next ();
848- if (h .getBinder () == cb ) {
849- hdlr = h ;
850- // Remove from client list so that it is re-inserted at top of list
851- iter .remove ();
852- break ;
853- }
854- }
855- if (hdlr == null ) {
856- hdlr = new SetModeDeathHandler (cb );
857- // cb is null when setMode() is called by AudioService constructor
858- if (cb != null ) {
859- // Register for client death notification
860- try {
861- cb .linkToDeath (hdlr , 0 );
862- } catch (RemoteException e ) {
863- // Client has died!
864- Log .w (TAG , "setMode() could not link to " +cb +" binder death" );
865- }
866- }
867- }
868- // Last client to call setMode() is always at top of client list
869- // as required by SetModeDeathHandler.binderDied()
870- mSetModeDeathHandlers .add (0 , hdlr );
871- hdlr .setMode (mode );
872- }
877+ // Last client to call setMode() is always at top of client list
878+ // as required by SetModeDeathHandler.binderDied()
879+ mSetModeDeathHandlers .add (0 , hdlr );
880+ hdlr .setMode (mode );
881+ }
873882
874- // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
875- // SCO connections not started by the application changing the mode
876- if (mode != AudioSystem .MODE_NORMAL ) {
877- disconnectBluetoothSco (cb );
883+ if (mode != mMode ) {
884+ status = AudioSystem .setPhoneState (mode );
885+ if (status == AudioSystem .AUDIO_STATUS_OK ) {
886+ // automatically handle audio focus for mode changes
887+ handleFocusForCalls (mMode , mode , cb );
888+ mMode = mode ;
889+ } else {
890+ if (hdlr != null ) {
891+ mSetModeDeathHandlers .remove (hdlr );
892+ cb .unlinkToDeath (hdlr , 0 );
878893 }
894+ // force reading new top of mSetModeDeathHandlers stack
895+ mode = AudioSystem .MODE_NORMAL ;
879896 }
897+ } else {
898+ status = AudioSystem .AUDIO_STATUS_OK ;
899+ }
900+ } while (status != AudioSystem .AUDIO_STATUS_OK && !mSetModeDeathHandlers .isEmpty ());
901+
902+ if (status == AudioSystem .AUDIO_STATUS_OK ) {
903+ if (mode != AudioSystem .MODE_NORMAL ) {
904+ newModeOwner = cb ;
880905 }
881906 int streamType = getActiveStreamType (AudioManager .USE_DEFAULT_STREAM_TYPE );
882907 int index = mStreamStates [STREAM_VOLUME_ALIAS [streamType ]].mIndex ;
883908 setStreamVolumeInt (STREAM_VOLUME_ALIAS [streamType ], index , true , false );
884909 }
910+ return newModeOwner ;
885911 }
886912
887913 /** pre-condition: oldMode != newMode */
@@ -1345,28 +1371,30 @@ private void requestScoState(int state) {
13451371 broadcastScoConnectionState (AudioManager .SCO_AUDIO_STATE_CONNECTING );
13461372 // Accept SCO audio activation only in NORMAL audio mode or if the mode is
13471373 // currently controlled by the same client process.
1348- if ((AudioService .this .mMode == AudioSystem .MODE_NORMAL ||
1349- mSetModeDeathHandlers .get (0 ).getPid () == mCreatorPid ) &&
1350- (mScoAudioState == SCO_STATE_INACTIVE ||
1351- mScoAudioState == SCO_STATE_DEACTIVATE_REQ )) {
1352- if (mScoAudioState == SCO_STATE_INACTIVE ) {
1353- if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null ) {
1354- if (mBluetoothHeadset .startScoUsingVirtualVoiceCall (
1355- mBluetoothHeadsetDevice )) {
1356- mScoAudioState = SCO_STATE_ACTIVE_INTERNAL ;
1357- } else {
1358- broadcastScoConnectionState (
1359- AudioManager .SCO_AUDIO_STATE_DISCONNECTED );
1374+ synchronized (mSetModeDeathHandlers ) {
1375+ if ((mSetModeDeathHandlers .isEmpty () ||
1376+ mSetModeDeathHandlers .get (0 ).getPid () == mCreatorPid ) &&
1377+ (mScoAudioState == SCO_STATE_INACTIVE ||
1378+ mScoAudioState == SCO_STATE_DEACTIVATE_REQ )) {
1379+ if (mScoAudioState == SCO_STATE_INACTIVE ) {
1380+ if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null ) {
1381+ if (mBluetoothHeadset .startScoUsingVirtualVoiceCall (
1382+ mBluetoothHeadsetDevice )) {
1383+ mScoAudioState = SCO_STATE_ACTIVE_INTERNAL ;
1384+ } else {
1385+ broadcastScoConnectionState (
1386+ AudioManager .SCO_AUDIO_STATE_DISCONNECTED );
1387+ }
1388+ } else if (getBluetoothHeadset ()) {
1389+ mScoAudioState = SCO_STATE_ACTIVATE_REQ ;
13601390 }
1361- } else if (getBluetoothHeadset ()) {
1362- mScoAudioState = SCO_STATE_ACTIVATE_REQ ;
1391+ } else {
1392+ mScoAudioState = SCO_STATE_ACTIVE_INTERNAL ;
1393+ broadcastScoConnectionState (AudioManager .SCO_AUDIO_STATE_CONNECTED );
13631394 }
13641395 } else {
1365- mScoAudioState = SCO_STATE_ACTIVE_INTERNAL ;
1366- broadcastScoConnectionState (AudioManager .SCO_AUDIO_STATE_CONNECTED );
1396+ broadcastScoConnectionState (AudioManager .SCO_AUDIO_STATE_DISCONNECTED );
13671397 }
1368- } else {
1369- broadcastScoConnectionState (AudioManager .SCO_AUDIO_STATE_DISCONNECTED );
13701398 }
13711399 } else if (state == BluetoothHeadset .STATE_AUDIO_DISCONNECTED &&
13721400 (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
0 commit comments