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

Commit e7cb6bd2 authored by Alice Kuo's avatar Alice Kuo
Browse files

csip: seamless pair with the coordinated set

1. Handle the set member avaiabler intent, check the group is existing and create bond automatically.
2. Accept the paring request for the ongoing set member

Bug: 150670922
Bug: 178981521
Test: pair with one of the CSIP supported device,and get bonded with the
whole coordinated set

Change-Id: Ia95e1ba6dccde0a4e61a9eafdef746b1415704a4
parent e7d2554f
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -126,6 +126,9 @@ public class BluetoothEventManager {
        addHandler(BluetoothDevice.ACTION_ACL_CONNECTED, new AclStateChangedHandler());
        addHandler(BluetoothDevice.ACTION_ACL_DISCONNECTED, new AclStateChangedHandler());

        addHandler(BluetoothCsipSetCoordinator.ACTION_CSIS_SET_MEMBER_AVAILABLE,
                new SetMemberAvailableHandler());

        registerAdapterIntentReceiver();
    }

@@ -339,6 +342,12 @@ public class BluetoothEventManager {
            }
            int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                    BluetoothDevice.ERROR);

            if (mDeviceManager.onBondStateChangedIfProcess(device, bondState)) {
                Log.d(TAG, "Should not update UI for the set member");
                return;
            }

            CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
            if (cachedDevice == null) {
                Log.w(TAG, "Got bonding state changed for " + device +
@@ -502,4 +511,29 @@ public class BluetoothEventManager {
            dispatchAudioModeChanged();
        }
    }

    private class SetMemberAvailableHandler implements Handler {
        @Override
        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
            final String action = intent.getAction();
            if (device == null) {
                Log.e(TAG, "SetMemberAvailableHandler: device is null");
                return;
            }

            if (action == null) {
                Log.e(TAG, "SetMemberAvailableHandler: action is null");
                return;
            }

            final int groupId = intent.getIntExtra(BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_ID,
                    BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
            if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
                Log.e(TAG, "SetMemberAvailableHandler: Invalid group id");
                return;
            }

            mDeviceManager.onSetMemberAppear(device, groupId);
        }
    }
}
+69 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ public class CachedBluetoothDeviceManager {
    HearingAidDeviceManager mHearingAidDeviceManager;
    @VisibleForTesting
    CsipDeviceManager mCsipDeviceManager;
    BluetoothDevice mOngoingSetMemberPair;

    CachedBluetoothDeviceManager(Context context, LocalBluetoothManager localBtManager) {
        mContext = context;
@@ -337,6 +338,74 @@ public class CachedBluetoothDeviceManager {
        }
    }

    /**
     * Called when we found a set member of a group. The function will check the {@code groupId} if
     * it exists and if there is a ongoing pair, the device would be ignored.
     *
     * @param device The found device
     * @param groupId The group id of the found device
     */
    public synchronized void onSetMemberAppear(BluetoothDevice device, int groupId) {
        Log.d(TAG, "onSetMemberAppear, groupId: " + groupId + " device: " + device.toString());

        if (mOngoingSetMemberPair != null) {
            Log.d(TAG, "Ongoing set memberPairing in process, drop it!");
            return;
        }

        if (mCsipDeviceManager.onSetMemberAppear(device, groupId)) {
            mOngoingSetMemberPair = device;
        }
    }

    /**
     * Called when the bond state change. If the bond state change is related with the
     * ongoing set member pair, the cachedBluetoothDevice will be created but the UI
     * would not be updated. For the other case, return {@code false} to go through the normal
     * flow.
     *
     * @param device The device
     * @param bondState The new bond state
     *
     * @return {@code true}, if the bond state change for the device is handled inside this
     * function, and would not like to update the UI. If not, return {@code false}.
     */
    public synchronized boolean onBondStateChangedIfProcess(BluetoothDevice device, int bondState) {
        if (mOngoingSetMemberPair == null || !mOngoingSetMemberPair.equals(device)) {
            return false;
        }

        if (bondState == BluetoothDevice.BOND_BONDING) {
            return true;
        }

        mOngoingSetMemberPair = null;
        if (bondState != BluetoothDevice.BOND_NONE) {
            if (findDevice(device) == null) {
                final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
                CachedBluetoothDevice newDevice =
                        new CachedBluetoothDevice(mContext, profileManager, device);
                mCachedDevices.add(newDevice);
                findDevice(device).connect();
            }
        }

        return true;
    }

    /**
     * Check if the device is the one which is initial paired locally by CSIP. The setting
     * would depned on it to accept the pairing request automatically
     *
     * @param device The device
     *
     * @return {@code true}, if the device is ongoing pair by CSIP. Otherwise, return
     * {@code false}.
     */
    public boolean isOngoingPairByCsip(BluetoothDevice device) {
        return !(mOngoingSetMemberPair == null) && mOngoingSetMemberPair.equals(device);
    }

    private void log(String msg) {
        if (DEBUG) {
            Log.d(TAG, msg);
+23 −0
Original line number Diff line number Diff line
@@ -239,6 +239,29 @@ public class CsipDeviceManager {
        return null;
    }

    /**
     * Called when we found a set member of a group. The function will check bond state, and
     * the {@code groupId} if it exists, and then create the bond.
     *
     * @param device The found device
     * @param groupId The group id of the found device
     *
     * @return {@code true}, if the we create bond with the device. Otherwise, return
     * {@code false}.
     */
    public boolean onSetMemberAppear(BluetoothDevice device, int groupId) {
        if (device.getBondState() != BluetoothDevice.BOND_NONE) {
            return false;
        }

        if (getCachedDevice(groupId) != null) {
            device.createBond(BluetoothDevice.TRANSPORT_LE);
            return true;
        }

        return false;
    }

    private void log(String msg) {
        if (DEBUG) {
            Log.d(TAG, msg);