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

Commit 4e5ae524 authored by Sanket Agarwal's avatar Sanket Agarwal
Browse files

Race in hfp call termination when local termination faster than HFP

update.

If we make a call from the CarKitt and terminate it immidiately then the
CarKitt assumes no call has been created since phone hasnt replied yet
to the message from CarKitt. When it does reply, the CarKitt throws that
message away because it did not handle the intermediate state of
disconnection properly.

Bug: b/28122608

Change-Id: I98105fd36914612fc96cba4d56db97b342822ffa
(cherry picked from commit 57a102e5548a7a395bcd7feec3c1df6d61be8187)
parent 5e181c2e
Loading
Loading
Loading
Loading
+23 −4
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ public class HfpClientConnection extends Connection {

    private BluetoothHeadsetClient mHeadsetProfile;
    private BluetoothHeadsetClientCall mCurrentCall;
    private boolean mClosing;
    private boolean mClosed;
    private boolean mLocalDisconnect;
    private boolean mClientHasEcc;
@@ -89,8 +90,24 @@ public class HfpClientConnection extends Connection {
    public void handleCallChanged(BluetoothHeadsetClientCall call) {
        HfpClientConference conference = (HfpClientConference) getConference();
        mCurrentCall = call;

        int state = call.getState();

        // If this call is already terminated (locally) but we are only hearing about the handle of
        // the call right now -- then close the call.
        boolean closing = false;
        synchronized (this) {
            closing = mClosing;
        }
        if (closing && state != BluetoothHeadsetClientCall.CALL_STATE_TERMINATED) {
            if (mHeadsetProfile != null) {
                mHeadsetProfile.terminateCall(mDevice, mClientHasEcc ? mCurrentCall.getId() : 0);
                mLocalDisconnect = true;
            } else {
                Log.e(TAG, "HFP disconnected but call update received, ignore.");
            }
            return;
        }

        Log.d(TAG, "Got call state change to " + state);
        switch (state) {
            case BluetoothHeadsetClientCall.CALL_STATE_ACTIVE:
@@ -160,14 +177,16 @@ public class HfpClientConnection extends Connection {
    }

    @Override
    public void onDisconnect() {
    public synchronized void onDisconnect() {
        Log.d(TAG, "onDisconnect " + mCurrentCall);
        mClosing = true;
        if (!mClosed) {
            // In this state we can close the call without problems.
            if (mHeadsetProfile != null && mCurrentCall != null) {
                mHeadsetProfile.terminateCall(mDevice, mClientHasEcc ? mCurrentCall.getId() : 0);
                mLocalDisconnect = true;
            } else {
                close(DisconnectCause.LOCAL);
            } else if (mCurrentCall == null) {
                Log.w(TAG, "Call disconnected but call handle not received.");
            }
        }
    }