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

Commit 3ffe3a46 authored by Jason Hsu's avatar Jason Hsu Committed by Automerger Merge Worker
Browse files

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

parents ef9df054 e5620036
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