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

Commit 13e18be2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "HFP: Only remove state machine when device is unbonded and disconnected"

parents d8c2f199 caa5d6ab
Loading
Loading
Loading
Loading
+23 −2
Original line number Original line Diff line number Diff line
@@ -1800,6 +1800,11 @@ public class AdapterService extends Service {
        return mAdapterProperties.discoveryEndMillis();
        return mAdapterProperties.discoveryEndMillis();
    }
    }


    /**
     * Same as API method {@link BluetoothAdapter#getBondedDevices()}
     *
     * @return array of bonded {@link BluetoothDevice} or null on error
     */
    public BluetoothDevice[] getBondedDevices() {
    public BluetoothDevice[] getBondedDevices() {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return mAdapterProperties.getBondedDevices();
        return mAdapterProperties.getBondedDevices();
@@ -1895,7 +1900,17 @@ public class AdapterService extends Service {
        return true;
        return true;
    }
    }


    int getBondState(BluetoothDevice device) {
    /**
     * Get the bond state of a particular {@link BluetoothDevice}
     *
     * @param device remote device of interest
     * @return bond state <p>Possible values are
     * {@link BluetoothDevice#BOND_NONE},
     * {@link BluetoothDevice#BOND_BONDING},
     * {@link BluetoothDevice#BOND_BONDED}.
     */
    @VisibleForTesting
    public int getBondState(BluetoothDevice device) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
        if (deviceProp == null) {
        if (deviceProp == null) {
@@ -1923,7 +1938,13 @@ public class AdapterService extends Service {
        return getConnectionStateNative(addr);
        return getConnectionStateNative(addr);
    }
    }


    String getRemoteName(BluetoothDevice device) {
    /**
     * Same as API method {@link BluetoothDevice#getName()}
     *
     * @param device remote device of interest
     * @return remote device name
     */
    public String getRemoteName(BluetoothDevice device) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (mRemoteDevices == null) {
        if (mRemoteDevices == null) {
            return null;
            return null;
+7 −4
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.os.Looper;
import android.util.Log;
import android.util.Log;


import com.android.bluetooth.Utils;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;


/**
/**
 * Factory class for object initialization to help with unit testing
 * Factory class for object initialization to help with unit testing
@@ -63,15 +64,17 @@ public class HeadsetObjectsFactory {
     *
     *
     * @param device the remote device associated with this state machine
     * @param device the remote device associated with this state machine
     * @param looper the thread that the state machine is supposed to run on
     * @param looper the thread that the state machine is supposed to run on
     * @param service the headset service
     * @param headsetService the headset service
     * @param adapterService the adapter service
     * @param nativeInterface native interface
     * @param nativeInterface native interface
     * @param systemInterface system interface
     * @param systemInterface system interface
     * @return a state machine that is initialized and started, ready to go
     * @return a state machine that is initialized and started, ready to go
     */
     */
    public HeadsetStateMachine makeStateMachine(BluetoothDevice device, Looper looper,
    public HeadsetStateMachine makeStateMachine(BluetoothDevice device, Looper looper,
            HeadsetService service, HeadsetNativeInterface nativeInterface,
            HeadsetService headsetService, AdapterService adapterService,
            HeadsetSystemInterface systemInterface) {
            HeadsetNativeInterface nativeInterface, HeadsetSystemInterface systemInterface) {
        return HeadsetStateMachine.make(device, looper, service, nativeInterface, systemInterface);
        return HeadsetStateMachine.make(device, looper, headsetService, adapterService,
                nativeInterface, systemInterface);
    }
    }


    /**
    /**
+48 −16
Original line number Original line Diff line number Diff line
@@ -234,10 +234,8 @@ public class HeadsetService extends ProfileService {
     * @param stackEvent event from native stack
     * @param stackEvent event from native stack
     */
     */
    void messageFromNative(HeadsetStackEvent stackEvent) {
    void messageFromNative(HeadsetStackEvent stackEvent) {
        if (stackEvent.device == null) {
        Objects.requireNonNull(stackEvent.device,
            Log.wtfStack(TAG, "messageFromNative, device is null, event: " + stackEvent);
                "Device should never be null, event: " + stackEvent);
            return;
        }
        synchronized (mStateMachines) {
        synchronized (mStateMachines) {
            HeadsetStateMachine stateMachine = mStateMachines.get(stackEvent.device);
            HeadsetStateMachine stateMachine = mStateMachines.get(stackEvent.device);
            if (stackEvent.type == HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) {
            if (stackEvent.type == HeadsetStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) {
@@ -248,16 +246,17 @@ public class HeadsetService extends ProfileService {
                        if (stateMachine == null) {
                        if (stateMachine == null) {
                            stateMachine = HeadsetObjectsFactory.getInstance()
                            stateMachine = HeadsetObjectsFactory.getInstance()
                                    .makeStateMachine(stackEvent.device,
                                    .makeStateMachine(stackEvent.device,
                                            mStateMachinesThread.getLooper(), this,
                                            mStateMachinesThread.getLooper(), this, mAdapterService,
                                            mNativeInterface, mSystemInterface);
                                            mNativeInterface, mSystemInterface);
                            mStateMachines.put(stackEvent.device, stateMachine);
                            mStateMachines.put(stackEvent.device, stateMachine);
                        }
                        }
                        break;
                        break;
                    }
                    }
                }
                }
            } else if (stateMachine == null) {
            }
                Log.wtfStack(TAG, "State machine not found for stack event: " + stackEvent);
            if (stateMachine == null) {
                return;
                throw new IllegalStateException(
                        "State machine not found for stack event: " + stackEvent);
            }
            }
            stateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, stackEvent);
            stateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT, stackEvent);
        }
        }
@@ -315,8 +314,9 @@ public class HeadsetService extends ProfileService {
                case BluetoothDevice.ACTION_BOND_STATE_CHANGED: {
                case BluetoothDevice.ACTION_BOND_STATE_CHANGED: {
                    int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                    int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                            BluetoothDevice.ERROR);
                            BluetoothDevice.ERROR);
                    BluetoothDevice device =
                    BluetoothDevice device = Objects.requireNonNull(
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE),
                            "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE");
                    logD("Bond state changed for device: " + device + " state: " + state);
                    logD("Bond state changed for device: " + device + " state: " + state);
                    if (state != BluetoothDevice.BOND_NONE) {
                    if (state != BluetoothDevice.BOND_NONE) {
                        break;
                        break;
@@ -326,9 +326,11 @@ public class HeadsetService extends ProfileService {
                        if (stateMachine == null) {
                        if (stateMachine == null) {
                            break;
                            break;
                        }
                        }
                        logD("Removing state machine for device: " + device);
                        if (stateMachine.getConnectionState()
                        HeadsetObjectsFactory.getInstance().destroyStateMachine(stateMachine);
                                != BluetoothProfile.STATE_DISCONNECTED) {
                        mStateMachines.remove(device);
                            break;
                        }
                        removeStateMachine(device);
                    }
                    }
                    break;
                    break;
                }
                }
@@ -626,13 +628,18 @@ public class HeadsetService extends ProfileService {
            Log.w(TAG, "connect: PRIORITY_OFF, device=" + device);
            Log.w(TAG, "connect: PRIORITY_OFF, device=" + device);
            return false;
            return false;
        }
        }
        ParcelUuid[] featureUuids = mAdapterService.getRemoteUuids(device);
        if (!BluetoothUuid.containsAnyUuid(featureUuids, HEADSET_UUIDS)) {
            Log.e(TAG, "connect: Cannot connect to " + device + ": no headset UUID");
            return false;
        }
        synchronized (mStateMachines) {
        synchronized (mStateMachines) {
            Log.i(TAG, "connect: device=" + device);
            Log.i(TAG, "connect: device=" + device);
            HeadsetStateMachine stateMachine = mStateMachines.get(device);
            HeadsetStateMachine stateMachine = mStateMachines.get(device);
            if (stateMachine == null) {
            if (stateMachine == null) {
                stateMachine = HeadsetObjectsFactory.getInstance()
                stateMachine = HeadsetObjectsFactory.getInstance()
                        .makeStateMachine(device, mStateMachinesThread.getLooper(), this,
                        .makeStateMachine(device, mStateMachinesThread.getLooper(), this,
                                mNativeInterface, mSystemInterface);
                                mAdapterService, mNativeInterface, mSystemInterface);
                mStateMachines.put(device, stateMachine);
                mStateMachines.put(device, stateMachine);
            }
            }
            int connectionState = stateMachine.getConnectionState();
            int connectionState = stateMachine.getConnectionState();
@@ -699,7 +706,14 @@ public class HeadsetService extends ProfileService {
        return devices;
        return devices;
    }
    }


    private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
    /**
     * Same as the API method {@link BluetoothHeadset#getDevicesMatchingConnectionStates(int[])}
     *
     * @param states an array of states from {@link BluetoothProfile}
     * @return a list of devices matching the array of connection states
     */
    @VisibleForTesting
    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        ArrayList<BluetoothDevice> devices = new ArrayList<>();
        ArrayList<BluetoothDevice> devices = new ArrayList<>();
        if (states == null) {
        if (states == null) {
@@ -1217,7 +1231,7 @@ public class HeadsetService extends ProfileService {
        // Check priority and accept or reject the connection.
        // Check priority and accept or reject the connection.
        // Note: Logic can be simplified, but keeping it this way for readability
        // Note: Logic can be simplified, but keeping it this way for readability
        int priority = getPriority(device);
        int priority = getPriority(device);
        int bondState = device.getBondState();
        int bondState = mAdapterService.getBondState(device);
        // If priority is undefined, it is likely that our SDP has not completed and peer is
        // If priority is undefined, it is likely that our SDP has not completed and peer is
        // initiating the connection. Allow this connection only if the device is bonded or bonding
        // initiating the connection. Allow this connection only if the device is bonded or bonding
        if ((priority == BluetoothProfile.PRIORITY_UNDEFINED) && (bondState
        if ((priority == BluetoothProfile.PRIORITY_UNDEFINED) && (bondState
@@ -1240,6 +1254,24 @@ public class HeadsetService extends ProfileService {
        return true;
        return true;
    }
    }


    /**
     * Remove state machine in {@link #mStateMachines} for a {@link BluetoothDevice}
     *
     * @param device device whose state machine is to be removed.
     */
    void removeStateMachine(BluetoothDevice device) {
        synchronized (mStateMachines) {
            HeadsetStateMachine stateMachine = mStateMachines.get(device);
            if (stateMachine == null) {
                Log.w(TAG, "removeStateMachine(), " + device + " does not have a state machine");
                return;
            }
            Log.i(TAG, "removeStateMachine(), removing state machine for device: " + device);
            HeadsetObjectsFactory.getInstance().destroyStateMachine(stateMachine);
            mStateMachines.remove(device);
        }
    }

    @Override
    @Override
    public void dump(StringBuilder sb) {
    public void dump(StringBuilder sb) {
        synchronized (mStateMachines) {
        synchronized (mStateMachines) {
+45 −32
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@ import android.support.annotation.VisibleForTesting;
import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneNumberUtils;
import android.util.Log;
import android.util.Log;


import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.internal.util.State;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.internal.util.StateMachine;
@@ -129,7 +130,8 @@ public class HeadsetStateMachine extends StateMachine {
    private HeadsetStateBase mPrevState;
    private HeadsetStateBase mPrevState;


    // Run time dependencies
    // Run time dependencies
    private final HeadsetService mService;
    private final HeadsetService mHeadsetService;
    private final AdapterService mAdapterService;
    private final HeadsetNativeInterface mNativeInterface;
    private final HeadsetNativeInterface mNativeInterface;
    private final HeadsetSystemInterface mSystemInterface;
    private final HeadsetSystemInterface mSystemInterface;


@@ -170,19 +172,21 @@ public class HeadsetStateMachine extends StateMachine {
        VOICE_COMMAND_INTENT.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        VOICE_COMMAND_INTENT.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    }
    }


    private HeadsetStateMachine(BluetoothDevice device, Looper looper, HeadsetService service,
    private HeadsetStateMachine(BluetoothDevice device, Looper looper,
            HeadsetService headsetService, AdapterService adapterService,
            HeadsetNativeInterface nativeInterface, HeadsetSystemInterface systemInterface) {
            HeadsetNativeInterface nativeInterface, HeadsetSystemInterface systemInterface) {
        super(TAG, Objects.requireNonNull(looper, "looper cannot be null"));
        super(TAG, Objects.requireNonNull(looper, "looper cannot be null"));
        // Enable/Disable StateMachine debug logs
        // Enable/Disable StateMachine debug logs
        setDbg(DBG);
        setDbg(DBG);
        mDevice = Objects.requireNonNull(device, "device cannot be null");
        mDevice = Objects.requireNonNull(device, "device cannot be null");
        mService = Objects.requireNonNull(service, "service cannot be null");
        mHeadsetService = Objects.requireNonNull(headsetService, "headsetService cannot be null");
        mNativeInterface =
        mNativeInterface =
                Objects.requireNonNull(nativeInterface, "nativeInterface cannot be null");
                Objects.requireNonNull(nativeInterface, "nativeInterface cannot be null");
        mSystemInterface =
        mSystemInterface =
                Objects.requireNonNull(systemInterface, "systemInterface cannot be null");
                Objects.requireNonNull(systemInterface, "systemInterface cannot be null");
        mAdapterService = Objects.requireNonNull(adapterService, "AdapterService cannot be null");
        // Create phonebook helper
        // Create phonebook helper
        mPhonebook = new AtPhonebook(mService, mNativeInterface);
        mPhonebook = new AtPhonebook(mHeadsetService, mNativeInterface);
        // Initialize state machine
        // Initialize state machine
        addState(mDisconnected);
        addState(mDisconnected);
        addState(mConnecting);
        addState(mConnecting);
@@ -194,12 +198,14 @@ public class HeadsetStateMachine extends StateMachine {
        setInitialState(mDisconnected);
        setInitialState(mDisconnected);
    }
    }


    static HeadsetStateMachine make(BluetoothDevice device, Looper looper, HeadsetService service,
    static HeadsetStateMachine make(BluetoothDevice device, Looper looper,
            HeadsetService headsetService, AdapterService adapterService,
            HeadsetNativeInterface nativeInterface, HeadsetSystemInterface systemInterface) {
            HeadsetNativeInterface nativeInterface, HeadsetSystemInterface systemInterface) {
        Log.i(TAG, "make");
        HeadsetStateMachine stateMachine =
        HeadsetStateMachine stateMachine =
                new HeadsetStateMachine(device, looper, service, nativeInterface, systemInterface);
                new HeadsetStateMachine(device, looper, headsetService, adapterService,
                        nativeInterface, systemInterface);
        stateMachine.start();
        stateMachine.start();
        Log.i(TAG, "Created state machine " + stateMachine + " for " + device);
        return stateMachine;
        return stateMachine;
    }
    }


@@ -302,13 +308,14 @@ public class HeadsetStateMachine extends StateMachine {
                // Headset is disconnecting, stop Virtual call if active.
                // Headset is disconnecting, stop Virtual call if active.
                terminateScoUsingVirtualVoiceCall();
                terminateScoUsingVirtualVoiceCall();
            }
            }
            mService.onConnectionStateChangedFromStateMachine(device, fromState, toState);
            mHeadsetService.onConnectionStateChangedFromStateMachine(device, fromState, toState);
            Intent intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
            Intent intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
            intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, fromState);
            intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, fromState);
            intent.putExtra(BluetoothProfile.EXTRA_STATE, toState);
            intent.putExtra(BluetoothProfile.EXTRA_STATE, toState);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            mService.sendBroadcastAsUser(intent, UserHandle.ALL, HeadsetService.BLUETOOTH_PERM);
            mHeadsetService.sendBroadcastAsUser(intent, UserHandle.ALL,
                    HeadsetService.BLUETOOTH_PERM);
        }
        }


        // Should not be called from enter() method
        // Should not be called from enter() method
@@ -319,12 +326,13 @@ public class HeadsetStateMachine extends StateMachine {
                // needs to be cleaned up.So call terminateScoUsingVirtualVoiceCall.
                // needs to be cleaned up.So call terminateScoUsingVirtualVoiceCall.
                terminateScoUsingVirtualVoiceCall();
                terminateScoUsingVirtualVoiceCall();
            }
            }
            mService.onAudioStateChangedFromStateMachine(device, fromState, toState);
            mHeadsetService.onAudioStateChangedFromStateMachine(device, fromState, toState);
            Intent intent = new Intent(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
            Intent intent = new Intent(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
            intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, fromState);
            intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, fromState);
            intent.putExtra(BluetoothProfile.EXTRA_STATE, toState);
            intent.putExtra(BluetoothProfile.EXTRA_STATE, toState);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            mService.sendBroadcastAsUser(intent, UserHandle.ALL, HeadsetService.BLUETOOTH_PERM);
            mHeadsetService.sendBroadcastAsUser(intent, UserHandle.ALL,
                    HeadsetService.BLUETOOTH_PERM);
        }
        }


        /**
        /**
@@ -451,6 +459,11 @@ public class HeadsetStateMachine extends StateMachine {
            mWaitingForVoiceRecognition = false;
            mWaitingForVoiceRecognition = false;
            mAudioParams.clear();
            mAudioParams.clear();
            broadcastStateTransitions();
            broadcastStateTransitions();
            // Remove the state machine for unbonded devices
            if (mPrevState != null
                    && mAdapterService.getBondState(mDevice) == BluetoothDevice.BOND_NONE) {
                getHandler().post(() -> mHeadsetService.removeStateMachine(mDevice));
            }
        }
        }


        @Override
        @Override
@@ -516,12 +529,12 @@ public class HeadsetStateMachine extends StateMachine {
                // Both events result in Connecting state as SLC establishment is still required
                // Both events result in Connecting state as SLC establishment is still required
                case HeadsetHalConstants.CONNECTION_STATE_CONNECTED:
                case HeadsetHalConstants.CONNECTION_STATE_CONNECTED:
                case HeadsetHalConstants.CONNECTION_STATE_CONNECTING:
                case HeadsetHalConstants.CONNECTION_STATE_CONNECTING:
                    if (mService.okToAcceptConnection(mDevice)) {
                    if (mHeadsetService.okToAcceptConnection(mDevice)) {
                        stateLogI("accept incoming connection");
                        stateLogI("accept incoming connection");
                        transitionTo(mConnecting);
                        transitionTo(mConnecting);
                    } else {
                    } else {
                        stateLogI("rejected incoming HF, priority=" + mService.getPriority(mDevice)
                        stateLogI("rejected incoming HF, priority=" + mHeadsetService.getPriority(
                                + " bondState=" + mDevice.getBondState());
                                mDevice) + " bondState=" + mAdapterService.getBondState(mDevice));
                        // Reject the connection and stay in Disconnected state itself
                        // Reject the connection and stay in Disconnected state itself
                        if (!mNativeInterface.disconnectHfp(mDevice)) {
                        if (!mNativeInterface.disconnectHfp(mDevice)) {
                            stateLogE("failed to disconnect");
                            stateLogE("failed to disconnect");
@@ -1219,8 +1232,8 @@ public class HeadsetStateMachine extends StateMachine {
            // Set active device to current active SCO device when the current active device
            // Set active device to current active SCO device when the current active device
            // is different from mCurrentDevice. This is to accommodate active device state
            // is different from mCurrentDevice. This is to accommodate active device state
            // mis-match between native and Java.
            // mis-match between native and Java.
            if (!mDevice.equals(mService.getActiveDevice())) {
            if (!mDevice.equals(mHeadsetService.getActiveDevice())) {
                mService.setActiveDevice(mDevice);
                mHeadsetService.setActiveDevice(mDevice);
            }
            }
            setAudioParameters();
            setAudioParameters();
            mSystemInterface.getAudioManager().setBluetoothScoOn(true);
            mSystemInterface.getAudioManager().setBluetoothScoOn(true);
@@ -1460,7 +1473,7 @@ public class HeadsetStateMachine extends StateMachine {
                    }
                    }
                }
                }
                try {
                try {
                    mService.startActivity(VOICE_COMMAND_INTENT);
                    mHeadsetService.startActivity(VOICE_COMMAND_INTENT);
                } catch (ActivityNotFoundException e) {
                } catch (ActivityNotFoundException e) {
                    mNativeInterface.atResponseCode(device, HeadsetHalConstants.AT_RESPONSE_ERROR,
                    mNativeInterface.atResponseCode(device, HeadsetHalConstants.AT_RESPONSE_ERROR,
                            0);
                            0);
@@ -1549,7 +1562,7 @@ public class HeadsetStateMachine extends StateMachine {


    private synchronized void expectVoiceRecognition(BluetoothDevice device) {
    private synchronized void expectVoiceRecognition(BluetoothDevice device) {
        mWaitingForVoiceRecognition = true;
        mWaitingForVoiceRecognition = true;
        mService.setActiveDevice(device);
        mHeadsetService.setActiveDevice(device);
        sendMessageDelayed(START_VR_TIMEOUT, device, START_VR_TIMEOUT_MS);
        sendMessageDelayed(START_VR_TIMEOUT, device, START_VR_TIMEOUT_MS);
        if (!mSystemInterface.getVoiceRecognitionWakeLock().isHeld()) {
        if (!mSystemInterface.getVoiceRecognitionWakeLock().isHeld()) {
            mSystemInterface.getVoiceRecognitionWakeLock().acquire(START_VR_TIMEOUT_MS);
            mSystemInterface.getVoiceRecognitionWakeLock().acquire(START_VR_TIMEOUT_MS);
@@ -1576,7 +1589,7 @@ public class HeadsetStateMachine extends StateMachine {
        intent.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "."
        intent.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "."
                + Integer.toString(companyId));
                + Integer.toString(companyId));


        mService.sendBroadcastAsUser(intent, UserHandle.ALL, HeadsetService.BLUETOOTH_PERM);
        mHeadsetService.sendBroadcastAsUser(intent, UserHandle.ALL, HeadsetService.BLUETOOTH_PERM);
    }
    }


    private void setAudioParameters() {
    private void setAudioParameters() {
@@ -1720,11 +1733,11 @@ public class HeadsetStateMachine extends StateMachine {
        }
        }
        // Check for virtual call to terminate before sending Call Intent
        // Check for virtual call to terminate before sending Call Intent
        terminateScoUsingVirtualVoiceCall();
        terminateScoUsingVirtualVoiceCall();
        mService.setActiveDevice(mDevice);
        mHeadsetService.setActiveDevice(mDevice);
        Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
        Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
                Uri.fromParts(SCHEME_TEL, dialNumber, null));
                Uri.fromParts(SCHEME_TEL, dialNumber, null));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mService.startActivity(intent);
        mHeadsetService.startActivity(intent);
        // TODO(BT) continue send OK reults code after call starts
        // TODO(BT) continue send OK reults code after call starts
        //          hold wait lock, start a timer, set wait call flag
        //          hold wait lock, start a timer, set wait call flag
        //          Get call started indication from bluetooth phone
        //          Get call started indication from bluetooth phone
@@ -1761,7 +1774,7 @@ public class HeadsetStateMachine extends StateMachine {
                if (!hasMessages(DIALING_OUT_TIMEOUT)) {
                if (!hasMessages(DIALING_OUT_TIMEOUT)) {
                    return;
                    return;
                }
                }
                mService.setActiveDevice(mDevice);
                mHeadsetService.setActiveDevice(mDevice);
                mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0);
                mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0);
                removeMessages(DIALING_OUT_TIMEOUT);
                removeMessages(DIALING_OUT_TIMEOUT);
            } else if (callState.mCallState == HeadsetHalConstants.CALL_STATE_ACTIVE
            } else if (callState.mCallState == HeadsetHalConstants.CALL_STATE_ACTIVE
@@ -2063,7 +2076,7 @@ public class HeadsetStateMachine extends StateMachine {
            mSystemInterface.answerCall(device);
            mSystemInterface.answerCall(device);
        } else if (phoneState.getNumActiveCall() > 0) {
        } else if (phoneState.getNumActiveCall() > 0) {
            if (getAudioState() != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
            if (getAudioState() != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
                mService.setActiveDevice(mDevice);
                mHeadsetService.setActiveDevice(mDevice);
                mNativeInterface.connectAudio(mDevice);
                mNativeInterface.connectAudio(mDevice);
            } else {
            } else {
                mSystemInterface.hangupCall(device, false);
                mSystemInterface.hangupCall(device, false);
@@ -2074,11 +2087,11 @@ public class HeadsetStateMachine extends StateMachine {
                log("processKeyPressed, last dial number null");
                log("processKeyPressed, last dial number null");
                return;
                return;
            }
            }
            mService.setActiveDevice(mDevice);
            mHeadsetService.setActiveDevice(mDevice);
            Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
            Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
                    Uri.fromParts(SCHEME_TEL, dialNumber, null));
                    Uri.fromParts(SCHEME_TEL, dialNumber, null));
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            mService.startActivity(intent);
            mHeadsetService.startActivity(intent);
        }
        }
    }
    }


@@ -2095,7 +2108,7 @@ public class HeadsetStateMachine extends StateMachine {
        intent.putExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, indId);
        intent.putExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, indId);
        intent.putExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, indValue);
        intent.putExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, indValue);


        mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
        mHeadsetService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
    }
    }


    private void processAtBind(String atString, BluetoothDevice device) {
    private void processAtBind(String atString, BluetoothDevice device) {
@@ -2159,7 +2172,7 @@ public class HeadsetStateMachine extends StateMachine {
    }
    }


    private String getCurrentDeviceName() {
    private String getCurrentDeviceName() {
        String deviceName = mDevice.getName();
        String deviceName = mAdapterService.getRemoteName(mDevice);
        if (deviceName == null) {
        if (deviceName == null) {
            return "<unknown>";
            return "<unknown>";
        }
        }
@@ -2169,28 +2182,28 @@ public class HeadsetStateMachine extends StateMachine {
    // Accept incoming SCO only when there is in-band ringing, incoming call,
    // Accept incoming SCO only when there is in-band ringing, incoming call,
    // active call, VR activated, active VOIP call
    // active call, VR activated, active VOIP call
    private boolean isScoAcceptable() {
    private boolean isScoAcceptable() {
        if (mService.getForceScoAudio()) {
        if (mHeadsetService.getForceScoAudio()) {
            return true;
            return true;
        }
        }
        BluetoothDevice activeDevice = mService.getActiveDevice();
        BluetoothDevice activeDevice = mHeadsetService.getActiveDevice();
        if (!mDevice.equals(activeDevice)) {
        if (!mDevice.equals(activeDevice)) {
            Log.w(TAG, "isScoAcceptable: rejected SCO since " + mDevice
            Log.w(TAG, "isScoAcceptable: rejected SCO since " + mDevice
                    + " is not the current active device " + activeDevice);
                    + " is not the current active device " + activeDevice);
            return false;
            return false;
        }
        }
        if (!mService.getAudioRouteAllowed()) {
        if (!mHeadsetService.getAudioRouteAllowed()) {
            Log.w(TAG, "isScoAcceptabl: rejected SCO since audio route is not allowed");
            Log.w(TAG, "isScoAcceptabl: rejected SCO since audio route is not allowed");
            return false;
            return false;
        }
        }
        if (mSystemInterface.isInCall() || mVoiceRecognitionStarted) {
        if (mSystemInterface.isInCall() || mVoiceRecognitionStarted) {
            return true;
            return true;
        }
        }
        if (mSystemInterface.isRinging() && mService.isInbandRingingEnabled()) {
        if (mSystemInterface.isRinging() && mHeadsetService.isInbandRingingEnabled()) {
            return true;
            return true;
        }
        }
        Log.w(TAG, "isScoAcceptable: rejected SCO, inCall=" + mSystemInterface.isInCall()
        Log.w(TAG, "isScoAcceptable: rejected SCO, inCall=" + mSystemInterface.isInCall()
                + ", voiceRecognition=" + mVoiceRecognitionStarted + ", ringing=" + mSystemInterface
                + ", voiceRecognition=" + mVoiceRecognitionStarted + ", ringing=" + mSystemInterface
                .isRinging() + ", inbandRinging=" + mService.isInbandRingingEnabled());
                .isRinging() + ", inbandRinging=" + mHeadsetService.isInbandRingingEnabled());
        return false;
        return false;
    }
    }


+341 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading