Loading src/com/android/server/telecom/CallAudioModeStateMachine.java +4 −4 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ public class CallAudioModeStateMachine extends StateMachine { mCallAudioManager.stopCallWaiting(); mCallAudioManager.startRinging(); mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS); mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.RINGING_FOCUS); } @Override Loading Loading @@ -288,7 +288,7 @@ public class CallAudioModeStateMachine extends StateMachine { 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 Loading Loading @@ -350,7 +350,7 @@ public class CallAudioModeStateMachine extends StateMachine { 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 Loading Loading @@ -407,7 +407,7 @@ public class CallAudioModeStateMachine extends StateMachine { mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); mAudioManager.setMode(mMostRecentMode); mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS); mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS); } @Override Loading src/com/android/server/telecom/CallAudioRouteStateMachine.java +108 −9 Original line number Diff line number Diff line Loading @@ -105,7 +105,8 @@ public class CallAudioRouteStateMachine extends StateMachine { /** 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> AUDIO_ROUTE_TO_LOG_EVENT = new SparseArray<String>() {{ put(CallAudioState.ROUTE_BLUETOOTH, Log.Events.AUDIO_ROUTE_BT); Loading Loading @@ -135,6 +136,8 @@ public class CallAudioRouteStateMachine extends StateMachine { 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"); Loading @@ -148,6 +151,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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"; Loading @@ -160,7 +164,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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); } } Loading Loading @@ -217,6 +221,9 @@ public class CallAudioRouteStateMachine extends StateMachine { case USER_SWITCH_BASELINE_ROUTE: sendInternalMessage(calculateBaselineRouteMessage(true)); return HANDLED; case SWITCH_FOCUS: mAudioFocusType = msg.arg1; return NOT_HANDLED; default: return NOT_HANDLED; } Loading Loading @@ -268,7 +275,8 @@ public class CallAudioRouteStateMachine extends StateMachine { 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."); } Loading Loading @@ -350,7 +358,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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; Loading Loading @@ -449,7 +457,8 @@ public class CallAudioRouteStateMachine extends StateMachine { 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."); } Loading Loading @@ -527,7 +536,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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; Loading Loading @@ -652,6 +661,8 @@ public class CallAudioRouteStateMachine extends StateMachine { case SWITCH_FOCUS: if (msg.arg1 == NO_FOCUS) { reinitialize(); } else if (msg.arg1 == RINGING_FOCUS) { transitionTo(mRingingBluetoothRoute); } return HANDLED; case BT_AUDIO_DISCONNECT: Loading @@ -663,6 +674,87 @@ public class CallAudioRouteStateMachine extends StateMachine { } } 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() { Loading Loading @@ -717,8 +809,10 @@ public class CallAudioRouteStateMachine extends StateMachine { 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: Loading Loading @@ -816,7 +910,8 @@ public class CallAudioRouteStateMachine extends StateMachine { // 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."); } Loading Loading @@ -906,7 +1001,7 @@ public class CallAudioRouteStateMachine extends StateMachine { // 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; Loading Loading @@ -962,6 +1057,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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(); Loading @@ -972,6 +1068,7 @@ public class CallAudioRouteStateMachine extends StateMachine { * states */ private int mAvailableRoutes; private int mAudioFocusType; private boolean mWasOnSpeaker; private boolean mIsMuted; Loading Loading @@ -1006,6 +1103,7 @@ public class CallAudioRouteStateMachine extends StateMachine { addState(mActiveHeadsetRoute); addState(mActiveBluetoothRoute); addState(mActiveSpeakerRoute); addState(mRingingBluetoothRoute); addState(mQuiescentEarpieceRoute); addState(mQuiescentHeadsetRoute); addState(mQuiescentBluetoothRoute); Loading @@ -1025,6 +1123,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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); Loading tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java +70 −3 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import static org.mockito.Mockito.doNothing; 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; Loading Loading @@ -177,7 +178,7 @@ public class CallAudioRouteStateMachineTest 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, Loading Loading @@ -209,7 +210,7 @@ public class CallAudioRouteStateMachineTest 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, Loading @@ -230,6 +231,72 @@ public class CallAudioRouteStateMachineTest 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, Loading Loading @@ -677,7 +744,7 @@ public class CallAudioRouteStateMachineTest 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); Loading Loading
src/com/android/server/telecom/CallAudioModeStateMachine.java +4 −4 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ public class CallAudioModeStateMachine extends StateMachine { mCallAudioManager.stopCallWaiting(); mCallAudioManager.startRinging(); mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS); mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.RINGING_FOCUS); } @Override Loading Loading @@ -288,7 +288,7 @@ public class CallAudioModeStateMachine extends StateMachine { 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 Loading Loading @@ -350,7 +350,7 @@ public class CallAudioModeStateMachine extends StateMachine { 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 Loading Loading @@ -407,7 +407,7 @@ public class CallAudioModeStateMachine extends StateMachine { mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); mAudioManager.setMode(mMostRecentMode); mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.HAS_FOCUS); mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS); } @Override Loading
src/com/android/server/telecom/CallAudioRouteStateMachine.java +108 −9 Original line number Diff line number Diff line Loading @@ -105,7 +105,8 @@ public class CallAudioRouteStateMachine extends StateMachine { /** 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> AUDIO_ROUTE_TO_LOG_EVENT = new SparseArray<String>() {{ put(CallAudioState.ROUTE_BLUETOOTH, Log.Events.AUDIO_ROUTE_BT); Loading Loading @@ -135,6 +136,8 @@ public class CallAudioRouteStateMachine extends StateMachine { 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"); Loading @@ -148,6 +151,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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"; Loading @@ -160,7 +164,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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); } } Loading Loading @@ -217,6 +221,9 @@ public class CallAudioRouteStateMachine extends StateMachine { case USER_SWITCH_BASELINE_ROUTE: sendInternalMessage(calculateBaselineRouteMessage(true)); return HANDLED; case SWITCH_FOCUS: mAudioFocusType = msg.arg1; return NOT_HANDLED; default: return NOT_HANDLED; } Loading Loading @@ -268,7 +275,8 @@ public class CallAudioRouteStateMachine extends StateMachine { 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."); } Loading Loading @@ -350,7 +358,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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; Loading Loading @@ -449,7 +457,8 @@ public class CallAudioRouteStateMachine extends StateMachine { 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."); } Loading Loading @@ -527,7 +536,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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; Loading Loading @@ -652,6 +661,8 @@ public class CallAudioRouteStateMachine extends StateMachine { case SWITCH_FOCUS: if (msg.arg1 == NO_FOCUS) { reinitialize(); } else if (msg.arg1 == RINGING_FOCUS) { transitionTo(mRingingBluetoothRoute); } return HANDLED; case BT_AUDIO_DISCONNECT: Loading @@ -663,6 +674,87 @@ public class CallAudioRouteStateMachine extends StateMachine { } } 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() { Loading Loading @@ -717,8 +809,10 @@ public class CallAudioRouteStateMachine extends StateMachine { 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: Loading Loading @@ -816,7 +910,8 @@ public class CallAudioRouteStateMachine extends StateMachine { // 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."); } Loading Loading @@ -906,7 +1001,7 @@ public class CallAudioRouteStateMachine extends StateMachine { // 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; Loading Loading @@ -962,6 +1057,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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(); Loading @@ -972,6 +1068,7 @@ public class CallAudioRouteStateMachine extends StateMachine { * states */ private int mAvailableRoutes; private int mAudioFocusType; private boolean mWasOnSpeaker; private boolean mIsMuted; Loading Loading @@ -1006,6 +1103,7 @@ public class CallAudioRouteStateMachine extends StateMachine { addState(mActiveHeadsetRoute); addState(mActiveBluetoothRoute); addState(mActiveSpeakerRoute); addState(mRingingBluetoothRoute); addState(mQuiescentEarpieceRoute); addState(mQuiescentHeadsetRoute); addState(mQuiescentBluetoothRoute); Loading @@ -1025,6 +1123,7 @@ public class CallAudioRouteStateMachine extends StateMachine { 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); Loading
tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java +70 −3 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import static org.mockito.Mockito.doNothing; 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; Loading Loading @@ -177,7 +178,7 @@ public class CallAudioRouteStateMachineTest 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, Loading Loading @@ -209,7 +210,7 @@ public class CallAudioRouteStateMachineTest 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, Loading @@ -230,6 +231,72 @@ public class CallAudioRouteStateMachineTest 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, Loading Loading @@ -677,7 +744,7 @@ public class CallAudioRouteStateMachineTest 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); Loading