Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fda4f506 authored by Hall Liu's avatar Hall Liu Committed by Android (Google) Code Review
Browse files

Merge "Prevent BT reconnection from switching route" into nyc-dev

parents 01635b05 4f296ba3
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -321,23 +321,23 @@ public class CallAudioManager extends CallsManagerListenerBase {
        switch (route) {
            case CallAudioState.ROUTE_BLUETOOTH:
                mCallAudioRouteStateMachine.sendMessageWithSessionInfo(
                        CallAudioRouteStateMachine.SWITCH_BLUETOOTH);
                        CallAudioRouteStateMachine.USER_SWITCH_BLUETOOTH);
                return;
            case CallAudioState.ROUTE_SPEAKER:
                mCallAudioRouteStateMachine.sendMessageWithSessionInfo(
                        CallAudioRouteStateMachine.SWITCH_SPEAKER);
                        CallAudioRouteStateMachine.USER_SWITCH_SPEAKER);
                return;
            case CallAudioState.ROUTE_WIRED_HEADSET:
                mCallAudioRouteStateMachine.sendMessageWithSessionInfo(
                        CallAudioRouteStateMachine.SWITCH_HEADSET);
                        CallAudioRouteStateMachine.USER_SWITCH_HEADSET);
                return;
            case CallAudioState.ROUTE_EARPIECE:
                mCallAudioRouteStateMachine.sendMessageWithSessionInfo(
                        CallAudioRouteStateMachine.SWITCH_EARPIECE);
                        CallAudioRouteStateMachine.USER_SWITCH_EARPIECE);
                return;
            case CallAudioState.ROUTE_WIRED_OR_EARPIECE:
                mCallAudioRouteStateMachine.sendMessageWithSessionInfo(
                        CallAudioRouteStateMachine.SWITCH_BASELINE_ROUTE);
                        CallAudioRouteStateMachine.USER_SWITCH_BASELINE_ROUTE);
                return;
            default:
                Log.wtf(this, "Invalid route specified: %d", route);
+74 −15
Original line number Diff line number Diff line
@@ -85,6 +85,12 @@ public class CallAudioRouteStateMachine extends StateMachine {
    // Wired headset, earpiece, or speakerphone, in that order of precedence.
    public static final int SWITCH_BASELINE_ROUTE = 1005;

    public static final int USER_SWITCH_EARPIECE = 1101;
    public static final int USER_SWITCH_BLUETOOTH = 1102;
    public static final int USER_SWITCH_HEADSET = 1103;
    public static final int USER_SWITCH_SPEAKER = 1104;
    public static final int USER_SWITCH_BASELINE_ROUTE = 1105;

    public static final int REINITIALIZE = 2001;

    public static final int MUTE_ON = 3001;
@@ -114,6 +120,12 @@ public class CallAudioRouteStateMachine extends StateMachine {
        put(SWITCH_SPEAKER, "SWITCH_SPEAKER");
        put(SWITCH_BASELINE_ROUTE, "SWITCH_BASELINE_ROUTE");

        put(USER_SWITCH_EARPIECE, "USER_SWITCH_EARPIECE");
        put(USER_SWITCH_BLUETOOTH, "USER_SWITCH_BLUETOOTH");
        put(USER_SWITCH_HEADSET, "USER_SWITCH_HEADSET");
        put(USER_SWITCH_SPEAKER, "USER_SWITCH_SPEAKER");
        put(USER_SWITCH_BASELINE_ROUTE, "USER_SWITCH_BASELINE_ROUTE");

        put(REINITIALIZE, "REINITIALIZE");

        put(MUTE_ON, "MUTE_ON");
@@ -204,24 +216,17 @@ public class CallAudioRouteStateMachine extends StateMachine {
                        return NOT_HANDLED;
                    }
                case SWITCH_BASELINE_ROUTE:
                    if ((mAvailableRoutes & ROUTE_EARPIECE) != 0) {
                        sendInternalMessage(SWITCH_EARPIECE);
                    } else if ((mAvailableRoutes & ROUTE_WIRED_HEADSET) != 0) {
                        sendInternalMessage(SWITCH_HEADSET);
                    } else if (!mDoesDeviceSupportEarpieceRoute) {
                        sendInternalMessage(SWITCH_SPEAKER);
                    } else {
                        Log.e(this, new IllegalStateException(),
                                "Neither headset nor earpiece are available, but there is an " +
                                        "earpiece on the device. Defaulting to earpiece.");
                        sendInternalMessage(SWITCH_EARPIECE);
                    }
                    sendInternalMessage(calculateBaselineRouteMessage(false));
                    return HANDLED;
                case USER_SWITCH_BASELINE_ROUTE:
                    sendInternalMessage(calculateBaselineRouteMessage(true));
                    return HANDLED;
                case REINITIALIZE:
                    CallAudioState initState = getInitialAudioState();
                    mAvailableRoutes = initState.getSupportedRouteMask();
                    mIsMuted = initState.isMuted();
                    mWasOnSpeaker = initState.getRoute() == ROUTE_SPEAKER;
                    mHasUserExplicitlyLeftBluetooth = false;
                    transitionTo(mRouteCodeToQuiescentState.get(initState.getRoute()));
                    return HANDLED;
                default:
@@ -269,9 +274,11 @@ public class CallAudioRouteStateMachine extends StateMachine {
            }
            switch (msg.what) {
                case SWITCH_EARPIECE:
                case USER_SWITCH_EARPIECE:
                    // Nothing to do here
                    return HANDLED;
                case SWITCH_BLUETOOTH:
                case USER_SWITCH_BLUETOOTH:
                    if ((mAvailableRoutes & ROUTE_BLUETOOTH) != 0) {
                        transitionTo(mActiveBluetoothRoute);
                    } else {
@@ -279,6 +286,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    }
                    return HANDLED;
                case SWITCH_HEADSET:
                case USER_SWITCH_HEADSET:
                    if ((mAvailableRoutes & ROUTE_WIRED_HEADSET) != 0) {
                        transitionTo(mActiveHeadsetRoute);
                    } else {
@@ -286,6 +294,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    }
                    return HANDLED;
                case SWITCH_SPEAKER:
                case USER_SWITCH_SPEAKER:
                    transitionTo(mActiveSpeakerRoute);
                    return HANDLED;
                case SWITCH_FOCUS:
@@ -313,6 +322,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
        @Override
        public void enter() {
            super.enter();
            mHasUserExplicitlyLeftBluetooth = false;
            updateInternalCallAudioState();
        }

@@ -369,7 +379,11 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    sendInternalMessage(SWITCH_HEADSET);
                    return HANDLED;
                case CONNECT_BLUETOOTH:
                    if (!mHasUserExplicitlyLeftBluetooth) {
                        sendInternalMessage(SWITCH_BLUETOOTH);
                    } else {
                        updateSystemAudioState();
                    }
                    return HANDLED;
                case DISCONNECT_BLUETOOTH:
                    updateSystemAudioState();
@@ -428,6 +442,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
            }
            switch (msg.what) {
                case SWITCH_EARPIECE:
                case USER_SWITCH_EARPIECE:
                    if ((mAvailableRoutes & ROUTE_EARPIECE) != 0) {
                        transitionTo(mActiveEarpieceRoute);
                    } else {
@@ -435,6 +450,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    }
                    return HANDLED;
                case SWITCH_BLUETOOTH:
                case USER_SWITCH_BLUETOOTH:
                    if ((mAvailableRoutes & ROUTE_BLUETOOTH) != 0) {
                        transitionTo(mActiveBluetoothRoute);
                    } else {
@@ -442,9 +458,11 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    }
                    return HANDLED;
                case SWITCH_HEADSET:
                case USER_SWITCH_HEADSET:
                    // Nothing to do
                    return HANDLED;
                case SWITCH_SPEAKER:
                case USER_SWITCH_SPEAKER:
                    transitionTo(mActiveSpeakerRoute);
                    return HANDLED;
                case SWITCH_FOCUS:
@@ -472,6 +490,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
        @Override
        public void enter() {
            super.enter();
            mHasUserExplicitlyLeftBluetooth = false;
            updateInternalCallAudioState();
        }

@@ -531,7 +550,11 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    updateSystemAudioState();
                    return HANDLED;
                case CONNECT_BLUETOOTH:
                    if (!mHasUserExplicitlyLeftBluetooth) {
                        sendInternalMessage(SWITCH_BLUETOOTH);
                    } else {
                        updateSystemAudioState();
                    }
                    return HANDLED;
                case DISCONNECT_BLUETOOTH:
                    updateSystemAudioState();
@@ -590,6 +613,9 @@ public class CallAudioRouteStateMachine extends StateMachine {
                return HANDLED;
            }
            switch (msg.what) {
                case USER_SWITCH_EARPIECE:
                    mHasUserExplicitlyLeftBluetooth = true;
                    // fall through
                case SWITCH_EARPIECE:
                    if ((mAvailableRoutes & ROUTE_EARPIECE) != 0) {
                        transitionTo(mActiveEarpieceRoute);
@@ -598,8 +624,12 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    }
                    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);
@@ -607,6 +637,9 @@ public class CallAudioRouteStateMachine extends StateMachine {
                        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;
@@ -635,6 +668,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
        @Override
        public void enter() {
            super.enter();
            mHasUserExplicitlyLeftBluetooth = false;
            updateInternalCallAudioState();
        }

@@ -751,6 +785,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
            }
            switch(msg.what) {
                case SWITCH_EARPIECE:
                case USER_SWITCH_EARPIECE:
                    if ((mAvailableRoutes & ROUTE_EARPIECE) != 0) {
                        transitionTo(mActiveEarpieceRoute);
                    } else {
@@ -758,6 +793,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    }
                    return HANDLED;
                case SWITCH_BLUETOOTH:
                case USER_SWITCH_BLUETOOTH:
                    if ((mAvailableRoutes & ROUTE_BLUETOOTH) != 0) {
                        transitionTo(mActiveBluetoothRoute);
                    } else {
@@ -765,6 +801,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    }
                    return HANDLED;
                case SWITCH_HEADSET:
                case USER_SWITCH_HEADSET:
                    if ((mAvailableRoutes & ROUTE_WIRED_HEADSET) != 0) {
                        transitionTo(mActiveHeadsetRoute);
                    } else {
@@ -772,6 +809,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    }
                    return HANDLED;
                case SWITCH_SPEAKER:
                case USER_SWITCH_SPEAKER:
                    // Nothing to do
                    return HANDLED;
                case SWITCH_FOCUS:
@@ -799,6 +837,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
        @Override
        public void enter() {
            super.enter();
            mHasUserExplicitlyLeftBluetooth = false;
            // Omit setting mWasOnSpeaker to true here, since this does not reflect a call
            // actually being on speakerphone.
            updateInternalCallAudioState();
@@ -861,7 +900,11 @@ public class CallAudioRouteStateMachine extends StateMachine {
                    sendInternalMessage(SWITCH_HEADSET);
                    return HANDLED;
                case CONNECT_BLUETOOTH:
                    if (!mHasUserExplicitlyLeftBluetooth) {
                        sendInternalMessage(SWITCH_BLUETOOTH);
                    } else {
                        updateSystemAudioState();
                    }
                    return HANDLED;
                case DISCONNECT_BLUETOOTH:
                    updateSystemAudioState();
@@ -908,6 +951,7 @@ public class CallAudioRouteStateMachine extends StateMachine {
    private final StatusBarNotifier mStatusBarNotifier;
    private final CallAudioManager.AudioServiceFactory mAudioServiceFactory;
    private final boolean mDoesDeviceSupportEarpieceRoute;
    private boolean mHasUserExplicitlyLeftBluetooth = false;

    private HashMap<String, Integer> mStateNameToRouteCode;
    private HashMap<Integer, AudioState> mRouteCodeToQuiescentState;
@@ -1214,4 +1258,19 @@ public class CallAudioRouteStateMachine extends StateMachine {
        }
        return true;
    }

    private int calculateBaselineRouteMessage(boolean isExplicitUserRequest) {
        if ((mAvailableRoutes & ROUTE_EARPIECE) != 0) {
            return isExplicitUserRequest ? USER_SWITCH_EARPIECE : SWITCH_EARPIECE;
        } else if ((mAvailableRoutes & ROUTE_WIRED_HEADSET) != 0) {
            return isExplicitUserRequest ? USER_SWITCH_HEADSET : SWITCH_HEADSET;
        } else if (!mDoesDeviceSupportEarpieceRoute) {
            return isExplicitUserRequest ? USER_SWITCH_SPEAKER : SWITCH_SPEAKER;
        } else {
            Log.e(this, new IllegalStateException(),
                    "Neither headset nor earpiece are available, but there is an " +
                            "earpiece on the device. Defaulting to earpiece.");
            return isExplicitUserRequest ? USER_SWITCH_EARPIECE : SWITCH_EARPIECE;
        }
    }
}
 No newline at end of file
+49 −5
Original line number Diff line number Diff line
@@ -190,6 +190,46 @@ public class CallAudioRouteStateMachineTest
        verifyNewSystemCallAudioState(expectedMiddleState, initState);
    }

    @MediumTest
    public void testUserBluetoothSwitchOff() {
        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(true);
        CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH,
                CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH);
        stateMachine.initialize(initState);

        stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS,
                CallAudioRouteStateMachine.HAS_FOCUS);
        stateMachine.sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.USER_SWITCH_BASELINE_ROUTE);
        CallAudioState expectedEndState = new CallAudioState(false,
                CallAudioState.ROUTE_EARPIECE,
                CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH);

        waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);
        verifyNewSystemCallAudioState(initState, expectedEndState);
        resetMocks();

        stateMachine.sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH);
        stateMachine.sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.CONNECT_BLUETOOTH);

        waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE);

        assertEquals(expectedEndState, stateMachine.getCurrentCallAudioState());
    }

    @SmallTest
    public void testInitializationWithEarpieceNoHeadsetNoBluetooth() {
        CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE,
@@ -709,6 +749,15 @@ public class CallAudioRouteStateMachineTest

        // Verify that no substantive interactions have taken place with the
        // rest of the system
        verifyNoSystemAudioChanges();

        // Verify the end state
        CallAudioState expectedState = new CallAudioState(false, params.expectedRoute,
                params.expectedAvailableRoutes | CallAudioState.ROUTE_SPEAKER);
        assertEquals(expectedState, stateMachine.getCurrentCallAudioState());
    }

    private void verifyNoSystemAudioChanges() {
        verify(mockBluetoothManager, never()).disconnectBluetoothAudio();
        verify(mockBluetoothManager, never()).connectBluetoothAudio();
        verify(mockAudioManager, never()).setSpeakerphoneOn(any(Boolean.class));
@@ -716,11 +765,6 @@ public class CallAudioRouteStateMachineTest
                any(CallAudioState.class));
        verify(mockConnectionServiceWrapper, never()).onCallAudioStateChanged(
                any(Call.class), any(CallAudioState.class));

        // Verify the end state
        CallAudioState expectedState = new CallAudioState(false, params.expectedRoute,
                params.expectedAvailableRoutes | CallAudioState.ROUTE_SPEAKER);
        assertEquals(expectedState, stateMachine.getCurrentCallAudioState());
    }

    private void verifyNewSystemCallAudioState(CallAudioState expectedOldState,