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

Commit b3ccbb31 authored by Honggang's avatar Honggang Committed by takeshi tanigawa
Browse files

Fix issue that the disconnect tone doesn't sound from BTHS

When the call is disconnected, the BTHF state is changed to IDLE and
SCO connection is disconnected before playing disconnect tone. So the
disconnect tone can't be sound from BTHS.

Add DISCONNECTED state for HFP and keep the state until disconnect tone
sounds from BT.

Test: manual - Checked whether the disconnect tone is sound from the
BTHS
Test: auto - Passed BluetoothPhoneServiceTest
Bug: 69645337

Change-Id: I6deca4ccee97b8b1a50c491810d2b75f6741c0e9
parent 3a75c622
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ public class BluetoothPhoneServiceImpl {
    private static final int CALL_STATE_INCOMING = 4;
    private static final int CALL_STATE_WAITING = 5;
    private static final int CALL_STATE_IDLE = 6;
    private static final int CALL_STATE_DISCONNECTED = 7;

    // match up with bthf_call_state_t of bt_hf.h
    // Terminate all held or set UDUB("busy") to a waiting call
@@ -84,6 +85,7 @@ public class BluetoothPhoneServiceImpl {
    private String mRingingAddress = null;
    private int mRingingAddressType = 0;
    private Call mOldHeldCall = null;
    private boolean mIsDisconnectedTonePlaying = false;

    /**
     * Binder implementation of IBluetoothHeadsetPhone. Implements the command interface that the
@@ -387,6 +389,12 @@ public class BluetoothPhoneServiceImpl {
            }
            updateHeadsetWithCallState(false /* force */);
        }

        @Override
        public void onDisconnectedTonePlaying(boolean isTonePlaying) {
            mIsDisconnectedTonePlaying = isTonePlaying;
            updateHeadsetWithCallState(false /* force */);
        }
    };

    /**
@@ -816,6 +824,7 @@ public class BluetoothPhoneServiceImpl {
        CallsManager callsManager = mCallsManager;
        Call ringingCall = mCallsManager.getRingingCall();
        Call dialingCall = mCallsManager.getOutgoingCall();
        boolean hasOnlyDisconnectedCalls = mCallsManager.hasOnlyDisconnectedCalls();

        //
        // !! WARNING !!
@@ -831,6 +840,9 @@ public class BluetoothPhoneServiceImpl {
            bluetoothCallState = CALL_STATE_INCOMING;
        } else if (dialingCall != null) {
            bluetoothCallState = CALL_STATE_ALERTING;
        } else if (hasOnlyDisconnectedCalls || mIsDisconnectedTonePlaying) {
            // Keep the DISCONNECTED state until the disconnect tone's playback is done
            bluetoothCallState = CALL_STATE_DISCONNECTED;
        }
        return bluetoothCallState;
    }
+9 −1
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ public class CallAudioManager extends CallsManagerListenerBase {

    private Call mForegroundCall;
    private boolean mIsTonePlaying = false;
    private boolean mIsDisconnectedTonePlaying = false;
    private InCallTonePlayer mHoldTonePlayer;

    public CallAudioManager(CallAudioRouteStateMachine callAudioRouteStateMachine,
@@ -519,6 +520,11 @@ public class CallAudioManager extends CallsManagerListenerBase {
                isTonePlaying ? CallAudioModeStateMachine.TONE_STARTED_PLAYING
                        : CallAudioModeStateMachine.TONE_STOPPED_PLAYING,
                makeArgsForModeStateMachine());

        if (!isTonePlaying && mIsDisconnectedTonePlaying) {
            mCallsManager.onDisconnectedTonePlaying(false);
            mIsDisconnectedTonePlaying = false;
        }
    }

    private void onCallLeavingState(Call call, int state) {
@@ -699,6 +705,8 @@ public class CallAudioManager extends CallsManagerListenerBase {

            if (toneToPlay != InCallTonePlayer.TONE_INVALID) {
                mPlayerFactory.createPlayer(toneToPlay).startTone();
                mCallsManager.onDisconnectedTonePlaying(true);
                mIsDisconnectedTonePlaying = true;
            }
        }
    }
+20 −1
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ public class CallsManager extends Call.ListenerBase
        void onSessionModifyRequestReceived(Call call, VideoProfile videoProfile);
        void onHoldToneRequested(Call call);
        void onExternalCallChanged(Call call, boolean isExternalCall);
        void onDisconnectedTonePlaying(boolean isTonePlaying);
    }

    private static final String TAG = "CallsManager";
@@ -773,7 +774,11 @@ public class CallsManager extends Call.ListenerBase
        return false;
    }

    boolean hasOnlyDisconnectedCalls() {
    @VisibleForTesting
    public boolean hasOnlyDisconnectedCalls() {
        if (mCalls.size() == 0) {
            return false;
        }
        for (Call call : mCalls) {
            if (!call.isDisconnected()) {
                return false;
@@ -1788,6 +1793,20 @@ public class CallsManager extends Call.ListenerBase
        }
    }

    /**
     * Called when disconnect tone is started or stopped, including any InCallTone
     * after disconnected call.
     *
     * @param isTonePlaying true if the disconnected tone is started, otherwise the disconnected
     * tone is stopped.
     */
    void onDisconnectedTonePlaying(boolean isTonePlaying) {
        Log.v(this, "onDisconnectedTonePlaying, %s", isTonePlaying ? "started" : "stopped");
        for (CallsManagerListener listener : mListeners) {
            listener.onDisconnectedTonePlaying(isTonePlaying);
        }
    }

    void markCallAsRinging(Call call) {
        setCallState(call, CallState.RINGING, "ringing set explicitly");
    }
+4 −0
Original line number Diff line number Diff line
@@ -88,4 +88,8 @@ public class CallsManagerListenerBase implements CallsManager.CallsManagerListen
    @Override
    public void onExternalCallChanged(Call call, boolean isExternalCall) {
    }

    @Override
    public void onDisconnectedTonePlaying(boolean isTonePlaying) {
    }
}
+27 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ public class BluetoothPhoneServiceTest extends TelecomTestCase {
    private static final int CALL_STATE_INCOMING = 4;
    private static final int CALL_STATE_WAITING = 5;
    private static final int CALL_STATE_IDLE = 6;
    private static final int CALL_STATE_DISCONNECTED = 7;
    // Terminate all held or set UDUB("busy") to a waiting call
    private static final int CHLD_TYPE_RELEASEHELD = 0;
    // Terminate all active calls and accepts a waiting/held call
@@ -110,6 +111,7 @@ public class BluetoothPhoneServiceTest extends TelecomTestCase {
        doReturn(null).when(mMockCallsManager).getHeldCall();
        doReturn(null).when(mMockCallsManager).getOutgoingCall();
        doReturn(0).when(mMockCallsManager).getNumHeldCalls();
        doReturn(false).when(mMockCallsManager).hasOnlyDisconnectedCalls();
        mBluetoothPhoneService = new BluetoothPhoneServiceImpl(mContext, mLock, mMockCallsManager,
                mock(BluetoothAdapterProxy.class), mMockPhoneAccountRegistrar);

@@ -816,6 +818,25 @@ public class BluetoothPhoneServiceTest extends TelecomTestCase {
        verify(mMockBluetoothHeadset).phoneStateChanged(0, 0, CALL_STATE_ALERTING, "", 128);
    }

    @MediumTest
    public void testOnCallStateChangedDisconnected() throws Exception {
        Call disconnectedCall = createDisconnectedCall();
        doReturn(true).when(mMockCallsManager).hasOnlyDisconnectedCalls();
        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(disconnectedCall,
                CallState.DISCONNECTING, CallState.DISCONNECTED);
        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DISCONNECTED),
                eq(""), eq(128));

        doReturn(false).when(mMockCallsManager).hasOnlyDisconnectedCalls();
        mBluetoothPhoneService.mCallsManagerListener.onDisconnectedTonePlaying(true);
        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_DISCONNECTED),
                eq(""), eq(128));

        mBluetoothPhoneService.mCallsManagerListener.onDisconnectedTonePlaying(false);
        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
                eq(""), eq(128));
    }

    @MediumTest
    public void testOnCallStateChanged() throws Exception {
        Call ringingCall = createRingingCall();
@@ -929,6 +950,12 @@ public class BluetoothPhoneServiceTest extends TelecomTestCase {
        return call;
    }

    private Call createDisconnectedCall() {
        Call call = mock(Call.class);
        when(mMockCallsManager.getFirstCallWithState(CallState.DISCONNECTED)).thenReturn(call);
        return call;
    }

    private Call createForegroundCall() {
        Call call = mock(Call.class);
        when(mMockCallsManager.getForegroundCall()).thenReturn(call);