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

Commit 638c3f60 authored by Automerger Merge Worker's avatar Automerger Merge Worker Committed by Android (Google) Code Review
Browse files

Merge "Merge changes from topic "hearingAidsInT" into tm-dev am: e5620036 am: 3ffe3a46"

parents 57ac16bd e7defd98
Loading
Loading
Loading
Loading
+38 −1
Original line number Diff line number Diff line
@@ -77,6 +77,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
    private final LocalBluetoothProfileManager mProfileManager;
    private final Object mProfileLock = new Object();
    BluetoothDevice mDevice;
    private int mDeviceSide;
    private int mDeviceMode;
    private long mHiSyncId;
    private int mGroupId;
    // Need this since there is no method for getting RSSI
@@ -335,6 +337,22 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
        connectDevice();
    }

    public int getDeviceSide() {
        return mDeviceSide;
    }

    public void setDeviceSide(int side) {
        mDeviceSide = side;
    }

    public int getDeviceMode() {
        return mDeviceMode;
    }

    public void setDeviceMode(int mode) {
        mDeviceMode = mode;
    }

    public long getHiSyncId() {
        return mHiSyncId;
    }
@@ -1111,7 +1129,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
                stringRes = R.string.bluetooth_battery_level;
            }

            // Set active string in following device connected situation.
            // Set active string in following device connected situation, also show battery
            // information if they have.
            //    1. Hearing Aid device active.
            //    2. Headset device active with in-calling state.
            //    3. A2DP device active without in-calling state.
@@ -1130,6 +1149,24 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
                        stringRes = R.string.bluetooth_active_no_battery_level;
                    }
                }

                // Try to show left/right information if can not get it from battery for hearing
                // aids specifically.
                if (mIsActiveDeviceHearingAid
                        && stringRes == R.string.bluetooth_active_no_battery_level) {
                    final CachedBluetoothDevice subDevice = getSubDevice();
                    if (subDevice != null && subDevice.isConnected()) {
                        stringRes = R.string.bluetooth_hearing_aid_left_and_right_active;
                    } else {
                        if (mDeviceSide == HearingAidProfile.DeviceSide.SIDE_LEFT) {
                            stringRes = R.string.bluetooth_hearing_aid_left_active;
                        } else if (mDeviceSide == HearingAidProfile.DeviceSide.SIDE_RIGHT) {
                            stringRes = R.string.bluetooth_hearing_aid_right_active;
                        } else {
                            stringRes = R.string.bluetooth_active_no_battery_level;
                        }
                    }
                }
            }
        }

+99 −0
Original line number Diff line number Diff line
@@ -29,13 +29,48 @@ import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;

import com.android.settingslib.R;
import com.android.settingslib.Utils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class HearingAidProfile implements LocalBluetoothProfile {
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
            DeviceSide.SIDE_INVALID,
            DeviceSide.SIDE_LEFT,
            DeviceSide.SIDE_RIGHT
    })

    /** Side definition for hearing aids. See {@link BluetoothHearingAid}. */
    public @interface DeviceSide {
        int SIDE_INVALID = -1;
        int SIDE_LEFT = 0;
        int SIDE_RIGHT = 1;
    }

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
            DeviceMode.MODE_INVALID,
            DeviceMode.MODE_MONAURAL,
            DeviceMode.MODE_BINAURAL
    })

    /** Mode definition for hearing aids. See {@link BluetoothHearingAid}. */
    public @interface DeviceMode {
        int MODE_INVALID = -1;
        int MODE_MONAURAL = 0;
        int MODE_BINAURAL = 1;
    }

    private static final String TAG = "HearingAidProfile";
    private static boolean V = true;

@@ -212,6 +247,11 @@ public class HearingAidProfile implements LocalBluetoothProfile {
        return isEnabled;
    }

    /**
     * Tells remote device to set an absolute volume.
     *
     * @param volume Absolute volume to be set on remote
     */
    public void setVolume(int volume) {
        if (mService == null) {
            return;
@@ -219,6 +259,12 @@ public class HearingAidProfile implements LocalBluetoothProfile {
        mService.setVolume(volume);
    }

    /**
     * Gets the HiSyncId (unique hearing aid device identifier) of the device.
     *
     * @param device Bluetooth device
     * @return the HiSyncId of the device
     */
    public long getHiSyncId(BluetoothDevice device) {
        if (mService == null || device == null) {
            return BluetoothHearingAid.HI_SYNC_ID_INVALID;
@@ -226,6 +272,59 @@ public class HearingAidProfile implements LocalBluetoothProfile {
        return mService.getHiSyncId(device);
    }

    /**
     * Gets the side of the device.
     *
     * @param device Bluetooth device.
     * @return side of the device. See {@link DeviceSide}.
     */
    @DeviceSide
    public int getDeviceSide(@NonNull BluetoothDevice device) {
        final int defaultValue = DeviceSide.SIDE_INVALID;
        if (mService == null) {
            Log.w(TAG, "Proxy not attached to HearingAidService");
            return defaultValue;
        }

        try {
            Method method = mService.getClass().getDeclaredMethod("getDeviceSideInternal",
                    BluetoothDevice.class);
            method.setAccessible(true);
            return (int) method.invoke(mService, device);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            Log.e(TAG, "fail to get getDeviceSideInternal\n" + e.toString() + "\n"
                    + Log.getStackTraceString(new Throwable()));
            return defaultValue;
        }
    }

    /**
     * Gets the mode of the device.
     *
     * @param device Bluetooth device
     * @return mode of the device. See {@link DeviceMode}.
     */
    @DeviceMode
    public int getDeviceMode(@NonNull BluetoothDevice device) {
        final int defaultValue = DeviceMode.MODE_INVALID;
        if (mService == null) {
            Log.w(TAG, "Proxy not attached to HearingAidService");
            return defaultValue;
        }

        try {
            Method method = mService.getClass().getDeclaredMethod("getDeviceModeInternal",
                    BluetoothDevice.class);
            method.setAccessible(true);
            return (int) method.invoke(mService, device);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            Log.e(TAG, "fail to get getDeviceModeInternal\n" + e.toString() + "\n"
                    + Log.getStackTraceString(new Throwable()));

            return defaultValue;
        }
    }

    public String toString() {
        return NAME;
    }
+5 −0
Original line number Diff line number Diff line
@@ -340,6 +340,11 @@ public class LocalBluetoothProfileManager {
            if (getHearingAidProfile() != null &&
                mProfile instanceof HearingAidProfile &&
                (newState == BluetoothProfile.STATE_CONNECTED)) {
                final int side = getHearingAidProfile().getDeviceSide(cachedDevice.getDevice());
                final int mode = getHearingAidProfile().getDeviceMode(cachedDevice.getDevice());
                cachedDevice.setDeviceSide(side);
                cachedDevice.setDeviceMode(mode);

                // Check if the HiSyncID has being initialized
                if (cachedDevice.getHiSyncId() == BluetoothHearingAid.HI_SYNC_ID_INVALID) {
                    long newHiSyncId = getHearingAidProfile().getHiSyncId(cachedDevice.getDevice());
+44 −19
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ public class CachedBluetoothDeviceTest {
    @Mock
    private BluetoothDevice mSubDevice;
    private CachedBluetoothDevice mCachedDevice;
    private CachedBluetoothDevice mSubCachedDevice;
    private AudioManager mAudioManager;
    private Context mContext;
    private int mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
@@ -95,7 +96,9 @@ public class CachedBluetoothDeviceTest {
        when(mPanProfile.isProfileReady()).thenReturn(true);
        when(mHearingAidProfile.isProfileReady()).thenReturn(true);
        mCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mDevice));
        mSubCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mSubDevice));
        doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel();
        doAnswer((invocation) -> mBatteryLevel).when(mSubCachedDevice).getBatteryLevel();
    }

    @Test
@@ -351,8 +354,9 @@ public class CachedBluetoothDeviceTest {
        assertThat(mCachedDevice.getConnectionSummary()).isNull();

        // Set device as Active for Hearing Aid and test connection state summary
        mCachedDevice.setDeviceSide(HearingAidProfile.DeviceSide.SIDE_LEFT);
        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, left only");

        // Set Hearing Aid profile to be disconnected and test connection state summary
        mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEARING_AID);
@@ -390,17 +394,36 @@ public class CachedBluetoothDeviceTest {
    }

    @Test
    public void getConnectionSummary_testHearingAidInCall_returnActive() {
    public void getConnectionSummary_testHearingAidRightEarInCall_returnActiveRightEar() {
        // Arrange:
        //   1. Profile:       {HEARING_AID, Connected, Active}
        //   1. Profile:       {HEARING_AID, Connected, Active, Right ear}
        //   2. Audio Manager: In Call
        updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
        mCachedDevice.setDeviceSide(HearingAidProfile.DeviceSide.SIDE_RIGHT);
        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
        mAudioManager.setMode(AudioManager.MODE_IN_CALL);

        // Act & Assert:
        //   Get "Active" result without Battery Level.
        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, right only");
    }

    @Test
    public void getConnectionSummary_testHearingAidBothEarInCall_returnActiveBothEar() {
        // Arrange:
        //   1. Profile:       {HEARING_AID, Connected, Active, Both ear}
        //   2. Audio Manager: In Call
        mCachedDevice.setDeviceSide(HearingAidProfile.DeviceSide.SIDE_RIGHT);
        updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
        mSubCachedDevice.setDeviceSide(HearingAidProfile.DeviceSide.SIDE_LEFT);
        updateSubDeviceProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
        mCachedDevice.setSubDevice(mSubCachedDevice);
        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
        mAudioManager.setMode(AudioManager.MODE_IN_CALL);

        // Act & Assert:
        //   Get "Active" result without Battery Level.
        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, left and right");
    }

    @Test
@@ -925,39 +948,41 @@ public class CachedBluetoothDeviceTest {
        mCachedDevice.onProfileStateChanged(profile, status);
    }

    private void updateSubDeviceProfileStatus(LocalBluetoothProfile profile, int status) {
        doReturn(status).when(profile).getConnectionStatus(mSubDevice);
        mSubCachedDevice.onProfileStateChanged(profile, status);
    }

    @Test
    public void getSubDevice_setSubDevice() {
        CachedBluetoothDevice subCachedDevice = new CachedBluetoothDevice(mContext, mProfileManager,
                mSubDevice);
        mCachedDevice.setSubDevice(subCachedDevice);
        mCachedDevice.setSubDevice(mSubCachedDevice);

        assertThat(mCachedDevice.getSubDevice()).isEqualTo(subCachedDevice);
        assertThat(mCachedDevice.getSubDevice()).isEqualTo(mSubCachedDevice);
    }

    @Test
    public void switchSubDeviceContent() {
        CachedBluetoothDevice subCachedDevice = new CachedBluetoothDevice(mContext, mProfileManager,
                mSubDevice);

        mCachedDevice.mRssi = RSSI_1;
        mCachedDevice.mJustDiscovered = JUSTDISCOVERED_1;
        subCachedDevice.mRssi = RSSI_2;
        subCachedDevice.mJustDiscovered = JUSTDISCOVERED_2;
        mCachedDevice.setSubDevice(subCachedDevice);
        mSubCachedDevice.mRssi = RSSI_2;
        mSubCachedDevice.mJustDiscovered = JUSTDISCOVERED_2;
        mCachedDevice.setSubDevice(mSubCachedDevice);

        assertThat(mCachedDevice.mRssi).isEqualTo(RSSI_1);
        assertThat(mCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
        assertThat(mCachedDevice.mDevice).isEqualTo(mDevice);
        assertThat(subCachedDevice.mRssi).isEqualTo(RSSI_2);
        assertThat(subCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
        assertThat(subCachedDevice.mDevice).isEqualTo(mSubDevice);
        assertThat(mSubCachedDevice.mRssi).isEqualTo(RSSI_2);
        assertThat(mSubCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
        assertThat(mSubCachedDevice.mDevice).isEqualTo(mSubDevice);
        mCachedDevice.switchSubDeviceContent();

        assertThat(mCachedDevice.mRssi).isEqualTo(RSSI_2);
        assertThat(mCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
        assertThat(mCachedDevice.mDevice).isEqualTo(mSubDevice);
        assertThat(subCachedDevice.mRssi).isEqualTo(RSSI_1);
        assertThat(subCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
        assertThat(subCachedDevice.mDevice).isEqualTo(mDevice);
        assertThat(mSubCachedDevice.mRssi).isEqualTo(RSSI_1);
        assertThat(mSubCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
        assertThat(mSubCachedDevice.mDevice).isEqualTo(mDevice);
    }

    @Test