Skip to content

Commit ebf6478

Browse files
Eric LaurentAndroid (Google) Code Review
authored andcommitted
Merge "Fix issue 4673378: switching from VoIP to GSM call"
2 parents ce00275 + 9f103de commit ebf6478

File tree

1 file changed

+108
-80
lines changed

1 file changed

+108
-80
lines changed

media/java/android/media/AudioService.java

Lines changed: 108 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)