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

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

Remove HFP Client Connection Service's usage of BluetoothHeadsetClient

Currently, the HFP Client Connection Service uses the
BluetoothHeadsetClient profile proxy to get the HFP Client Service to do
things like accept calls, hang up, etc. This proxy exposes a surface we
don't need to expose outside of the Bluetooth stack, and causes calls to
leave the stack and come back.

The HFP Client Connection Service is now a singleton started by the HFP
Client Service itself. The HFP Client Service is also a singleton that
we can get an instance of to invoke functions directly against.

This change makes the connection service invoke things directly against
the HFP Client Service.

Tag: #refactor
Bug: 206035301
Test: atest BluetoothInstrumentationTests
Change-Id: Ic7d003108f1b8ca8d83b77a12b10190621a92769
parent a807315f
Loading
Loading
Loading
Loading
+26 −14
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;

/**
@@ -668,7 +669,7 @@ public class HeadsetClientService extends ProfileService {
                HeadsetClientService service = getService(source);
                Bundle defaultValue = null;
                if (service != null) {
                    defaultValue = service.getCurrentAgFeatures(device);
                    defaultValue = service.getCurrentAgFeaturesBundle(device);
                }
                receiver.send(defaultValue);
            } catch (RuntimeException e) {
@@ -677,8 +678,6 @@ public class HeadsetClientService extends ProfileService {
        }
    }

    ;

    // API methods
    public static synchronized HeadsetClientService getHeadsetClientService() {
        if (sHeadsetClientService == null) {
@@ -902,7 +901,7 @@ public class HeadsetClientService extends ProfileService {
        return false;
    }

    boolean connectAudio(BluetoothDevice device) {
    public boolean connectAudio(BluetoothDevice device) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
@@ -919,7 +918,7 @@ public class HeadsetClientService extends ProfileService {
        return true;
    }

    boolean disconnectAudio(BluetoothDevice device) {
    public boolean disconnectAudio(BluetoothDevice device) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
@@ -933,7 +932,7 @@ public class HeadsetClientService extends ProfileService {
        return true;
    }

    boolean holdCall(BluetoothDevice device) {
    public boolean holdCall(BluetoothDevice device) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
@@ -950,7 +949,7 @@ public class HeadsetClientService extends ProfileService {
        return true;
    }

    boolean acceptCall(BluetoothDevice device, int flag) {
    public boolean acceptCall(BluetoothDevice device, int flag) {
        /* Phonecalls from a single device are supported, hang up any calls on the other phone */
        synchronized (mStateMachineMap) {
            for (Map.Entry<BluetoothDevice, HeadsetClientStateMachine> entry : mStateMachineMap
@@ -987,7 +986,7 @@ public class HeadsetClientService extends ProfileService {
        return true;
    }

    boolean rejectCall(BluetoothDevice device) {
    public boolean rejectCall(BluetoothDevice device) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
@@ -1005,7 +1004,7 @@ public class HeadsetClientService extends ProfileService {
        return true;
    }

    boolean terminateCall(BluetoothDevice device, UUID uuid) {
    public boolean terminateCall(BluetoothDevice device, UUID uuid) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
@@ -1024,7 +1023,7 @@ public class HeadsetClientService extends ProfileService {
        return true;
    }

    boolean enterPrivateMode(BluetoothDevice device, int index) {
    public boolean enterPrivateMode(BluetoothDevice device, int index) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
@@ -1043,7 +1042,7 @@ public class HeadsetClientService extends ProfileService {
        return true;
    }

    BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
    public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
@@ -1058,7 +1057,7 @@ public class HeadsetClientService extends ProfileService {

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

    public Bundle getCurrentAgFeatures(BluetoothDevice device) {
    public Bundle getCurrentAgFeaturesBundle(BluetoothDevice device) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
            return null;
        }
        int connectionState = sm.getConnectionState(device);
        if (connectionState != BluetoothProfile.STATE_CONNECTED) {
            return null;
        }
        return sm.getCurrentAgFeaturesBundle();
    }

    public Set<Integer> getCurrentAgFeatures(BluetoothDevice device) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
@@ -1269,7 +1281,7 @@ public class HeadsetClientService extends ProfileService {
                    .entrySet()) {
                if (entry.getValue() != null) {
                    int audioState = entry.getValue().getAudioState(entry.getKey());
                    if (audioState == BluetoothHeadsetClient.STATE_AUDIO_CONNECTED) {
                    if (audioState == HeadsetClientHalConstants.AUDIO_STATE_CONNECTED) {
                        if (DBG) {
                            Log.d(TAG, "Device " + entry.getKey() + " audio state " + audioState
                                    + " Connected");
+41 −1
Original line number Diff line number Diff line
@@ -720,7 +720,7 @@ public class HeadsetClientStateMachine extends StateMachine {
        }
    }

    public Bundle getCurrentAgFeatures() {
    public Bundle getCurrentAgFeaturesBundle() {
        Bundle b = new Bundle();
        if ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_3WAY)
                == HeadsetClientHalConstants.PEER_FEAT_3WAY) {
@@ -765,6 +765,46 @@ public class HeadsetClientStateMachine extends StateMachine {
        return b;
    }

    public Set<Integer> getCurrentAgFeatures() {
        HashSet<Integer> features = new HashSet<>();

        if (isSupported(mPeerFeatures, HeadsetClientHalConstants.PEER_FEAT_3WAY)) {
            features.add(HeadsetClientHalConstants.PEER_FEAT_3WAY);
        }
        if (isSupported(mPeerFeatures, HeadsetClientHalConstants.PEER_FEAT_VREC)) {
            features.add(HeadsetClientHalConstants.PEER_FEAT_VREC);
        }
        if (isSupported(mPeerFeatures, HeadsetClientHalConstants.PEER_FEAT_REJECT)) {
            features.add(HeadsetClientHalConstants.PEER_FEAT_REJECT);
        }
        if (isSupported(mPeerFeatures, HeadsetClientHalConstants.PEER_FEAT_ECC)) {
            features.add(HeadsetClientHalConstants.PEER_FEAT_ECC);
        }

        // add individual CHLD support extras
        if (isSupported(mChldFeatures, HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC)) {
            features.add(HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC);
        }
        if (isSupported(mChldFeatures, HeadsetClientHalConstants.CHLD_FEAT_REL)) {
            features.add(HeadsetClientHalConstants.CHLD_FEAT_REL);
        }
        if (isSupported(mChldFeatures, HeadsetClientHalConstants.CHLD_FEAT_REL_ACC)) {
            features.add(HeadsetClientHalConstants.CHLD_FEAT_REL_ACC);
        }
        if (isSupported(mChldFeatures, HeadsetClientHalConstants.CHLD_FEAT_MERGE)) {
            features.add(HeadsetClientHalConstants.CHLD_FEAT_MERGE);
        }
        if (isSupported(mChldFeatures, HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH)) {
            features.add(HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH);
        }

        return features;
    }

    private boolean isSupported(int bitfield, int mask) {
        return (bitfield & mask) == mask;
    }

    HeadsetClientStateMachine(HeadsetClientService context, Looper looper,
                              NativeInterface nativeInterface) {
        super(TAG, looper);
+133 −0
Original line number Diff line number Diff line
@@ -17,112 +17,117 @@
package com.android.bluetooth.hfpclient;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothHeadsetClientCall;
import android.os.Bundle;

import com.android.internal.annotations.VisibleForTesting;
import android.util.Log;

import java.util.List;
import java.util.Set;

/**
 * A mockable proxy class that facilitates testing of the {@code hfpclient.connserv} package.
 * Interface for talking to the HeadsetClientService
 *
 * <p>This is necessary due to the "final" attribute of the BluetoothHeadsetClient class.
 * Deals with service lifecycle and returns consistent error values
 */
public class BluetoothHeadsetClientProxy {
public class HeadsetClientServiceInterface {
    private static final String TAG = "HeadsetClientServiceInterface";

    private final BluetoothHeadsetClient mBluetoothHeadsetClient;
    /* Action policy for other calls when accepting call */
    public static final int CALL_ACCEPT_NONE = 0;
    public static final int CALL_ACCEPT_HOLD = 1;
    public static final int CALL_ACCEPT_TERMINATE = 2;

    private BluetoothHeadsetClientProxy(BluetoothHeadsetClient bluetoothHeadsetClient) {
        mBluetoothHeadsetClient = bluetoothHeadsetClient;
    public HeadsetClientServiceInterface() {
    }

    public BluetoothHeadsetClient getProxiedBluetoothHeadsetClient() {
        return mBluetoothHeadsetClient;
    private boolean isServiceAvailable(HeadsetClientService service) {
        if (service == null) {
            Log.w(TAG, "HeadsetClientService is not available");
            return false;
        }
        return true;
    }

    /** @see BluetoothHeadsetClient#dial(BluetoothDevice, String) */
    public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
        return mBluetoothHeadsetClient.dial(device, number);
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return null;
        return service.dial(device, number);
    }

    /** @see BluetoothHeadsetClient#enterPrivateMode(BluetoothDevice, int) */
    public boolean enterPrivateMode(BluetoothDevice device, int index) {
        return mBluetoothHeadsetClient.enterPrivateMode(device, index);
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return false;
        return service.enterPrivateMode(device, index);
    }

    /** @see BluetoothHeadsetClient#sendDTMF(BluetoothDevice, byte) */
    public boolean sendDTMF(BluetoothDevice device, byte code) {
        return mBluetoothHeadsetClient.sendDTMF(device, code);
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return false;
        return service.sendDTMF(device, code);
    }

    /** @see BluetoothHeadsetClient#terminateCall(BluetoothDevice, BluetoothHeadsetClientCall) */
    public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
        return mBluetoothHeadsetClient.terminateCall(device, call);
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return false;
        return service.terminateCall(device, call != null ? call.getUUID() : null);
    }

    /** @see BluetoothHeadsetClient#holdCall(BluetoothDevice) */
    public boolean holdCall(BluetoothDevice device) {
        return mBluetoothHeadsetClient.holdCall(device);
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return false;
        return service.holdCall(device);
    }

    /** @see BluetoothHeadsetClient#acceptCall(BluetoothDevice, int) */
    public boolean acceptCall(BluetoothDevice device, int flag) {
        return mBluetoothHeadsetClient.acceptCall(device, flag);
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return false;
        return service.acceptCall(device, flag);
    }

    /** @see BluetoothHeadsetClient#rejectCall(BluetoothDevice) */
    public boolean rejectCall(BluetoothDevice device) {
        return mBluetoothHeadsetClient.rejectCall(device);
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return false;
        return service.rejectCall(device);
    }

    /** @see BluetoothHeadsetClient#connectAudio(BluetoothDevice) */
    public boolean connectAudio(BluetoothDevice device) {
        return mBluetoothHeadsetClient.connectAudio(device);
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return false;
        return service.connectAudio(device);
    }

    /** @see BluetoothHeadsetClient#disconnectAudio(BluetoothDevice) */
    public boolean disconnectAudio(BluetoothDevice device) {
        return mBluetoothHeadsetClient.disconnectAudio(device);
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return false;
        return service.disconnectAudio(device);
    }

    public Set<Integer> getCurrentAgFeatures(BluetoothDevice device) {
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return null;
        return service.getCurrentAgFeatures(device);
    }

    /** @see BluetoothHeadsetClient#getCurrentAgEvents(BluetoothDevice) */
    public Bundle getCurrentAgEvents(BluetoothDevice device) {
        return mBluetoothHeadsetClient.getCurrentAgEvents(device);
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return null;
        return service.getCurrentAgEvents(device);
    }

    /** @see BluetoothHeadsetClient#getConnectedDevices() */
    public List<BluetoothDevice> getConnectedDevices() {
        return mBluetoothHeadsetClient.getConnectedDevices();
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return null;
        return service.getConnectedDevices();
    }

    /** @see BluetoothHeadsetClient#getCurrentCalls(BluetoothDevice) */
    public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
        return mBluetoothHeadsetClient.getCurrentCalls(device);
    }

    /**
     * Factory class for {@link BluetoothHeadsetClientProxy}
     */
    public static class Factory {
        private static Factory sInstance = new Factory();

        @VisibleForTesting
        static void setInstance(Factory instance) {
            sInstance = instance;
        }

        /**
         * Returns an instance of {@link BluetoothHeadsetClientProxy}
         */
        public static BluetoothHeadsetClientProxy build(BluetoothHeadsetClient proxy) {
            return sInstance.buildInternal(proxy);
        }

        protected BluetoothHeadsetClientProxy buildInternal(BluetoothHeadsetClient proxy) {
            return  new BluetoothHeadsetClientProxy(proxy);
        HeadsetClientService service = HeadsetClientService.getHeadsetClientService();
        if (!isServiceAvailable(service)) return null;
        return service.getCurrentCalls(device);
    }

    public boolean hasHfpClientEcc(BluetoothDevice device) {
        Set<Integer> features = getCurrentAgFeatures(device);
        return features != null && features.contains(HeadsetClientHalConstants.PEER_FEAT_ECC);
    }
}
+11 −14
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
package com.android.bluetooth.hfpclient;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClient;
import android.telecom.Conference;
import android.telecom.Connection;
import android.telecom.PhoneAccountHandle;
@@ -25,15 +24,15 @@ import android.util.Log;
public class HfpClientConference extends Conference {
    private static final String TAG = "HfpClientConference";

    private BluetoothDevice mDevice;
    private BluetoothHeadsetClientProxy mHeadsetProfile;
    private final BluetoothDevice mDevice;
    private final HeadsetClientServiceInterface mServiceInterface;

    public HfpClientConference(PhoneAccountHandle handle, BluetoothDevice device,
            BluetoothHeadsetClientProxy client) {
    public HfpClientConference(BluetoothDevice device, PhoneAccountHandle handle,
            HeadsetClientServiceInterface serviceInterface) {
        super(handle);
        mDevice = device;
        mHeadsetProfile = client;
        boolean manage = HfpClientConnectionService.hasHfpClientEcc(client, device);
        mServiceInterface = serviceInterface;
        boolean manage = mServiceInterface.hasHfpClientEcc(device);
        setConnectionCapabilities(
                Connection.CAPABILITY_SUPPORT_HOLD | Connection.CAPABILITY_HOLD | (manage
                        ? Connection.CAPABILITY_MANAGE_CONFERENCE : 0));
@@ -43,7 +42,7 @@ public class HfpClientConference extends Conference {
    @Override
    public void onDisconnect() {
        Log.d(TAG, "onDisconnect");
        mHeadsetProfile.terminateCall(mDevice, null);
        mServiceInterface.terminateCall(mDevice, null);
    }

    @Override
@@ -62,21 +61,19 @@ public class HfpClientConference extends Conference {
    @Override
    public void onHold() {
        Log.d(TAG, "onHold");
        mHeadsetProfile.holdCall(mDevice);
        mServiceInterface.holdCall(mDevice);
    }

    @Override
    public void onUnhold() {
        Log.d(TAG, "onUnhold");
        mHeadsetProfile.acceptCall(mDevice, BluetoothHeadsetClient.CALL_ACCEPT_HOLD);
        mServiceInterface.acceptCall(mDevice, HeadsetClientServiceInterface.CALL_ACCEPT_HOLD);
    }

    @Override
    public void onPlayDtmfTone(char c) {
        Log.d(TAG, "onPlayDtmfTone " + c);
        if (mHeadsetProfile != null) {
            mHeadsetProfile.sendDTMF(mDevice, (byte) c);
        }
        mServiceInterface.sendDTMF(mDevice, (byte) c);
    }

    @Override
@@ -87,7 +84,7 @@ public class HfpClientConference extends Conference {
            connection.onAnswer();
        } else if (connection.getState() == Connection.STATE_ACTIVE
                && getState() == Connection.STATE_HOLDING) {
            mHeadsetProfile.acceptCall(mDevice, BluetoothHeadsetClient.CALL_ACCEPT_NONE);
            mServiceInterface.acceptCall(mDevice, HeadsetClientServiceInterface.CALL_ACCEPT_NONE);
        }
    }
}
+29 −48
Original line number Diff line number Diff line
@@ -16,9 +16,7 @@
package com.android.bluetooth.hfpclient;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothHeadsetClientCall;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.telecom.Connection;
@@ -27,6 +25,7 @@ import android.telecom.PhoneAccount;
import android.telecom.TelecomManager;
import android.util.Log;

import java.util.Objects;
import java.util.UUID;

public class HfpClientConnection extends Connection {
@@ -37,12 +36,11 @@ public class HfpClientConnection extends Connection {
    private static final String EVENT_SCO_DISCONNECT =
             "com.android.bluetooth.hfpclient.SCO_DISCONNECT";

    private final Context mContext;
    private final BluetoothDevice mDevice;
    private BluetoothHeadsetClientProxy mHeadsetProfile;
    private HfpClientConnectionService mHfpClientConnectionService;

    private BluetoothHeadsetClientCall mCurrentCall;
    private final HfpClientConnectionService mConnServ;
    private final HeadsetClientServiceInterface mServiceInterface;

    private int mPreviousCallState = -1;
    private boolean mClosed;
    private boolean mClosing = false;
@@ -52,34 +50,25 @@ public class HfpClientConnection extends Connection {

    // Constructor to be used when there's an existing call (such as that created on the AG or
    // when connection happens and we see calls for the first time).
    public HfpClientConnection(Context context, BluetoothDevice device,
            BluetoothHeadsetClientProxy client, BluetoothHeadsetClientCall call) {
    public HfpClientConnection(BluetoothDevice device, BluetoothHeadsetClientCall call,
            HfpClientConnectionService connServ, HeadsetClientServiceInterface serviceInterface) {
        mDevice = device;
        mContext = context;
        mHeadsetProfile = client;

        if (call == null) {
            throw new IllegalStateException("Call is null");
        }
        mConnServ = connServ;
        mServiceInterface = serviceInterface;
        mCurrentCall = Objects.requireNonNull(call);

        mCurrentCall = call;
        handleCallChanged();
        finishInitializing();
    }

    // Constructor to be used when a call is intiated on the HF. The call handle is obtained by
    // using the dial() command.
    public HfpClientConnection(Context context, BluetoothDevice device,
            BluetoothHeadsetClientProxy client, Uri number) {
    public HfpClientConnection(BluetoothDevice device, Uri number,
            HfpClientConnectionService connServ, HeadsetClientServiceInterface serviceInterface) {
        mDevice = device;
        mContext = context;
        mHeadsetProfile = client;

        if (mHeadsetProfile == null) {
            throw new IllegalStateException("HeadsetProfile is null, returning");
        }

        mCurrentCall = mHeadsetProfile.dial(mDevice, number.getSchemeSpecificPart());
        mConnServ = connServ;
        mServiceInterface = serviceInterface;
        mCurrentCall = mServiceInterface.dial(mDevice, number.getSchemeSpecificPart());
        if (mCurrentCall == null) {
            close(DisconnectCause.ERROR);
            Log.e(TAG, "Failed to create the call, dial failed.");
@@ -92,7 +81,7 @@ public class HfpClientConnection extends Connection {
    }

    void finishInitializing() {
        mClientHasEcc = HfpClientConnectionService.hasHfpClientEcc(mHeadsetProfile, mDevice);
        mClientHasEcc = mServiceInterface.hasHfpClientEcc(mDevice);
        setAudioModeIsVoip(false);
        Uri number = Uri.fromParts(PhoneAccount.SCHEME_TEL, mCurrentCall.getNumber(), null);
        setAddress(number, TelecomManager.PRESENTATION_ALLOWED);
@@ -108,7 +97,6 @@ public class HfpClientConnection extends Connection {
    }

    public void onHfpDisconnected() {
        mHeadsetProfile = null;
        close(DisconnectCause.ERROR);
    }

@@ -126,7 +114,7 @@ public class HfpClientConnection extends Connection {
    }

    public void enterPrivateMode() {
        mHeadsetProfile.enterPrivateMode(mDevice, mCurrentCall.getId());
        mServiceInterface.enterPrivateMode(mDevice, mCurrentCall.getId());
        setActive();
    }

@@ -203,7 +191,7 @@ public class HfpClientConnection extends Connection {
        return mClosing;
    }

    public synchronized BluetoothDevice getDevice() {
    public BluetoothDevice getDevice() {
        return mDevice;
    }

@@ -213,7 +201,7 @@ public class HfpClientConnection extends Connection {
            Log.d(TAG, "onPlayDtmfTone " + c + " " + mCurrentCall);
        }
        if (!mClosed) {
            mHeadsetProfile.sendDTMF(mDevice, (byte) c);
            mServiceInterface.sendDTMF(mDevice, (byte) c);
        }
    }

@@ -224,7 +212,7 @@ public class HfpClientConnection extends Connection {
        }
        // The call is not closed so we should send a terminate here.
        if (!mClosed) {
            mHeadsetProfile.terminateCall(mDevice, mCurrentCall);
            mServiceInterface.terminateCall(mDevice, mCurrentCall);
            mLocalDisconnect = true;
            mClosing = true;
        }
@@ -244,13 +232,13 @@ public class HfpClientConnection extends Connection {
            Log.d(TAG, "onHold " + mCurrentCall);
        }
        if (!mClosed) {
            mHeadsetProfile.holdCall(mDevice);
            mServiceInterface.holdCall(mDevice);
        }
    }

    @Override
    public synchronized void onUnhold() {
        if (getHfpClientConnectionService().getAllConnections().size() > 1) {
        if (mConnServ.getAllConnections().size() > 1) {
            Log.w(TAG, "Ignoring unhold; call hold on the foreground call");
            return;
        }
@@ -258,7 +246,7 @@ public class HfpClientConnection extends Connection {
            Log.d(TAG, "onUnhold " + mCurrentCall);
        }
        if (!mClosed) {
            mHeadsetProfile.acceptCall(mDevice, BluetoothHeadsetClient.CALL_ACCEPT_HOLD);
            mServiceInterface.acceptCall(mDevice, HeadsetClientServiceInterface.CALL_ACCEPT_HOLD);
        }
    }

@@ -268,7 +256,7 @@ public class HfpClientConnection extends Connection {
            Log.d(TAG, "onAnswer " + mCurrentCall);
        }
        if (!mClosed) {
            mHeadsetProfile.acceptCall(mDevice, BluetoothHeadsetClient.CALL_ACCEPT_NONE);
            mServiceInterface.acceptCall(mDevice, HeadsetClientServiceInterface.CALL_ACCEPT_NONE);
        }
    }

@@ -278,7 +266,7 @@ public class HfpClientConnection extends Connection {
            Log.d(TAG, "onReject " + mCurrentCall);
        }
        if (!mClosed) {
            mHeadsetProfile.rejectCall(mDevice);
            mServiceInterface.rejectCall(mDevice);
        }
    }

@@ -287,12 +275,15 @@ public class HfpClientConnection extends Connection {
        if (DBG) {
            Log.d(TAG, "onCallEvent(" + event + ", " + extras + ")");
        }
        if (mClosed) {
            return;
        }
        switch (event) {
            case EVENT_SCO_CONNECT:
                mHeadsetProfile.connectAudio(mDevice);
                mServiceInterface.connectAudio(mDevice);
                break;
            case EVENT_SCO_DISCONNECT:
                mHeadsetProfile.disconnectAudio(mDevice);
                mServiceInterface.disconnectAudio(mDevice);
                break;
        }
    }
@@ -311,14 +302,4 @@ public class HfpClientConnection extends Connection {
        return "HfpClientConnection{" + getAddress() + "," + stateToString(getState()) + ","
                + mCurrentCall + "}";
    }

    public void setHfpClientConnectionService(
            HfpClientConnectionService hfpClientConnectionService) {
        mHfpClientConnectionService = hfpClientConnectionService;
    }

    public HfpClientConnectionService getHfpClientConnectionService() {
        return mHfpClientConnectionService;
    }

}
Loading