summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author jasonwshsu <jasonwshsu@google.com> 2024-05-22 21:28:21 +0800
committer jasonwshsu <jasonwshsu@google.com> 2024-06-06 15:21:11 +0800
commit618e3a3d335628ab5fe57a632b18f68c404bd6d6 (patch)
tree075c0637a56e68cd658f6c94cf76751030fa10d9
parent1e7265081a34c9c67195619cbf379ee41fa5ad63 (diff)
Add Hearing Devices tile status
* Active state when hearing device is currently active. * Inactive state when hearing device have been paired before. Bug: 338520195 Test: atest HearingDevicesDialogManagerTest HearingDevicesTileTest HearingDevicesCheckerTest Flag: EXEMPT bugfix Change-Id: Iba6d1d252afa710474fc7152861c8ff0b39fa168
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesChecker.java108
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java76
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java58
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesCheckerTest.java116
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java48
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java50
6 files changed, 387 insertions, 69 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesChecker.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesChecker.java
new file mode 100644
index 000000000000..2d1cd03aea4d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesChecker.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.hearingaid;
+
+import android.bluetooth.BluetoothDevice;
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+
+import com.android.settingslib.bluetooth.BluetoothUtils;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.systemui.dagger.SysUISingleton;
+
+import javax.inject.Inject;
+
+/**
+ * HearingDevicesChecker provides utility methods to determine the presence and status of
+ * connected hearing aid devices.
+ *
+ * <p>It also filters out devices that are exclusively managed by other applications to avoid
+ * interfering with their operation.
+ */
+@SysUISingleton
+public class HearingDevicesChecker {
+
+ private final Context mContext;
+ private final LocalBluetoothManager mLocalBluetoothManager;
+
+ @Inject
+ public HearingDevicesChecker(
+ Context context,
+ @Nullable LocalBluetoothManager localBluetoothManager) {
+ mContext = context;
+ mLocalBluetoothManager = localBluetoothManager;
+ }
+
+ /**
+ * Checks if any hearing device is already paired.
+ *
+ * <p>It includes {@link BluetoothDevice.BOND_BONDING} and {@link BluetoothDevice.BOND_BONDED}).
+ *
+ * <p>A bonded device means it has been paired, but may not connected now.
+ *
+ * @return {@code true} if any bonded hearing device is found, {@code false} otherwise.
+ */
+ @WorkerThread
+ public boolean isAnyPairedHearingDevice() {
+ if (mLocalBluetoothManager == null) {
+ return false;
+ }
+ if (!mLocalBluetoothManager.getBluetoothAdapter().isEnabled()) {
+ return false;
+ }
+
+ return mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy().stream()
+ .anyMatch(device -> device.isHearingAidDevice()
+ && device.getBondState() != BluetoothDevice.BOND_NONE
+ && !isExclusivelyManagedBluetoothDevice(device));
+ }
+
+ /**
+ * Checks if there are any active hearing device.
+ *
+ * <p>An active device means it is currently connected and streaming media.
+ *
+ * @return {@code true} if any active hearing device is found, {@code false} otherwise.
+ */
+ @WorkerThread
+ public boolean isAnyActiveHearingDevice() {
+ if (mLocalBluetoothManager == null) {
+ return false;
+ }
+ if (!mLocalBluetoothManager.getBluetoothAdapter().isEnabled()) {
+ return false;
+ }
+
+ return mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy().stream()
+ .anyMatch(device -> BluetoothUtils.isActiveMediaDevice(device)
+ && BluetoothUtils.isAvailableHearingDevice(device)
+ && !isExclusivelyManagedBluetoothDevice(device));
+ }
+
+ private boolean isExclusivelyManagedBluetoothDevice(
+ @NonNull CachedBluetoothDevice cachedDevice) {
+ if (com.android.settingslib.flags.Flags.enableHideExclusivelyManagedBluetoothDevice()) {
+ return BluetoothUtils.isExclusivelyManagedBluetoothDevice(mContext,
+ cachedDevice.getDevice());
+ }
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
index 14e5f3422a27..bc4cb45582ff 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
@@ -16,19 +16,24 @@
package com.android.systemui.accessibility.hearingaid;
-import android.bluetooth.BluetoothDevice;
import android.util.Log;
-import androidx.annotation.Nullable;
+import androidx.concurrent.futures.CallbackToFutureAdapter;
import com.android.internal.jank.InteractionJankMonitor;
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.animation.DialogCuj;
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+
import javax.inject.Inject;
/**
@@ -43,16 +48,22 @@ public class HearingDevicesDialogManager {
private SystemUIDialog mDialog;
private final DialogTransitionAnimator mDialogTransitionAnimator;
private final HearingDevicesDialogDelegate.Factory mDialogFactory;
- private final LocalBluetoothManager mLocalBluetoothManager;
+ private final HearingDevicesChecker mDevicesChecker;
+ private final Executor mBackgroundExecutor;
+ private final Executor mMainExecutor;
@Inject
public HearingDevicesDialogManager(
DialogTransitionAnimator dialogTransitionAnimator,
HearingDevicesDialogDelegate.Factory dialogFactory,
- @Nullable LocalBluetoothManager localBluetoothManager) {
+ HearingDevicesChecker devicesChecker,
+ @Background Executor backgroundExecutor,
+ @Main Executor mainExecutor) {
mDialogTransitionAnimator = dialogTransitionAnimator;
mDialogFactory = dialogFactory;
- mLocalBluetoothManager = localBluetoothManager;
+ mDevicesChecker = devicesChecker;
+ mBackgroundExecutor = backgroundExecutor;
+ mMainExecutor = mainExecutor;
}
/**
@@ -68,36 +79,41 @@ public class HearingDevicesDialogManager {
destroyDialog();
}
- mDialog = mDialogFactory.create(!isAnyBondedHearingDevice()).createDialog();
+ final ListenableFuture<Boolean> pairedHearingDeviceCheckTask =
+ CallbackToFutureAdapter.getFuture(completer -> {
+ mBackgroundExecutor.execute(
+ () -> {
+ completer.set(mDevicesChecker.isAnyPairedHearingDevice());
+ });
+ // This value is used only for debug purposes: it will be used in toString()
+ // of returned future or error cases.
+ return "isAnyPairedHearingDevice check";
+ });
+ pairedHearingDeviceCheckTask.addListener(() -> {
+ try {
+ mDialog = mDialogFactory.create(!pairedHearingDeviceCheckTask.get()).createDialog();
+
+ if (expandable != null) {
+ DialogTransitionAnimator.Controller controller =
+ expandable.dialogTransitionController(
+ new DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+ INTERACTION_JANK_TAG));
+ if (controller != null) {
+ mDialogTransitionAnimator.show(mDialog,
+ controller, /* animateBackgroundBoundsChange= */ true);
+ return;
+ }
+ }
+ mDialog.show();
- if (expandable != null) {
- DialogTransitionAnimator.Controller controller = expandable.dialogTransitionController(
- new DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
- INTERACTION_JANK_TAG));
- if (controller != null) {
- mDialogTransitionAnimator.show(mDialog,
- controller, /* animateBackgroundBoundsChange= */ true);
- return;
+ } catch (InterruptedException | ExecutionException e) {
+ Log.e(TAG, "Exception occurs while running pairedHearingDeviceCheckTask", e);
}
- }
- mDialog.show();
+ }, mMainExecutor);
}
private void destroyDialog() {
mDialog.dismiss();
mDialog = null;
}
-
- private boolean isAnyBondedHearingDevice() {
- if (mLocalBluetoothManager == null) {
- return false;
- }
- if (!mLocalBluetoothManager.getBluetoothAdapter().isEnabled()) {
- return false;
- }
-
- return mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy().stream()
- .anyMatch(device -> device.isHearingAidDevice()
- && device.getBondState() != BluetoothDevice.BOND_NONE);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
index 183c1a4a7ce7..b96e83d43e32 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
@@ -19,34 +19,53 @@ package com.android.systemui.qs.tiles;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
+import android.os.UserManager;
import android.provider.Settings;
+import android.service.quicksettings.Tile;
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Flags;
+import com.android.systemui.accessibility.hearingaid.HearingDevicesChecker;
import com.android.systemui.accessibility.hearingaid.HearingDevicesDialogManager;
import com.android.systemui.animation.Expandable;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QsEventLogger;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.res.R;
+import com.android.systemui.statusbar.policy.BluetoothController;
import javax.inject.Inject;
/** Quick settings tile: Hearing Devices **/
-public class HearingDevicesTile extends QSTileImpl<State> {
-
+public class HearingDevicesTile extends QSTileImpl<BooleanState> {
+ //TODO(b/338520598): Transform the current implementation into new QS architecture
+ // and use Kotlin except Tile class.
public static final String TILE_SPEC = "hearing_devices";
private final HearingDevicesDialogManager mDialogManager;
+ private final HearingDevicesChecker mDevicesChecker;
+ private final BluetoothController mBluetoothController;
+
+ private final BluetoothController.Callback mCallback = new BluetoothController.Callback() {
+ @Override
+ public void onBluetoothStateChange(boolean enabled) {
+ refreshState();
+ }
+
+ @Override
+ public void onBluetoothDevicesChanged() {
+ refreshState();
+ }
+ };
@Inject
public HearingDevicesTile(
@@ -59,16 +78,20 @@ public class HearingDevicesTile extends QSTileImpl<State> {
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
QSLogger qsLogger,
- HearingDevicesDialogManager hearingDevicesDialogManager
- ) {
+ HearingDevicesDialogManager hearingDevicesDialogManager,
+ HearingDevicesChecker hearingDevicesChecker,
+ BluetoothController bluetoothController) {
super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
mDialogManager = hearingDevicesDialogManager;
+ mDevicesChecker = hearingDevicesChecker;
+ mBluetoothController = bluetoothController;
+ mBluetoothController.observe(getLifecycle(), mCallback);
}
@Override
- public State newTileState() {
- return new State();
+ public BooleanState newTileState() {
+ return new BooleanState();
}
@Override
@@ -77,9 +100,28 @@ public class HearingDevicesTile extends QSTileImpl<State> {
}
@Override
- protected void handleUpdateState(State state, Object arg) {
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_BLUETOOTH);
+
state.label = mContext.getString(R.string.quick_settings_hearing_devices_label);
state.icon = ResourceIcon.get(R.drawable.qs_hearing_devices_icon);
+ state.forceExpandIcon = true;
+
+ boolean isBonded = mDevicesChecker.isAnyPairedHearingDevice();
+ boolean isActive = mDevicesChecker.isAnyActiveHearingDevice();
+
+ if (isActive) {
+ state.state = Tile.STATE_ACTIVE;
+ state.secondaryLabel = mContext.getString(
+ R.string.quick_settings_hearing_devices_connected);
+ } else if (isBonded) {
+ state.state = Tile.STATE_INACTIVE;
+ state.secondaryLabel = mContext.getString(
+ R.string.quick_settings_hearing_devices_disconnected);
+ } else {
+ state.state = Tile.STATE_INACTIVE;
+ state.secondaryLabel = "";
+ }
}
@Nullable
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesCheckerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesCheckerTest.java
new file mode 100644
index 000000000000..51f6cdb2cb89
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesCheckerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.hearingaid;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@SmallTest
+public class HearingDevicesCheckerTest extends SysuiTestCase {
+ @Rule
+ public MockitoRule mockito = MockitoJUnit.rule();
+
+ private final List<CachedBluetoothDevice> mCachedDevices = new ArrayList<>();
+ @Mock
+ private LocalBluetoothManager mLocalBluetoothManager;
+ @Mock
+ private LocalBluetoothAdapter mLocalBluetoothAdapter;
+ @Mock
+ private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager;
+ @Mock
+ private CachedBluetoothDevice mCachedDevice;
+ @Mock
+ private BluetoothDevice mDevice;
+ private HearingDevicesChecker mDevicesChecker;
+
+ @Before
+ public void setUp() {
+ when(mLocalBluetoothManager.getBluetoothAdapter()).thenReturn(mLocalBluetoothAdapter);
+ when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(
+ mCachedBluetoothDeviceManager);
+ when(mCachedBluetoothDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
+ when(mCachedDevice.getDevice()).thenReturn(mDevice);
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
+ null);
+
+ mDevicesChecker = new HearingDevicesChecker(mContext, mLocalBluetoothManager);
+ }
+
+ @Test
+ public void isAnyPairedHearingDevice_bluetoothDisable_returnFalse() {
+ when(mLocalBluetoothAdapter.isEnabled()).thenReturn(false);
+
+ assertThat(mDevicesChecker.isAnyPairedHearingDevice()).isFalse();
+ }
+
+ @Test
+ public void isAnyActiveHearingDevice_bluetoothDisable_returnFalse() {
+ when(mLocalBluetoothAdapter.isEnabled()).thenReturn(false);
+
+ assertThat(mDevicesChecker.isAnyActiveHearingDevice()).isFalse();
+ }
+
+ @Test
+ public void isAnyPairedHearingDevice_hearingAidBonded_returnTrue() {
+ when(mLocalBluetoothAdapter.isEnabled()).thenReturn(true);
+ when(mCachedDevice.isHearingAidDevice()).thenReturn(true);
+ when(mCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ mCachedDevices.add(mCachedDevice);
+
+ assertThat(mDevicesChecker.isAnyPairedHearingDevice()).isTrue();
+ }
+
+ @Test
+ public void isAnyActiveHearingDevice_hearingAidActiveAndConnected_returnTrue() {
+ when(mLocalBluetoothAdapter.isEnabled()).thenReturn(true);
+ when(mCachedDevice.isActiveDevice(BluetoothProfile.HEARING_AID)).thenReturn(true);
+ when(mCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice.isConnected()).thenReturn(true);
+ when(mCachedDevice.isConnectedHearingAidDevice()).thenReturn(true);
+ mCachedDevices.add(mCachedDevice);
+
+ assertThat(mDevicesChecker.isAnyActiveHearingDevice()).isTrue();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
index e9c742d63d81..cb9c26c7a4b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
@@ -21,20 +21,17 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.bluetooth.BluetoothDevice;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
-import com.android.settingslib.bluetooth.CachedBluetoothDevice;
-import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
-import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.animation.Expandable;
import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Rule;
@@ -44,9 +41,6 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
-import java.util.ArrayList;
-import java.util.List;
-
/** Tests for {@link HearingDevicesDialogManager}. */
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -56,7 +50,8 @@ public class HearingDevicesDialogManagerTest extends SysuiTestCase {
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
- private final List<CachedBluetoothDevice> mCachedDevices = new ArrayList<>();
+ private final FakeExecutor mMainExecutor = new FakeExecutor(new FakeSystemClock());
+ private final FakeExecutor mBackgroundExecutor = new FakeExecutor(new FakeSystemClock());
@Mock
private Expandable mExpandable;
@Mock
@@ -68,13 +63,7 @@ public class HearingDevicesDialogManagerTest extends SysuiTestCase {
@Mock
private SystemUIDialog mDialog;
@Mock
- private LocalBluetoothManager mLocalBluetoothManager;
- @Mock
- private LocalBluetoothAdapter mLocalBluetoothAdapter;
- @Mock
- private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager;
- @Mock
- private CachedBluetoothDevice mCachedDevice;
+ private HearingDevicesChecker mDevicesChecker;
private HearingDevicesDialogManager mManager;
@@ -82,36 +71,35 @@ public class HearingDevicesDialogManagerTest extends SysuiTestCase {
public void setUp() {
when(mDialogFactory.create(anyBoolean())).thenReturn(mDialogDelegate);
when(mDialogDelegate.createDialog()).thenReturn(mDialog);
- when(mLocalBluetoothManager.getBluetoothAdapter()).thenReturn(mLocalBluetoothAdapter);
- when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(
- mCachedBluetoothDeviceManager);
- when(mCachedBluetoothDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
mManager = new HearingDevicesDialogManager(
mDialogTransitionAnimator,
mDialogFactory,
- mLocalBluetoothManager
+ mDevicesChecker,
+ mBackgroundExecutor,
+ mMainExecutor
);
}
@Test
- public void showDialog_bluetoothDisable_showPairNewDeviceTrue() {
- when(mLocalBluetoothAdapter.isEnabled()).thenReturn(false);
+ public void showDialog_existHearingDevice_showPairNewDeviceFalse() {
+ when(mDevicesChecker.isAnyPairedHearingDevice()).thenReturn(true);
mManager.showDialog(mExpandable);
+ mBackgroundExecutor.runAllReady();
+ mMainExecutor.runAllReady();
- verify(mDialogFactory).create(eq(true));
+ verify(mDialogFactory).create(eq(/* showPairNewDevice= */ false));
}
@Test
- public void showDialog_containsHearingAid_showPairNewDeviceFalse() {
- when(mLocalBluetoothAdapter.isEnabled()).thenReturn(true);
- when(mCachedDevice.isHearingAidDevice()).thenReturn(true);
- when(mCachedDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
- mCachedDevices.add(mCachedDevice);
+ public void showDialog_noHearingDevice_showPairNewDeviceTrue() {
+ when(mDevicesChecker.isAnyPairedHearingDevice()).thenReturn(false);
mManager.showDialog(mExpandable);
+ mBackgroundExecutor.runAllReady();
+ mMainExecutor.runAllReady();
- verify(mDialogFactory).create(eq(false));
+ verify(mDialogFactory).create(eq(/* showPairNewDevice= */ true));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
index 59ee0b843043..76c8cf081262 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
@@ -28,6 +28,7 @@ import android.os.Handler;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.provider.Settings;
+import android.service.quicksettings.Tile;
import android.testing.TestableLooper;
import android.view.View;
@@ -37,14 +38,18 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.accessibility.hearingaid.HearingDevicesChecker;
import com.android.systemui.accessibility.hearingaid.HearingDevicesDialogManager;
import com.android.systemui.animation.Expandable;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QsEventLogger;
import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.res.R;
+import com.android.systemui.statusbar.policy.BluetoothController;
import org.junit.After;
import org.junit.Before;
@@ -78,7 +83,11 @@ public class HearingDevicesTileTest extends SysuiTestCase {
@Mock
private QSLogger mQSLogger;
@Mock
+ private HearingDevicesChecker mDevicesChecker;
+ @Mock
HearingDevicesDialogManager mHearingDevicesDialogManager;
+ @Mock
+ BluetoothController mBluetoothController;
private TestableLooper mTestableLooper;
private HearingDevicesTile mTile;
@@ -98,7 +107,9 @@ public class HearingDevicesTileTest extends SysuiTestCase {
mStatusBarStateController,
mActivityStarter,
mQSLogger,
- mHearingDevicesDialogManager);
+ mHearingDevicesDialogManager,
+ mDevicesChecker,
+ mBluetoothController);
mTile.initialize();
mTestableLooper.processAllMessages();
@@ -142,4 +153,41 @@ public class HearingDevicesTileTest extends SysuiTestCase {
verify(mHearingDevicesDialogManager).showDialog(expandable);
}
+
+ @Test
+ public void handleUpdateState_activeHearingDevice_stateActiveConnectedLabel() {
+ when(mDevicesChecker.isAnyActiveHearingDevice()).thenReturn(true);
+ when(mDevicesChecker.isAnyPairedHearingDevice()).thenReturn(true);
+
+ BooleanState activeState = new BooleanState();
+ mTile.handleUpdateState(activeState, null);
+
+ assertThat(activeState.state).isEqualTo(Tile.STATE_ACTIVE);
+ assertThat(activeState.secondaryLabel.toString()).isEqualTo(
+ mContext.getString(R.string.quick_settings_hearing_devices_connected));
+ }
+
+ @Test
+ public void handleUpdateState_bondedInactiveHearingDevice_stateInactiveDisconnectedLabel() {
+ when(mDevicesChecker.isAnyActiveHearingDevice()).thenReturn(false);
+ when(mDevicesChecker.isAnyPairedHearingDevice()).thenReturn(true);
+
+ BooleanState disconnectedState = new BooleanState();
+ mTile.handleUpdateState(disconnectedState, null);
+
+ assertThat(disconnectedState.state).isEqualTo(Tile.STATE_INACTIVE);
+ assertThat(disconnectedState.secondaryLabel.toString()).isEqualTo(
+ mContext.getString(R.string.quick_settings_hearing_devices_disconnected));
+ }
+
+ @Test
+ public void handleUpdateState_noHearingDevice_stateInactive() {
+ when(mDevicesChecker.isAnyActiveHearingDevice()).thenReturn(false);
+ when(mDevicesChecker.isAnyPairedHearingDevice()).thenReturn(false);
+
+ BooleanState inactiveState = new BooleanState();
+ mTile.handleUpdateState(inactiveState, null);
+
+ assertThat(inactiveState.state).isEqualTo(Tile.STATE_INACTIVE);
+ }
}