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

Commit d9df442f authored by Jason Hsu's avatar Jason Hsu Committed by Android (Google) Code Review
Browse files

Merge "[HA Status] Notify hearing devices connection status" into main

parents 00b503d4 5add7298
Loading
Loading
Loading
Loading
+40 −8
Original line number Diff line number Diff line
@@ -444,12 +444,23 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
    }

    /**
     * @return {@code true} if {@code cachedBluetoothDevice} is hearing aid device
     * @return {@code true} if {@code cachedBluetoothDevice} is hearing aid device.
     * @deprecated use {@link #isHearingDevice() }
     * // TODO: b/385679160 - Target to deprecate it and replace  with #isHearingDevice()
     */
    @Deprecated
    public boolean isHearingAidDevice() {
        return mHearingAidInfo != null;
    }

    /**
     * @return {@code true} if {@code cachedBluetoothDevice} support any of hearing device profile.
     */
    public boolean isHearingDevice() {
        return getProfiles().stream().anyMatch(
                p -> (p instanceof HearingAidProfile || p instanceof HapClientProfile));
    }

    public int getDeviceSide() {
        return mHearingAidInfo != null
                ? mHearingAidInfo.getSide() : HearingAidInfo.DeviceSide.SIDE_INVALID;
@@ -910,12 +921,33 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
        }
    }

    /**
     * Checks if the device is connected to the specified Bluetooth profile.
     *
     * @param profile The Bluetooth profile to check.
     * @return {@code true} if the device is connected to the profile.
     */
    public boolean isConnectedProfile(LocalBluetoothProfile profile) {
        int status = getProfileConnectionState(profile);
        return status == BluetoothProfile.STATE_CONNECTED;

    }

    /**
     * Checks if the device is connected to the Bluetooth profile with the given ID.
     *
     * @param profileId The ID of the Bluetooth profile to check.
     * @return {@code true} if the device is connected to the profile.
     */
    public boolean isConnectedProfile(int profileId) {
        for (LocalBluetoothProfile profile : getProfiles()) {
            if (profile.getProfileId() == profileId) {
                return isConnectedProfile(profile);
            }
        }
        return false;
    }

    public boolean isBusy() {
        synchronized (mProfileLock) {
            for (LocalBluetoothProfile profile : mProfiles) {
@@ -1890,13 +1922,6 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
                == BluetoothProfile.STATE_CONNECTED;
    }

    /**
     * @return {@code true} if {@code cachedBluetoothDevice} is LeAudio hearing aid device
     */
    public boolean isConnectedLeAudioHearingAidDevice() {
        return isConnectedHapClientDevice() && isConnectedLeAudioDevice();
    }

    /**
     * @return {@code true} if {@code cachedBluetoothDevice} is hearing aid device
     *
@@ -1907,6 +1932,13 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
        return isConnectedAshaHearingAidDevice() || isConnectedLeAudioHearingAidDevice();
    }

    /**
     * @return {@code true} if {@code cachedBluetoothDevice} is LeAudio hearing aid device
     */
    public boolean isConnectedLeAudioHearingAidDevice() {
        return isConnectedHapClientDevice() && isConnectedLeAudioDevice();
    }

    /**
     * @return {@code true} if {@code cachedBluetoothDevice} is LeAudio device
     */
+33 −2
Original line number Diff line number Diff line
@@ -24,7 +24,10 @@ import android.bluetooth.le.ScanFilter;
import android.content.Context;
import android.util.Log;

import androidx.annotation.NonNull;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.flags.Flags;

import java.sql.Timestamp;
import java.util.ArrayList;
@@ -46,7 +49,7 @@ public class CachedBluetoothDeviceManager {
    private final LocalBluetoothManager mBtManager;

    @VisibleForTesting
    final List<CachedBluetoothDevice> mCachedDevices = new ArrayList<CachedBluetoothDevice>();
    final List<CachedBluetoothDevice> mCachedDevices = new ArrayList<>();
    @VisibleForTesting
    HearingAidDeviceManager mHearingAidDeviceManager;
    @VisibleForTesting
@@ -191,6 +194,20 @@ public class CachedBluetoothDeviceManager {
        }
    }

    /**
     * Notifies the connection status if device is hearing device.
     *
     * @param device The {@link CachedBluetoothDevice} need to be hearing device
     */
    public synchronized void notifyHearingDevicesConnectionStatusChangedIfNeeded(
            @NonNull CachedBluetoothDevice device) {
        if (!device.isHearingDevice()) {
            return;
        }

        mHearingAidDeviceManager.notifyDevicesConnectionStatusChanged();
    }

    /**
     * Search for existing sub device {@link CachedBluetoothDevice}.
     *
@@ -388,8 +405,14 @@ public class CachedBluetoothDeviceManager {

    /** Handles when the device been set as active/inactive. */
    public synchronized void onActiveDeviceChanged(CachedBluetoothDevice cachedBluetoothDevice) {
        if (cachedBluetoothDevice.isHearingAidDevice()) {
        if (cachedBluetoothDevice == null) {
            return;
        }
        if (cachedBluetoothDevice.isHearingDevice()) {
            mHearingAidDeviceManager.onActiveDeviceChanged(cachedBluetoothDevice);
            if (Flags.hearingDeviceSetConnectionStatusReport()) {
                mHearingAidDeviceManager.notifyDevicesConnectionStatusChanged();
            }
        }
    }

@@ -421,6 +444,14 @@ public class CachedBluetoothDeviceManager {
            mainDevice.unpair();
            mainDevice.setSubDevice(null);
        }

        // TODO: b/386121967 - Should change to use isHearingDevice but mProfile get clear here.
        //  Need to consider where to put this logic when using isHearingDevice()
        if (device.isHearingAidDevice()) {
            if (Flags.hearingDeviceSetConnectionStatusReport()) {
                mHearingAidDeviceManager.notifyDevicesConnectionStatusChanged();
            }
        }
    }

    /**
+154 −1
Original line number Diff line number Diff line
@@ -15,7 +15,10 @@
 */
package com.android.settingslib.bluetooth;

import static android.bluetooth.BluetoothDevice.BOND_BONDED;

import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHapClient;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothProfile;
@@ -30,15 +33,22 @@ import android.provider.Settings;
import android.util.FeatureFlagUtils;
import android.util.Log;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.collection.ArraySet;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants.RoutingValue;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * HearingAidDeviceManager manages the set of remote HearingAid(ASHA) Bluetooth devices.
 * HearingAidDeviceManager manages the set of remote bluetooth hearing devices.
 */
public class HearingAidDeviceManager {
    private static final String TAG = "HearingAidDeviceManager";
@@ -49,6 +59,10 @@ public class HearingAidDeviceManager {
    private final LocalBluetoothManager mBtManager;
    private final List<CachedBluetoothDevice> mCachedDevices;
    private final HearingAidAudioRoutingHelper mRoutingHelper;
    @ConnectionStatus
    private int mDevicesConnectionStatus = ConnectionStatus.NO_DEVICE_BONDED;
    private boolean mInitialDevicesConnectionStatusUpdate = false;

    HearingAidDeviceManager(Context context, LocalBluetoothManager localBtManager,
            List<CachedBluetoothDevice> CachedDevices) {
        mContext = context;
@@ -68,6 +82,145 @@ public class HearingAidDeviceManager {
        mRoutingHelper = routingHelper;
    }

    /**
     * Defines the connection status for hearing devices.
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
            ConnectionStatus.NO_DEVICE_BONDED,
            ConnectionStatus.DISCONNECTED,
            ConnectionStatus.CONNECTED,
            ConnectionStatus.CONNECTING_OR_DISCONNECTING,
            ConnectionStatus.ACTIVE
    })
    public @interface ConnectionStatus {
        int NO_DEVICE_BONDED = -1;
        int DISCONNECTED = 0;
        int CONNECTED = 1;
        int CONNECTING_OR_DISCONNECTING = 2;
        int ACTIVE = 3;
    }

    /**
     * Updates the connection status of the hearing devices based on the currently bonded
     * hearing aid devices.
     */
    synchronized void notifyDevicesConnectionStatusChanged() {
        updateDevicesConnectionStatus();
        // TODO: b/357882387 - notify connection status changes for the callers
    }

    private void updateDevicesConnectionStatus() {
        mInitialDevicesConnectionStatusUpdate = true;
        // Add all hearing devices including sub and member into a set.
        Set<CachedBluetoothDevice> allHearingDevices = mCachedDevices.stream()
                .filter(d -> d.getBondState() == BluetoothDevice.BOND_BONDED
                        && d.isHearingDevice())
                .flatMap(d -> getAssociatedCachedDevice(d).stream())
                .collect(Collectors.toSet());

        // Status sequence matters here. If one of the hearing devices is in previous
        // ConnectionStatus, we will treat whole hearing devices is in this status.
        // E.g. One of hearing device is in CONNECTED status and another is in DISCONNECTED
        // status, the hearing devices connection status will notify CONNECTED status.
        if (isConnectingOrDisconnectingConnectionStatus(allHearingDevices)) {
            mDevicesConnectionStatus = ConnectionStatus.CONNECTING_OR_DISCONNECTING;
        } else if (isActiveConnectionStatus(allHearingDevices)) {
            mDevicesConnectionStatus = ConnectionStatus.ACTIVE;
        } else if (isConnectedStatus(allHearingDevices)) {
            mDevicesConnectionStatus = ConnectionStatus.CONNECTED;
        } else if (isDisconnectedStatus(allHearingDevices)) {
            mDevicesConnectionStatus = ConnectionStatus.DISCONNECTED;
        } else {
            mDevicesConnectionStatus = ConnectionStatus.NO_DEVICE_BONDED;
        }

        if (DEBUG) {
            Log.d(TAG, "updateDevicesConnectionStatus: " + mDevicesConnectionStatus);
        }
    }

    /**
     * @return all the related CachedBluetoothDevices for this device.
     */
    @NonNull
    public Set<CachedBluetoothDevice> getAssociatedCachedDevice(
            @NonNull CachedBluetoothDevice device) {
        ArraySet<CachedBluetoothDevice> cachedDeviceSet = new ArraySet<>();
        cachedDeviceSet.add(device);
        // Associated device should be added into memberDevice if it support CSIP profile.
        Set<CachedBluetoothDevice> memberDevices = device.getMemberDevice();
        if (!memberDevices.isEmpty()) {
            cachedDeviceSet.addAll(memberDevices);
            return cachedDeviceSet;
        }
        // If not support CSIP profile, it should be ASHA hearing device and added into subDevice.
        CachedBluetoothDevice subDevice = device.getSubDevice();
        if (subDevice != null) {
            cachedDeviceSet.add(subDevice);
            return cachedDeviceSet;
        }

        return cachedDeviceSet;
    }

    private boolean isConnectingOrDisconnectingConnectionStatus(
            Set<CachedBluetoothDevice> devices) {
        HearingAidProfile hearingAidProfile = mBtManager.getProfileManager().getHearingAidProfile();
        HapClientProfile hapClientProfile = mBtManager.getProfileManager().getHapClientProfile();

        for (CachedBluetoothDevice device : devices) {
            if (hearingAidProfile != null) {
                int status = device.getProfileConnectionState(hearingAidProfile);
                if (status == BluetoothProfile.STATE_DISCONNECTING
                        || status == BluetoothProfile.STATE_CONNECTING) {
                    return true;
                }
            }
            if (hapClientProfile != null) {
                int status = device.getProfileConnectionState(hapClientProfile);
                if (status == BluetoothProfile.STATE_DISCONNECTING
                        || status == BluetoothProfile.STATE_CONNECTING) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isActiveConnectionStatus(Set<CachedBluetoothDevice> devices) {
        for (CachedBluetoothDevice device : devices) {
            if ((device.isActiveDevice(BluetoothProfile.HEARING_AID)
                    && device.isConnectedProfile(BluetoothProfile.HEARING_AID))
                    || (device.isActiveDevice(BluetoothProfile.LE_AUDIO)
                    && device.isConnectedProfile(BluetoothProfile.LE_AUDIO))) {
                return true;
            }
        }
        return false;
    }

    private boolean isConnectedStatus(Set<CachedBluetoothDevice> devices) {
        return devices.stream().anyMatch(CachedBluetoothDevice::isConnected);
    }

    private boolean isDisconnectedStatus(Set<CachedBluetoothDevice> devices) {
        return devices.stream().anyMatch(
                d -> (!d.isConnected() && d.getBondState() == BOND_BONDED));
    }

    /**
     * Gets the connection status for hearing device set. Will update connection status first if
     * never updated.
     */
    @ConnectionStatus
    public int getDevicesConnectionStatus() {
        if (!mInitialDevicesConnectionStatusUpdate) {
            updateDevicesConnectionStatus();
        }
        return mDevicesConnectionStatus;
    }

    void initHearingAidDeviceIfNeeded(CachedBluetoothDevice newDevice,
            List<ScanFilter> leScanFilters) {
        HearingAidInfo info = generateHearingAidInfo(newDevice);
+28 −12
Original line number Diff line number Diff line
@@ -47,12 +47,14 @@ import androidx.annotation.VisibleForTesting;

import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.settingslib.flags.Flags;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;


@@ -345,11 +347,17 @@ public class LocalBluetoothProfileManager {
                    oldState == BluetoothProfile.STATE_CONNECTING) {
                Log.i(TAG, "Failed to connect " + mProfile + " device");
            }
            final boolean isAshaProfile = getHearingAidProfile() != null
                    && mProfile instanceof HearingAidProfile;
            final boolean isHapClientProfile = getHapClientProfile() != null
                    && mProfile instanceof HapClientProfile;
            final boolean isLeAudioProfile = getLeAudioProfile() != null
                    && mProfile instanceof LeAudioProfile;
            final boolean isHapClientOrLeAudioProfile = isHapClientProfile || isLeAudioProfile;
            final boolean isCsipProfile = getCsipSetCoordinatorProfile() != null
                    && mProfile instanceof CsipSetCoordinatorProfile;

            if (getHearingAidProfile() != null
                    && mProfile instanceof HearingAidProfile
                    && (newState == BluetoothProfile.STATE_CONNECTED)) {

            if (isAshaProfile && (newState == BluetoothProfile.STATE_CONNECTED)) {
                // Check if the HiSyncID has being initialized
                if (cachedDevice.getHiSyncId() == BluetoothHearingAid.HI_SYNC_ID_INVALID) {
                    long newHiSyncId = getHearingAidProfile().getHiSyncId(cachedDevice.getDevice());
@@ -366,11 +374,6 @@ public class LocalBluetoothProfileManager {
                HearingAidStatsLogUtils.logHearingAidInfo(cachedDevice);
            }

            final boolean isHapClientProfile = getHapClientProfile() != null
                    && mProfile instanceof HapClientProfile;
            final boolean isLeAudioProfile = getLeAudioProfile() != null
                    && mProfile instanceof LeAudioProfile;
            final boolean isHapClientOrLeAudioProfile = isHapClientProfile || isLeAudioProfile;
            if (isHapClientOrLeAudioProfile && newState == BluetoothProfile.STATE_CONNECTED) {

                // Checks if both profiles are connected to the device. Hearing aid info need
@@ -385,9 +388,7 @@ public class LocalBluetoothProfileManager {
                }
            }

            if (getCsipSetCoordinatorProfile() != null
                    && mProfile instanceof CsipSetCoordinatorProfile
                    && newState == BluetoothProfile.STATE_CONNECTED) {
            if (isCsipProfile && (newState == BluetoothProfile.STATE_CONNECTED)) {
                // Check if the GroupID has being initialized
                if (cachedDevice.getGroupId() == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
                    final Map<Integer, ParcelUuid> groupIdMap = getCsipSetCoordinatorProfile()
@@ -403,6 +404,21 @@ public class LocalBluetoothProfileManager {
                }
            }

            // LE_AUDIO, CSIP_SET_COORDINATOR profiles will also impact the connection status
            // change, e.g. device need to active on LE_AUDIO to become active connection status.
            final Set<Integer> hearingDeviceConnectionStatusProfileId = Set.of(
                    BluetoothProfile.HEARING_AID,
                    BluetoothProfile.HAP_CLIENT,
                    BluetoothProfile.LE_AUDIO,
                    BluetoothProfile.CSIP_SET_COORDINATOR
            );
            if (Flags.hearingDeviceSetConnectionStatusReport()) {
                if (hearingDeviceConnectionStatusProfileId.contains(mProfile.getProfileId())) {
                    mDeviceManager.notifyHearingDevicesConnectionStatusChangedIfNeeded(
                            cachedDevice);
                }
            }

            cachedDevice.onProfileStateChanged(mProfile, newState);
            // Dispatch profile changed after device update
            boolean needDispatchProfileConnectionState = true;
+72 −12
Original line number Diff line number Diff line
@@ -33,21 +33,37 @@ import android.bluetooth.BluetoothUuid;
import android.content.Context;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;

import androidx.test.core.app.ApplicationProvider;

import com.google.common.collect.ImmutableList;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;

import java.util.Collection;
import java.util.List;
import java.util.Map;

@RunWith(RobolectricTestRunner.class)
public class CachedBluetoothDeviceManagerTest {
    @Rule
    public MockitoRule mMockitoRule = MockitoJUnit.rule();
    @Rule
    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();

    private final Context mContext = ApplicationProvider.getApplicationContext();

    private final static String DEVICE_NAME_1 = "TestName_1";
    private final static String DEVICE_NAME_2 = "TestName_2";
    private final static String DEVICE_NAME_3 = "TestName_3";
@@ -82,6 +98,8 @@ public class CachedBluetoothDeviceManagerTest {
    @Mock
    private HearingAidProfile mHearingAidProfile;
    @Mock
    private HapClientProfile mHapClientProfile;
    @Mock
    private CsipSetCoordinatorProfile mCsipSetCoordinatorProfile;
    @Mock
    private BluetoothDevice mDevice1;
@@ -89,12 +107,11 @@ public class CachedBluetoothDeviceManagerTest {
    private BluetoothDevice mDevice2;
    @Mock
    private BluetoothDevice mDevice3;
    private HearingAidDeviceManager mHearingAidDeviceManager;
    private CachedBluetoothDevice mCachedDevice1;
    private CachedBluetoothDevice mCachedDevice2;
    private CachedBluetoothDevice mCachedDevice3;
    private CachedBluetoothDeviceManager mCachedDeviceManager;
    private HearingAidDeviceManager mHearingAidDeviceManager;
    private Context mContext;

    private BluetoothClass createBtClass(int deviceClass) {
        Parcel p = Parcel.obtain();
@@ -108,8 +125,6 @@ public class CachedBluetoothDeviceManagerTest {

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext = RuntimeEnvironment.application;
        when(mDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1);
        when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
        when(mDevice3.getAddress()).thenReturn(DEVICE_ADDRESS_3);
@@ -129,13 +144,15 @@ public class CachedBluetoothDeviceManagerTest {
        when(mA2dpProfile.isProfileReady()).thenReturn(true);
        when(mPanProfile.isProfileReady()).thenReturn(true);
        when(mHearingAidProfile.isProfileReady()).thenReturn(true);
        when(mHapClientProfile.isProfileReady()).thenReturn(true);
        when(mCsipSetCoordinatorProfile.isProfileReady())
                .thenReturn(true);
        doAnswer((invocation) -> mHearingAidProfile).
                when(mLocalProfileManager).getHearingAidProfile();
        doAnswer((invocation) -> mCsipSetCoordinatorProfile)
                .when(mLocalProfileManager).getCsipSetCoordinatorProfile();
        mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager);
        mCachedDeviceManager = spy(
                new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager));
        mCachedDevice1 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice1));
        mCachedDevice2 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice2));
        mCachedDevice3 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice3));
@@ -621,12 +638,55 @@ public class CachedBluetoothDeviceManagerTest {
    public void onActiveDeviceChanged_validHiSyncId_callExpectedFunction() {
        doNothing().when(mHearingAidDeviceManager).onActiveDeviceChanged(any());
        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
        cachedDevice1.setHearingAidInfo(
                new HearingAidInfo.Builder().setHiSyncId(HISYNCID1).build());
        when(mCachedDevice1.getProfiles()).thenReturn(
                ImmutableList.of(mHapClientProfile, mHearingAidProfile));

        mCachedDeviceManager.onActiveDeviceChanged(mCachedDevice1);

        verify(mHearingAidDeviceManager).onActiveDeviceChanged(mCachedDevice1);
    }

    @Test
    @RequiresFlagsEnabled(
            com.android.settingslib.flags.Flags.FLAG_HEARING_DEVICE_SET_CONNECTION_STATUS_REPORT)
    public void onActiveDeviceChanged_hearingDevice_callReportConnectionStatus() {
        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
        when(mCachedDevice1.getProfiles()).thenReturn(
                ImmutableList.of(mHapClientProfile, mHearingAidProfile));

        mCachedDeviceManager.onActiveDeviceChanged(mCachedDevice1);

        verify(mHearingAidDeviceManager).notifyDevicesConnectionStatusChanged();
    }

    @Test
    @RequiresFlagsEnabled(
            com.android.settingslib.flags.Flags.FLAG_HEARING_DEVICE_SET_CONNECTION_STATUS_REPORT)
    public void onDeviceUnpaired_hearingDevice_callReportConnectionStatus() {
        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
        when(mCachedDevice1.getProfiles()).thenReturn(
                ImmutableList.of(mHapClientProfile, mHearingAidProfile));

        mCachedDeviceManager.onDeviceUnpaired(mCachedDevice1);

        verify(mHearingAidDeviceManager).notifyDevicesConnectionStatusChanged();
    }

    @Test
    public void notifyHearingDevicesConnectionStatusChanged_nonHearingDevice_notCallFunction() {
        when(mCachedDevice1.getProfiles()).thenReturn(List.of(mA2dpProfile));

        mCachedDeviceManager.notifyHearingDevicesConnectionStatusChangedIfNeeded(mCachedDevice1);

        verify(mHearingAidDeviceManager, never()).notifyDevicesConnectionStatusChanged();
    }

    @Test
    public void notifyHearingDevicesConnectionStatusChanged_hearingDeviceProfile_callFunction() {
        when(mCachedDevice1.getProfiles()).thenReturn(List.of(mHapClientProfile));

        mCachedDeviceManager.onActiveDeviceChanged(cachedDevice1);
        mCachedDeviceManager.notifyHearingDevicesConnectionStatusChangedIfNeeded(mCachedDevice1);

        verify(mHearingAidDeviceManager).onActiveDeviceChanged(cachedDevice1);
        verify(mHearingAidDeviceManager).notifyDevicesConnectionStatusChanged();
    }
}
Loading