Merge "Modify ConnectionServiceAdapter to include Session"
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index c461c85..2e3c5bd 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -216,7 +216,7 @@
mCallAudioManager.stopCallWaiting();
mCallAudioManager.startRinging();
- mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS);
+ mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.RINGING_FOCUS);
}
@Override
@@ -291,7 +291,7 @@
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
mMostRecentMode = AudioManager.MODE_IN_CALL;
- mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS);
+ mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS);
}
@Override
@@ -353,7 +353,7 @@
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mMostRecentMode = AudioManager.MODE_IN_COMMUNICATION;
- mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS);
+ mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS);
}
@Override
@@ -410,7 +410,7 @@
mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
mAudioManager.setMode(mMostRecentMode);
- mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS);
+ mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS);
}
@Override
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index a9729e2..e3d459c 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -107,7 +107,8 @@
/** Valid values for mAudioFocusType */
public static final int NO_FOCUS = 1;
- public static final int HAS_FOCUS = 2;
+ public static final int ACTIVE_FOCUS = 2;
+ public static final int RINGING_FOCUS = 3;
private static final SparseArray<String> MESSAGE_CODE_TO_NAME = new SparseArray<String>() {{
put(CONNECT_WIRED_HEADSET, "CONNECT_WIRED_HEADSET");
@@ -130,6 +131,8 @@
put(USER_SWITCH_SPEAKER, "USER_SWITCH_SPEAKER");
put(USER_SWITCH_BASELINE_ROUTE, "USER_SWITCH_BASELINE_ROUTE");
+ put(UPDATE_SYSTEM_AUDIO_ROUTE, "UPDATE_SYSTEM_AUDIO_ROUTE");
+
put(MUTE_ON, "MUTE_ON");
put(MUTE_OFF, "MUTE_OFF");
put(TOGGLE_MUTE, "TOGGLE_MUTE");
@@ -143,6 +146,7 @@
private static final String ACTIVE_BLUETOOTH_ROUTE_NAME = "ActiveBluetoothRoute";
private static final String ACTIVE_SPEAKER_ROUTE_NAME = "ActiveSpeakerRoute";
private static final String ACTIVE_HEADSET_ROUTE_NAME = "ActiveHeadsetRoute";
+ private static final String RINGING_BLUETOOTH_ROUTE_NAME = "RingingBluetoothRoute";
private static final String QUIESCENT_EARPIECE_ROUTE_NAME = "QuiescentEarpieceRoute";
private static final String QUIESCENT_BLUETOOTH_ROUTE_NAME = "QuiescentBluetoothRoute";
private static final String QUIESCENT_SPEAKER_ROUTE_NAME = "QuiescentSpeakerRoute";
@@ -155,7 +159,7 @@
if (msg.obj != null && msg.obj instanceof Session) {
String messageCodeName = MESSAGE_CODE_TO_NAME.get(msg.what, "unknown");
Log.continueSession((Session) msg.obj, "CARSM.pM_" + messageCodeName);
- Log.i(this, "Message received: %s=%d", messageCodeName, msg.what);
+ Log.i(this, "Message received: %s=%d, arg1=%d", messageCodeName, msg.what, msg.arg1);
}
}
@@ -212,6 +216,9 @@
case USER_SWITCH_BASELINE_ROUTE:
sendInternalMessage(calculateBaselineRouteMessage(true));
return HANDLED;
+ case SWITCH_FOCUS:
+ mAudioFocusType = msg.arg1;
+ return NOT_HANDLED;
default:
return NOT_HANDLED;
}
@@ -263,7 +270,8 @@
case SWITCH_BLUETOOTH:
case USER_SWITCH_BLUETOOTH:
if ((mAvailableRoutes & ROUTE_BLUETOOTH) != 0) {
- transitionTo(mActiveBluetoothRoute);
+ transitionTo(mAudioFocusType == ACTIVE_FOCUS ?
+ mActiveBluetoothRoute : mRingingBluetoothRoute);
} else {
Log.w(this, "Ignoring switch to bluetooth command. Not available.");
}
@@ -345,7 +353,7 @@
transitionTo(mQuiescentSpeakerRoute);
return HANDLED;
case SWITCH_FOCUS:
- if (msg.arg1 == HAS_FOCUS) {
+ if (msg.arg1 == ACTIVE_FOCUS || msg.arg1 == RINGING_FOCUS) {
transitionTo(mActiveEarpieceRoute);
}
return HANDLED;
@@ -444,7 +452,8 @@
case SWITCH_BLUETOOTH:
case USER_SWITCH_BLUETOOTH:
if ((mAvailableRoutes & ROUTE_BLUETOOTH) != 0) {
- transitionTo(mActiveBluetoothRoute);
+ transitionTo(mAudioFocusType == ACTIVE_FOCUS ?
+ mActiveBluetoothRoute : mRingingBluetoothRoute);
} else {
Log.w(this, "Ignoring switch to bluetooth command. Not available.");
}
@@ -522,7 +531,7 @@
transitionTo(mQuiescentSpeakerRoute);
return HANDLED;
case SWITCH_FOCUS:
- if (msg.arg1 == HAS_FOCUS) {
+ if (msg.arg1 == ACTIVE_FOCUS || msg.arg1 == RINGING_FOCUS) {
transitionTo(mActiveHeadsetRoute);
}
return HANDLED;
@@ -647,6 +656,8 @@
case SWITCH_FOCUS:
if (msg.arg1 == NO_FOCUS) {
reinitialize();
+ } else if (msg.arg1 == RINGING_FOCUS) {
+ transitionTo(mRingingBluetoothRoute);
}
return HANDLED;
case BT_AUDIO_DISCONNECT:
@@ -658,6 +669,87 @@
}
}
+ class RingingBluetoothRoute extends BluetoothRoute {
+ @Override
+ public String getName() {
+ return RINGING_BLUETOOTH_ROUTE_NAME;
+ }
+
+ @Override
+ public boolean isActive() {
+ return false;
+ }
+
+ @Override
+ public void enter() {
+ super.enter();
+ setSpeakerphoneOn(false);
+ // Do not enable SCO audio here, since RING is being sent to the headset.
+ CallAudioState newState = new CallAudioState(mIsMuted, ROUTE_BLUETOOTH,
+ mAvailableRoutes);
+ setSystemAudioState(newState);
+ updateInternalCallAudioState();
+ }
+
+ @Override
+ public void updateSystemAudioState() {
+ updateInternalCallAudioState();
+ setSystemAudioState(mCurrentCallAudioState);
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (super.processMessage(msg) == HANDLED) {
+ return HANDLED;
+ }
+ switch (msg.what) {
+ case USER_SWITCH_EARPIECE:
+ mHasUserExplicitlyLeftBluetooth = true;
+ // fall through
+ case SWITCH_EARPIECE:
+ if ((mAvailableRoutes & ROUTE_EARPIECE) != 0) {
+ transitionTo(mActiveEarpieceRoute);
+ } else {
+ Log.w(this, "Ignoring switch to earpiece command. Not available.");
+ }
+ return HANDLED;
+ case SWITCH_BLUETOOTH:
+ case USER_SWITCH_BLUETOOTH:
+ // Nothing to do
+ return HANDLED;
+ case USER_SWITCH_HEADSET:
+ mHasUserExplicitlyLeftBluetooth = true;
+ // fall through
+ case SWITCH_HEADSET:
+ if ((mAvailableRoutes & ROUTE_WIRED_HEADSET) != 0) {
+ transitionTo(mActiveHeadsetRoute);
+ } else {
+ Log.w(this, "Ignoring switch to headset command. Not available.");
+ }
+ return HANDLED;
+ case USER_SWITCH_SPEAKER:
+ mHasUserExplicitlyLeftBluetooth = true;
+ // fall through
+ case SWITCH_SPEAKER:
+ transitionTo(mActiveSpeakerRoute);
+ return HANDLED;
+ case SWITCH_FOCUS:
+ if (msg.arg1 == NO_FOCUS) {
+ reinitialize();
+ } else if (msg.arg1 == ACTIVE_FOCUS) {
+ transitionTo(mActiveBluetoothRoute);
+ }
+ return HANDLED;
+ case BT_AUDIO_DISCONNECT:
+ // Ignore BT_AUDIO_DISCONNECT when ringing, since SCO audio should not be
+ // connected.
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ }
+ }
+
class QuiescentBluetoothRoute extends BluetoothRoute {
@Override
public String getName() {
@@ -712,8 +804,10 @@
transitionTo(mQuiescentSpeakerRoute);
return HANDLED;
case SWITCH_FOCUS:
- if (msg.arg1 == HAS_FOCUS) {
+ if (msg.arg1 == ACTIVE_FOCUS) {
transitionTo(mActiveBluetoothRoute);
+ } else if (msg.arg1 == RINGING_FOCUS) {
+ transitionTo(mRingingBluetoothRoute);
}
return HANDLED;
case BT_AUDIO_DISCONNECT:
@@ -811,7 +905,8 @@
// fall through
case SWITCH_BLUETOOTH:
if ((mAvailableRoutes & ROUTE_BLUETOOTH) != 0) {
- transitionTo(mActiveBluetoothRoute);
+ transitionTo(mAudioFocusType == ACTIVE_FOCUS ?
+ mActiveBluetoothRoute : mRingingBluetoothRoute);
} else {
Log.w(this, "Ignoring switch to bluetooth command. Not available.");
}
@@ -901,7 +996,7 @@
// Nothing to do
return HANDLED;
case SWITCH_FOCUS:
- if (msg.arg1 == HAS_FOCUS) {
+ if (msg.arg1 == ACTIVE_FOCUS || msg.arg1 == RINGING_FOCUS) {
transitionTo(mActiveSpeakerRoute);
}
return HANDLED;
@@ -957,6 +1052,7 @@
private final ActiveHeadsetRoute mActiveHeadsetRoute = new ActiveHeadsetRoute();
private final ActiveBluetoothRoute mActiveBluetoothRoute = new ActiveBluetoothRoute();
private final ActiveSpeakerRoute mActiveSpeakerRoute = new ActiveSpeakerRoute();
+ private final RingingBluetoothRoute mRingingBluetoothRoute = new RingingBluetoothRoute();
private final QuiescentEarpieceRoute mQuiescentEarpieceRoute = new QuiescentEarpieceRoute();
private final QuiescentHeadsetRoute mQuiescentHeadsetRoute = new QuiescentHeadsetRoute();
private final QuiescentBluetoothRoute mQuiescentBluetoothRoute = new QuiescentBluetoothRoute();
@@ -967,6 +1063,7 @@
* states
*/
private int mAvailableRoutes;
+ private int mAudioFocusType;
private boolean mWasOnSpeaker;
private boolean mIsMuted;
@@ -1002,6 +1099,7 @@
addState(mActiveHeadsetRoute);
addState(mActiveBluetoothRoute);
addState(mActiveSpeakerRoute);
+ addState(mRingingBluetoothRoute);
addState(mQuiescentEarpieceRoute);
addState(mQuiescentHeadsetRoute);
addState(mQuiescentBluetoothRoute);
@@ -1022,6 +1120,7 @@
mStateNameToRouteCode.put(mQuiescentBluetoothRoute.getName(), ROUTE_BLUETOOTH);
mStateNameToRouteCode.put(mQuiescentHeadsetRoute.getName(), ROUTE_WIRED_HEADSET);
mStateNameToRouteCode.put(mQuiescentSpeakerRoute.getName(), ROUTE_SPEAKER);
+ mStateNameToRouteCode.put(mRingingBluetoothRoute.getName(), ROUTE_BLUETOOTH);
mStateNameToRouteCode.put(mActiveEarpieceRoute.getName(), ROUTE_EARPIECE);
mStateNameToRouteCode.put(mActiveBluetoothRoute.getName(), ROUTE_BLUETOOTH);
mStateNameToRouteCode.put(mActiveHeadsetRoute.getName(), ROUTE_WIRED_HEADSET);
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index cb71c61..4e5fe69 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -51,6 +51,7 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -180,7 +181,7 @@
stateMachine.initialize(initState);
stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
- CallAudioRouteStateMachine.HAS_FOCUS);
+ CallAudioRouteStateMachine.ACTIVE_FOCUS);
stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.CONNECT_WIRED_HEADSET);
CallAudioState expectedMiddleState = new CallAudioState(false,
CallAudioState.ROUTE_WIRED_HEADSET,
@@ -212,7 +213,7 @@
stateMachine.initialize(initState);
stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
- CallAudioRouteStateMachine.HAS_FOCUS);
+ CallAudioRouteStateMachine.ACTIVE_FOCUS);
stateMachine.sendMessageWithSessionInfo(
CallAudioRouteStateMachine.USER_SWITCH_BASELINE_ROUTE);
CallAudioState expectedEndState = new CallAudioState(false,
@@ -233,6 +234,72 @@
assertEquals(expectedEndState, stateMachine.getCurrentCallAudioState());
}
+ @MediumTest
+ public void testBluetoothRinging() {
+ CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
+ mContext,
+ mockCallsManager,
+ mockBluetoothManager,
+ mockWiredHeadsetManager,
+ mockStatusBarNotifier,
+ mAudioServiceFactory,
+ true);
+
+ when(mockBluetoothManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
+ when(mockBluetoothManager.isBluetoothAvailable()).thenReturn(true);
+ when(mockAudioManager.isSpeakerphoneOn()).thenReturn(false);
+ CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH,
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH);
+ stateMachine.initialize(initState);
+
+ stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
+ CallAudioRouteStateMachine.RINGING_FOCUS);
+ waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
+
+ verify(mockBluetoothManager, never()).connectBluetoothAudio();
+
+ stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
+ CallAudioRouteStateMachine.ACTIVE_FOCUS);
+ waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
+ verify(mockBluetoothManager, times(1)).connectBluetoothAudio();
+ }
+
+ @MediumTest
+ public void testConnectBluetoothDuringRinging() {
+ CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
+ mContext,
+ mockCallsManager,
+ mockBluetoothManager,
+ mockWiredHeadsetManager,
+ mockStatusBarNotifier,
+ mAudioServiceFactory,
+ true);
+
+ when(mockBluetoothManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
+ when(mockBluetoothManager.isBluetoothAvailable()).thenReturn(false);
+ when(mockAudioManager.isSpeakerphoneOn()).thenReturn(false);
+ CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE,
+ CallAudioState.ROUTE_EARPIECE);
+ stateMachine.initialize(initState);
+
+ stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
+ CallAudioRouteStateMachine.RINGING_FOCUS);
+ when(mockBluetoothManager.isBluetoothAvailable()).thenReturn(true);
+ stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.CONNECT_BLUETOOTH);
+ waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
+
+ verify(mockBluetoothManager, never()).connectBluetoothAudio();
+ CallAudioState expectedEndState = new CallAudioState(false,
+ CallAudioState.ROUTE_BLUETOOTH,
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH);
+ verifyNewSystemCallAudioState(initState, expectedEndState);
+
+ stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
+ CallAudioRouteStateMachine.ACTIVE_FOCUS);
+ waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
+ verify(mockBluetoothManager, times(1)).connectBluetoothAudio();
+ }
+
@SmallTest
public void testInitializationWithEarpieceNoHeadsetNoBluetooth() {
CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE,
@@ -680,7 +747,7 @@
stateMachine.initialize(initState);
// Make the state machine have focus so that we actually do something
stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
- CallAudioRouteStateMachine.HAS_FOCUS);
+ CallAudioRouteStateMachine.ACTIVE_FOCUS);
stateMachine.sendMessageWithSessionInfo(params.action);
waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);