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

Commit abc3642d authored by Matthew Xie's avatar Matthew Xie
Browse files

Set service priority of A2DP and Headset from BluetoothService via IPC call

We used to do the priority change in the 2 services after the broadcasted
intent reach them. But that left a small time gap that could reject
incoming connection due to undefined priorities.

Bug 4096186

Change-Id: I9bb6aedc7ed98c53a9b00c48eedd20b0cf5f1660
parent 8d9f9953
Loading
Loading
Loading
Loading
+0 −14
Original line number Diff line number Diff line
@@ -83,19 +83,6 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
                    onBluetoothDisable();
                    break;
                }
            } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
                int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                                                   BluetoothDevice.ERROR);
                switch(bondState) {
                case BluetoothDevice.BOND_BONDED:
                    if (getPriority(device) == BluetoothA2dp.PRIORITY_UNDEFINED) {
                        setPriority(device, BluetoothA2dp.PRIORITY_ON);
                    }
                    break;
                case BluetoothDevice.BOND_NONE:
                    setPriority(device, BluetoothA2dp.PRIORITY_UNDEFINED);
                    break;
                }
            } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
                synchronized (this) {
                    if (mAudioDevices.containsKey(device)) {
@@ -158,7 +145,6 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
        mAdapter = BluetoothAdapter.getDefaultAdapter();

        mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        mIntentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        mIntentFilter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
+82 −4
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ package android.server;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothHeadset;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
@@ -68,6 +71,8 @@ class BluetoothBondState {
    private final Context mContext;
    private final BluetoothService mService;
    private final BluetoothInputProfileHandler mBluetoothInputProfileHandler;
    private BluetoothA2dp mA2dpProxy;
    private BluetoothHeadset mHeadsetProxy;

    BluetoothBondState(Context context, BluetoothService service) {
        mContext = context;
@@ -126,14 +131,15 @@ class BluetoothBondState {

        if (state == BluetoothDevice.BOND_BONDED) {
            mService.addProfileState(address);
        } else if (state == BluetoothDevice.BOND_BONDING) {
            if (mA2dpProxy == null || mHeadsetProxy == null) {
                getProfileProxy();
            }
        } else if (state == BluetoothDevice.BOND_NONE) {
            mService.removeProfileState(address);
        }

        // HID is handled by BluetoothService, other profiles
        // will be handled by their respective services.
        mBluetoothInputProfileHandler.setInitialInputDevicePriority(
            mService.getRemoteDevice(address), state);
        setProfilePriorities(address, state);

        if (DBG) {
            Log.d(TAG, address + " bond state " + oldState + " -> " + state
@@ -261,6 +267,52 @@ class BluetoothBondState {
        mPinAttempt.put(address, new Integer(newAttempt));
    }

    private void getProfileProxy() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        if (mA2dpProxy == null) {
            bluetoothAdapter.getProfileProxy(mContext, mProfileServiceListener,
                                             BluetoothProfile.A2DP);
        }

        if (mHeadsetProxy == null) {
            bluetoothAdapter.getProfileProxy(mContext, mProfileServiceListener,
                                             BluetoothProfile.HEADSET);
        }
    }

    private void closeProfileProxy() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        if (mA2dpProxy != null) {
            bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, mA2dpProxy);
        }

        if (mHeadsetProxy != null) {
            bluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetProxy);
        }
    }

    private BluetoothProfile.ServiceListener mProfileServiceListener =
        new BluetoothProfile.ServiceListener() {

        public void onServiceConnected(int profile, BluetoothProfile proxy) {
            if (profile == BluetoothProfile.A2DP) {
                mA2dpProxy = (BluetoothA2dp) proxy;
            } else if (profile == BluetoothProfile.HEADSET) {
                mHeadsetProxy = (BluetoothHeadset) proxy;
            }
        }

        public void onServiceDisconnected(int profile) {
            if (profile == BluetoothProfile.A2DP) {
                mA2dpProxy = null;
            } else if (profile == BluetoothProfile.HEADSET) {
                mHeadsetProxy = null;
            }
        }
    };

    private void copyAutoPairingData() {
        FileInputStream in = null;
        FileOutputStream out = null;
@@ -365,4 +417,30 @@ class BluetoothBondState {
            }
        }
    }

    // Set service priority of Hid, A2DP and Headset profiles depending on
    // the bond state change
    private void setProfilePriorities(String address, int state) {
        BluetoothDevice remoteDevice = mService.getRemoteDevice(address);
        // HID is handled by BluetoothService
        mBluetoothInputProfileHandler.setInitialInputDevicePriority(remoteDevice, state);

        // Set service priority of A2DP and Headset
        // We used to do the priority change in the 2 services after the broadcast
        //   intent reach them. But that left a small time gap that could reject
        //   incoming connection due to undefined priorities.
        if (state == BluetoothDevice.BOND_BONDED) {
            if (mA2dpProxy.getPriority(remoteDevice) == BluetoothProfile.PRIORITY_UNDEFINED) {
                mA2dpProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_ON);
            }

            if (mHeadsetProxy.getPriority(remoteDevice) == BluetoothProfile.PRIORITY_UNDEFINED) {
                mHeadsetProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_ON);
            }
        } else if (state == BluetoothDevice.BOND_NONE) {
            mA2dpProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_UNDEFINED);
            mHeadsetProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_UNDEFINED);
        }
    }

}