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

Commit f1e63c0b authored by Sal Savage's avatar Sal Savage
Browse files

Replace BluetoothHeadsetClientCall with internal HfpClientCall

HFP Client Call metadata does not need to be shared outside the
Bluetooth stack. We're free to define our own parcelable object
internally and have it passed back to us.

This change removes BluetoothHeadsetClientCall in favor of our own
private call metadata objects, HfpClientCall.

Tag: #refactor
Bug: 206035301
Test: atest BluetoothInstrumentationTests
Change-Id: I21822e3cdc338878822b46ace6bb24568bc8008a
parent b0fc59df
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.bluetooth.a2dpsink;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClientCall;
import android.content.pm.PackageManager;
import android.media.AudioAttributes;
import android.media.AudioFocusRequest;
@@ -32,6 +31,7 @@ import android.util.Log;
import com.android.bluetooth.R;
import com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService;
import com.android.bluetooth.hfpclient.HeadsetClientService;
import com.android.bluetooth.hfpclient.HfpClientCall;

import java.util.List;

@@ -372,7 +372,7 @@ public class A2dpSinkStreamHandler extends Handler {
        }
        HeadsetClientService headsetClientService = HeadsetClientService.getHeadsetClientService();
        if (targetDevice != null && headsetClientService != null) {
            List<BluetoothHeadsetClientCall> currentCalls =
            List<HfpClientCall> currentCalls =
                    headsetClientService.getCurrentCalls(targetDevice);
            if (currentCalls == null) return false;
            return currentCalls.size() > 0;
+17 −6
Original line number Diff line number Diff line
@@ -244,6 +244,13 @@ public class HeadsetClientService extends ProfileService {
        }
    };

    private static BluetoothHeadsetClientCall toLegacyCall(HfpClientCall call) {
        if (call == null) return null;
        return new BluetoothHeadsetClientCall(call.getDevice(), call.getId(), call.getUUID(),
                call.getState(), call.getNumber(), call.isMultiParty(), call.isOutgoing(),
                call.isInBandRing());
    }

    /**
     * Handlers for incoming service calls
     */
@@ -579,7 +586,8 @@ public class HeadsetClientService extends ProfileService {
                HeadsetClientService service = getService(source);
                BluetoothHeadsetClientCall defaultValue = null;
                if (service != null) {
                    defaultValue = service.dial(device, number);
                    HfpClientCall call = service.dial(device, number);
                    defaultValue = toLegacyCall(call);
                }
                receiver.send(defaultValue);
            } catch (RuntimeException e) {
@@ -594,7 +602,10 @@ public class HeadsetClientService extends ProfileService {
                HeadsetClientService service = getService(source);
                List<BluetoothHeadsetClientCall> defaultValue = new ArrayList<>();
                if (service != null) {
                    defaultValue = service.getCurrentCalls(device);
                    List<HfpClientCall> calls = service.getCurrentCalls(device);
                    for (HfpClientCall call : calls) {
                        defaultValue.add(toLegacyCall(call));
                    }
                }
                receiver.send(defaultValue);
            } catch (RuntimeException e) {
@@ -1042,7 +1053,7 @@ public class HeadsetClientService extends ProfileService {
        return true;
    }

    public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
    public HfpClientCall dial(BluetoothDevice device, String number) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
@@ -1055,9 +1066,9 @@ public class HeadsetClientService extends ProfileService {
            return null;
        }

        BluetoothHeadsetClientCall call = new BluetoothHeadsetClientCall(device,
        HfpClientCall call = new HfpClientCall(device,
                HeadsetClientStateMachine.HF_ORIGINATED_CALL_ID,
                HeadsetClientHalConstants.CALL_STATE_DIALING, number, false  /* multiparty */,
                HfpClientCall.CALL_STATE_DIALING, number, false  /* multiparty */,
                true  /* outgoing */, sm.getInBandRing());
        Message msg = sm.obtainMessage(HeadsetClientStateMachine.DIAL_NUMBER);
        msg.obj = call;
@@ -1087,7 +1098,7 @@ public class HeadsetClientService extends ProfileService {
        return false;
    }

    public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
    public List<HfpClientCall> getCurrentCalls(BluetoothDevice device) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
+59 −56
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@ import static android.Manifest.permission.BLUETOOTH_CONNECT;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothHeadsetClientCall;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.hfp.BluetoothHfpProtoEnums;
@@ -143,10 +142,10 @@ public class HeadsetClientStateMachine extends StateMachine {

    // Set of calls that represent the accurate state of calls that exists on AG and the calls that
    // are currently in process of being notified to the AG from HF.
    private final Hashtable<Integer, BluetoothHeadsetClientCall> mCalls = new Hashtable<>();
    private final Hashtable<Integer, HfpClientCall> mCalls = new Hashtable<>();
    // Set of calls received from AG via the AT+CLCC command. We use this map to update the mCalls
    // which is eventually used to inform the telephony stack of any changes to call on HF.
    private final Hashtable<Integer, BluetoothHeadsetClientCall> mCallsUpdate = new Hashtable<>();
    private final Hashtable<Integer, HfpClientCall> mCallsUpdate = new Hashtable<>();

    private int mIndicatorNetworkState;
    private int mIndicatorNetworkType;
@@ -216,14 +215,14 @@ public class HeadsetClientStateMachine extends StateMachine {

        ProfileService.println(sb, "  mCalls:");
        if (mCalls != null) {
            for (BluetoothHeadsetClientCall call : mCalls.values()) {
            for (HfpClientCall call : mCalls.values()) {
                ProfileService.println(sb, "    " + call);
            }
        }

        ProfileService.println(sb, "  mCallsUpdate:");
        if (mCallsUpdate != null) {
            for (BluetoothHeadsetClientCall call : mCallsUpdate.values()) {
            for (HfpClientCall call : mCallsUpdate.values()) {
                ProfileService.println(sb, "    " + call);
            }
        }
@@ -327,9 +326,9 @@ public class HeadsetClientStateMachine extends StateMachine {
        mQueuedActions.add(new Pair<Integer, Object>(action, data));
    }

    private BluetoothHeadsetClientCall getCall(int... states) {
    private HfpClientCall getCall(int... states) {
        logD("getFromCallsWithStates states:" + Arrays.toString(states));
        for (BluetoothHeadsetClientCall c : mCalls.values()) {
        for (HfpClientCall c : mCalls.values()) {
            for (int s : states) {
                if (c.getState() == s) {
                    return c;
@@ -341,7 +340,7 @@ public class HeadsetClientStateMachine extends StateMachine {

    private int callsInState(int state) {
        int i = 0;
        for (BluetoothHeadsetClientCall c : mCalls.values()) {
        for (HfpClientCall c : mCalls.values()) {
            if (c.getState() == state) {
                i++;
            }
@@ -350,7 +349,7 @@ public class HeadsetClientStateMachine extends StateMachine {
        return i;
    }

    private void sendCallChangedIntent(BluetoothHeadsetClientCall c) {
    private void sendCallChangedIntent(HfpClientCall c) {
        logD("sendCallChangedIntent " + c);
        Intent intent = new Intent(BluetoothHeadsetClient.ACTION_CALL_CHANGED);
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -422,7 +421,7 @@ public class HeadsetClientStateMachine extends StateMachine {
        // First thing is to try to associate the outgoing HF with a valid call.
        Integer hfOriginatedAssoc = -1;
        if (mCalls.containsKey(HF_ORIGINATED_CALL_ID)) {
            BluetoothHeadsetClientCall c = mCalls.get(HF_ORIGINATED_CALL_ID);
            HfpClientCall c = mCalls.get(HF_ORIGINATED_CALL_ID);
            long cCreationElapsed = c.getCreationElapsedMilli();
            if (callAddedIds.size() > 0) {
                logD("Associating the first call with HF originated call");
@@ -441,8 +440,8 @@ public class HeadsetClientStateMachine extends StateMachine {

                // Clean out the state for outgoing call.
                for (Integer idx : mCalls.keySet()) {
                    BluetoothHeadsetClientCall c1 = mCalls.get(idx);
                    c1.setState(BluetoothHeadsetClientCall.CALL_STATE_TERMINATED);
                    HfpClientCall c1 = mCalls.get(idx);
                    c1.setState(HfpClientCall.CALL_STATE_TERMINATED);
                    sendCallChangedIntent(c1);
                }
                mCalls.clear();
@@ -459,22 +458,22 @@ public class HeadsetClientStateMachine extends StateMachine {

        // Terminate & remove the calls that are done.
        for (Integer idx : callRemovedIds) {
            BluetoothHeadsetClientCall c = mCalls.remove(idx);
            c.setState(BluetoothHeadsetClientCall.CALL_STATE_TERMINATED);
            HfpClientCall c = mCalls.remove(idx);
            c.setState(HfpClientCall.CALL_STATE_TERMINATED);
            sendCallChangedIntent(c);
        }

        // Add the new calls.
        for (Integer idx : callAddedIds) {
            BluetoothHeadsetClientCall c = mCallsUpdate.get(idx);
            HfpClientCall c = mCallsUpdate.get(idx);
            mCalls.put(idx, c);
            sendCallChangedIntent(c);
        }

        // Update the existing calls.
        for (Integer idx : callRetainedIds) {
            BluetoothHeadsetClientCall cOrig = mCalls.get(idx);
            BluetoothHeadsetClientCall cUpdate = mCallsUpdate.get(idx);
            HfpClientCall cOrig = mCalls.get(idx);
            HfpClientCall cUpdate = mCallsUpdate.get(idx);

            // If any of the fields differs, update and send intent
            if (!cOrig.getNumber().equals(cUpdate.getNumber())
@@ -497,7 +496,7 @@ public class HeadsetClientStateMachine extends StateMachine {
                        mService.getResources().getInteger(
                        R.integer.hfp_clcc_poll_interval_during_call));
            } else {
                if (getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING) != null) {
                if (getCall(HfpClientCall.CALL_STATE_INCOMING) != null) {
                    logD("Still have incoming call; polling");
                    sendMessageDelayed(QUERY_CURRENT_CALLS, QUERY_CURRENT_CALLS_WAIT_MILLIS);
                } else {
@@ -513,7 +512,7 @@ public class HeadsetClientStateMachine extends StateMachine {
            boolean outgoing) {
        logD("queryCallsUpdate: " + id);
        mCallsUpdate.put(id,
                new BluetoothHeadsetClientCall(mCurrentDevice, id, state, number, multiParty,
                new HfpClientCall(mCurrentDevice, id, state, number, multiParty,
                        outgoing, mInBandRing));
    }

@@ -522,11 +521,11 @@ public class HeadsetClientStateMachine extends StateMachine {

        logD("acceptCall: (" + flag + ")");

        BluetoothHeadsetClientCall c = getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING,
                BluetoothHeadsetClientCall.CALL_STATE_WAITING);
        HfpClientCall c = getCall(HfpClientCall.CALL_STATE_INCOMING,
                HfpClientCall.CALL_STATE_WAITING);
        if (c == null) {
            c = getCall(BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD,
                    BluetoothHeadsetClientCall.CALL_STATE_HELD);
            c = getCall(HfpClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD,
                    HfpClientCall.CALL_STATE_HELD);

            if (c == null) {
                return;
@@ -535,14 +534,14 @@ public class HeadsetClientStateMachine extends StateMachine {

        logD("Call to accept: " + c);
        switch (c.getState()) {
            case BluetoothHeadsetClientCall.CALL_STATE_INCOMING:
            case HfpClientCall.CALL_STATE_INCOMING:
                if (flag != BluetoothHeadsetClient.CALL_ACCEPT_NONE) {
                    return;
                }
                action = HeadsetClientHalConstants.CALL_ACTION_ATA;
                break;
            case BluetoothHeadsetClientCall.CALL_STATE_WAITING:
                if (callsInState(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) == 0) {
            case HfpClientCall.CALL_STATE_WAITING:
                if (callsInState(HfpClientCall.CALL_STATE_ACTIVE) == 0) {
                    // if no active calls present only plain accept is allowed
                    if (flag != BluetoothHeadsetClient.CALL_ACCEPT_NONE) {
                        return;
@@ -565,12 +564,12 @@ public class HeadsetClientStateMachine extends StateMachine {
                    return;
                }
                break;
            case BluetoothHeadsetClientCall.CALL_STATE_HELD:
            case HfpClientCall.CALL_STATE_HELD:
                if (flag == BluetoothHeadsetClient.CALL_ACCEPT_HOLD) {
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
                } else if (flag == BluetoothHeadsetClient.CALL_ACCEPT_TERMINATE) {
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_1;
                } else if (getCall(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) != null) {
                } else if (getCall(HfpClientCall.CALL_STATE_ACTIVE) != null) {
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_3;
                } else if (flag == BluetoothHeadsetClient.CALL_ACCEPT_NONE) {
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
@@ -578,12 +577,12 @@ public class HeadsetClientStateMachine extends StateMachine {
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
                }
                break;
            case BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD:
            case HfpClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD:
                action = HeadsetClientHalConstants.CALL_ACTION_BTRH_1;
                break;
            case BluetoothHeadsetClientCall.CALL_STATE_ALERTING:
            case BluetoothHeadsetClientCall.CALL_STATE_ACTIVE:
            case BluetoothHeadsetClientCall.CALL_STATE_DIALING:
            case HfpClientCall.CALL_STATE_ALERTING:
            case HfpClientCall.CALL_STATE_ACTIVE:
            case HfpClientCall.CALL_STATE_DIALING:
            default:
                return;
        }
@@ -605,29 +604,29 @@ public class HeadsetClientStateMachine extends StateMachine {

        logD("rejectCall");

        BluetoothHeadsetClientCall c = getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING,
                BluetoothHeadsetClientCall.CALL_STATE_WAITING,
                BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD,
                BluetoothHeadsetClientCall.CALL_STATE_HELD);
        HfpClientCall c = getCall(HfpClientCall.CALL_STATE_INCOMING,
                HfpClientCall.CALL_STATE_WAITING,
                HfpClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD,
                HfpClientCall.CALL_STATE_HELD);
        if (c == null) {
            logD("No call to reject, returning.");
            return;
        }

        switch (c.getState()) {
            case BluetoothHeadsetClientCall.CALL_STATE_INCOMING:
            case HfpClientCall.CALL_STATE_INCOMING:
                action = HeadsetClientHalConstants.CALL_ACTION_CHUP;
                break;
            case BluetoothHeadsetClientCall.CALL_STATE_WAITING:
            case BluetoothHeadsetClientCall.CALL_STATE_HELD:
            case HfpClientCall.CALL_STATE_WAITING:
            case HfpClientCall.CALL_STATE_HELD:
                action = HeadsetClientHalConstants.CALL_ACTION_CHLD_0;
                break;
            case BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD:
            case HfpClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD:
                action = HeadsetClientHalConstants.CALL_ACTION_BTRH_2;
                break;
            case BluetoothHeadsetClientCall.CALL_STATE_ACTIVE:
            case BluetoothHeadsetClientCall.CALL_STATE_DIALING:
            case BluetoothHeadsetClientCall.CALL_STATE_ALERTING:
            case HfpClientCall.CALL_STATE_ACTIVE:
            case HfpClientCall.CALL_STATE_DIALING:
            case HfpClientCall.CALL_STATE_ALERTING:
            default:
                return;
        }
@@ -645,11 +644,11 @@ public class HeadsetClientStateMachine extends StateMachine {

        logD("holdCall");

        BluetoothHeadsetClientCall c = getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING);
        HfpClientCall c = getCall(HfpClientCall.CALL_STATE_INCOMING);
        if (c != null) {
            action = HeadsetClientHalConstants.CALL_ACTION_BTRH_0;
        } else {
            c = getCall(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
            c = getCall(HfpClientCall.CALL_STATE_ACTIVE);
            if (c == null) {
                return;
            }
@@ -669,12 +668,12 @@ public class HeadsetClientStateMachine extends StateMachine {

        int action = HeadsetClientHalConstants.CALL_ACTION_CHUP;

        BluetoothHeadsetClientCall c = getCall(BluetoothHeadsetClientCall.CALL_STATE_DIALING,
                BluetoothHeadsetClientCall.CALL_STATE_ALERTING,
                BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
        HfpClientCall c = getCall(HfpClientCall.CALL_STATE_DIALING,
                HfpClientCall.CALL_STATE_ALERTING,
                HfpClientCall.CALL_STATE_ACTIVE);
        if (c == null) {
            // If the call being terminated is currently held, switch the action to CHLD_0
            c = getCall(BluetoothHeadsetClientCall.CALL_STATE_HELD);
            c = getCall(HfpClientCall.CALL_STATE_HELD);
            action = HeadsetClientHalConstants.CALL_ACTION_CHLD_0;
        }
        if (c != null) {
@@ -689,9 +688,9 @@ public class HeadsetClientStateMachine extends StateMachine {
    private void enterPrivateMode(int idx) {
        logD("enterPrivateMode: " + idx);

        BluetoothHeadsetClientCall c = mCalls.get(idx);
        HfpClientCall c = mCalls.get(idx);

        if (c == null || c.getState() != BluetoothHeadsetClientCall.CALL_STATE_ACTIVE
        if (c == null || c.getState() != HfpClientCall.CALL_STATE_ACTIVE
                || !c.isMultiParty()) {
            return;
        }
@@ -1331,7 +1330,7 @@ public class HeadsetClientStateMachine extends StateMachine {
                    break;
                case DIAL_NUMBER:
                    // Add the call as an outgoing call.
                    BluetoothHeadsetClientCall c = (BluetoothHeadsetClientCall) message.obj;
                    HfpClientCall c = (HfpClientCall) message.obj;
                    mCalls.put(HF_ORIGINATED_CALL_ID, c);

                    if (mNativeInterface.dial(mCurrentDevice, c.getNumber())) {
@@ -1340,9 +1339,9 @@ public class HeadsetClientStateMachine extends StateMachine {
                        sendMessage(QUERY_CURRENT_CALLS);
                    } else {
                        Log.e(TAG,
                                "ERROR: Cannot dial with a given number:" + c.toString(true));
                                "ERROR: Cannot dial with a given number:" + c.toString());
                        // Set the call to terminated remove.
                        c.setState(BluetoothHeadsetClientCall.CALL_STATE_TERMINATED);
                        c.setState(HfpClientCall.CALL_STATE_TERMINATED);
                        sendCallChangedIntent(c);
                        mCalls.remove(HF_ORIGINATED_CALL_ID);
                    }
@@ -2000,8 +1999,12 @@ public class HeadsetClientStateMachine extends StateMachine {
        return devices;
    }

    public List<BluetoothHeadsetClientCall> getCurrentCalls() {
        return new ArrayList<BluetoothHeadsetClientCall>(mCalls.values());
    private byte[] getByteAddress(BluetoothDevice device) {
        return Utils.getBytesFromAddress(device.getAddress());
    }

    public List<HfpClientCall> getCurrentCalls() {
        return new ArrayList<HfpClientCall>(mCalls.values());
    }

    public Bundle getCurrentAgEvents() {
+3 −4
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.bluetooth.hfpclient;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClientCall;
import android.os.Bundle;
import android.util.Log;

@@ -48,7 +47,7 @@ public class HeadsetClientServiceInterface {
        return true;
    }

    public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
    public HfpClientCall dial(BluetoothDevice device, String number) {
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return null;
        return service.dial(device, number);
@@ -66,7 +65,7 @@ public class HeadsetClientServiceInterface {
        return service.sendDTMF(device, code);
    }

    public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
    public boolean terminateCall(BluetoothDevice device, HfpClientCall call) {
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return false;
        return service.terminateCall(device, call != null ? call.getUUID() : null);
@@ -120,7 +119,7 @@ public class HeadsetClientServiceInterface {
        return service.getConnectedDevices();
    }

    public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
    public List<HfpClientCall> getCurrentCalls(BluetoothDevice device) {
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return null;
        return service.getCurrentCalls(device);
+303 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading