diff options
| author | 2024-12-29 23:08:20 -0800 | |
|---|---|---|
| committer | 2024-12-29 23:08:20 -0800 | |
| commit | 4ca00f8794bb3d689f162594016d0122e5ba9f83 (patch) | |
| tree | ed3778d3406d44fab397ff033b25f053c3e8c364 | |
| parent | d9df442f0bc33b8387cb91e95ffd27cdc80d2bc6 (diff) | |
| parent | c8d744d05d2875420eb229d8dff49dd44e381409 (diff) | |
Merge "[HA Status] Implement hearing devices connection status listener" into main
18 files changed, 302 insertions, 38 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java index 69492d5040db..313013cdcf79 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java @@ -610,6 +610,11 @@ public class CachedBluetoothDeviceManager { return mOngoingSetMemberPair != null && mOngoingSetMemberPair.equals(device); } + @NonNull + public HearingAidDeviceManager getHearingAidDeviceManager() { + return mHearingAidDeviceManager; + } + private void log(String msg) { if (DEBUG) { Log.d(TAG, msg); diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java index 2e9cd30eedc4..b2c279466ee4 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java @@ -17,6 +17,7 @@ package com.android.settingslib.bluetooth; import static android.bluetooth.BluetoothDevice.BOND_BONDED; +import android.annotation.CallbackExecutor; import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHapClient; @@ -44,7 +45,10 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; import java.util.stream.Collectors; /** @@ -59,6 +63,8 @@ public class HearingAidDeviceManager { private final LocalBluetoothManager mBtManager; private final List<CachedBluetoothDevice> mCachedDevices; private final HearingAidAudioRoutingHelper mRoutingHelper; + private static final Map<ConnectionStatusListener, Executor> + mConnectionStatusListeners = new ConcurrentHashMap<>(); @ConnectionStatus private int mDevicesConnectionStatus = ConnectionStatus.NO_DEVICE_BONDED; private boolean mInitialDevicesConnectionStatusUpdate = false; @@ -100,14 +106,60 @@ public class HearingAidDeviceManager { int CONNECTING_OR_DISCONNECTING = 2; int ACTIVE = 3; } + /** + * Interface for connection status listener. + */ + public interface ConnectionStatusListener { + /** + * Callback when hearing devices connection status change. + * + * <p>devices here means singular device or binaural device. + * E.g. One of hearing device is in CONNECTED status and another is in DISCONNECTED, + * it will callback CONNECTED status. + * + * @param status Updated {@link ConnectionStatus} + */ + void onDevicesConnectionStatusChanged(@ConnectionStatus int status); + } + + /** + * Registers a listener to be notified of connection status changes. + * + * @param listener The listener to register. + * @param executor The executor on which the listener's callback will be run. + */ + public void registerConnectionStatusListener( + @NonNull ConnectionStatusListener listener, + @NonNull @CallbackExecutor Executor executor) { + mConnectionStatusListeners.put(listener, executor); + } + + /** + * Unregisters a listener previously registered with + * {@link #registerConnectionStatusListener(ConnectionStatusListener, Executor)}. + * + * @param listener The listener to unregister. + */ + public void unregisterConnectionStatusListener( + @NonNull ConnectionStatusListener listener) { + mConnectionStatusListeners.remove(listener); + } + + private void notifyDevicesConnectionStatusChanged(int status) { + mConnectionStatusListeners.forEach((listener, executor) -> + executor.execute(() -> listener.onDevicesConnectionStatusChanged(status))); + } /** * Updates the connection status of the hearing devices based on the currently bonded * hearing aid devices. */ synchronized void notifyDevicesConnectionStatusChanged() { + final int prevVal = mDevicesConnectionStatus; updateDevicesConnectionStatus(); - // TODO: b/357882387 - notify connection status changes for the callers + if (mDevicesConnectionStatus != prevVal) { + notifyDevicesConnectionStatusChanged(mDevicesConnectionStatus); + } } private void updateDevicesConnectionStatus() { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java index f126eaf06503..21dde1fd9411 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java @@ -114,7 +114,10 @@ public class HearingAidDeviceManagerTest { private BluetoothDevice mDevice1; @Mock private BluetoothDevice mDevice2; - + @Mock + private HearingAidDeviceManager.ConnectionStatusListener mConnectionStatusListener; + @Mock + private HearingAidDeviceManager.ConnectionStatusListener mConnectionStatusListener2; private BluetoothClass createBtClass(int deviceClass) { Parcel p = Parcel.obtain(); @@ -914,6 +917,41 @@ public class HearingAidDeviceManagerTest { ConnectionStatus.NO_DEVICE_BONDED); } + @Test + public void notifyDevicesConnectionStatusChanged_noRegisteredListener_noCallback() { + when(mCachedDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); + when(mCachedDevice1.getProfiles()).thenReturn(List.of(mHapClientProfile, mLeAudioProfile)); + when(mCachedDevice1.isConnected()).thenReturn(true); + mCachedDeviceManager.mCachedDevices.add(mCachedDevice1); + + mHearingAidDeviceManager.registerConnectionStatusListener( + mConnectionStatusListener, mContext.getMainExecutor()); + mHearingAidDeviceManager.unregisterConnectionStatusListener( + mConnectionStatusListener); + mHearingAidDeviceManager.notifyDevicesConnectionStatusChanged(); + + verify(mConnectionStatusListener, never()).onDevicesConnectionStatusChanged(anyInt()); + } + + @Test + public void notifyDevicesConnectionStatusChanged_twoRegisteredListener_callbackEachConnected() { + when(mCachedDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); + when(mCachedDevice1.getProfiles()).thenReturn(List.of(mHapClientProfile, mLeAudioProfile)); + when(mCachedDevice1.isConnected()).thenReturn(true); + mCachedDeviceManager.mCachedDevices.add(mCachedDevice1); + + mHearingAidDeviceManager.registerConnectionStatusListener( + mConnectionStatusListener, mContext.getMainExecutor()); + mHearingAidDeviceManager.registerConnectionStatusListener( + mConnectionStatusListener2, mContext.getMainExecutor()); + mHearingAidDeviceManager.notifyDevicesConnectionStatusChanged(); + + verify(mConnectionStatusListener).onDevicesConnectionStatusChanged( + ConnectionStatus.CONNECTED); + verify(mConnectionStatusListener2).onDevicesConnectionStatusChanged( + ConnectionStatus.CONNECTED); + } + private HearingAidInfo getLeftAshaHearingAidInfo(long hiSyncId) { return new HearingAidInfo.Builder() .setAshaDeviceSide(HearingAidInfo.DeviceSide.SIDE_LEFT) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationControllerTest.java index 80de087971c5..266591028efb 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/DragToInteractAnimationControllerTest.java @@ -29,6 +29,7 @@ import android.view.accessibility.AccessibilityManager; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.accessibility.utils.TestUtils; @@ -58,13 +59,15 @@ public class DragToInteractAnimationControllerTest extends SysuiTestCase { @Mock private AccessibilityManager mAccessibilityManager; + @Mock + private HearingAidDeviceManager mHearingAidDeviceManager; @Before public void setUp() throws Exception { final WindowManager stubWindowManager = mContext.getSystemService(WindowManager.class); final SecureSettings mockSecureSettings = TestUtils.mockSecureSettings(); final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager, - mockSecureSettings); + mockSecureSettings, mHearingAidDeviceManager); final MenuViewAppearance stubMenuViewAppearance = new MenuViewAppearance(mContext, stubWindowManager); final MenuView stubMenuView = spy(new MenuView(mContext, stubMenuViewModel, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java index 24f3a29e64ee..785493faf957 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java @@ -16,6 +16,7 @@ package com.android.systemui.accessibility.floatingmenu; +import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME; import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; import static org.mockito.ArgumentMatchers.anyInt; @@ -25,11 +26,13 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.content.res.Configuration; +import android.platform.test.annotations.EnableFlags; import android.view.accessibility.AccessibilityManager; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.SysuiTestCase; import com.android.systemui.util.settings.SecureSettings; @@ -45,6 +48,7 @@ import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.concurrent.Executor; /** Tests for {@link MenuInfoRepository}. */ @RunWith(AndroidJUnit4.class) @@ -55,9 +59,10 @@ public class MenuInfoRepositoryTest extends SysuiTestCase { @Mock private AccessibilityManager mAccessibilityManager; - @Mock - private MenuInfoRepository.OnSettingsContentsChanged mMockSettingsContentsChanged; + private HearingAidDeviceManager mHearingAidDeviceManager; + @Mock + private MenuInfoRepository.OnContentsChanged mMockSettingsContentsChanged; @Mock private SecureSettings mSecureSettings; @@ -72,7 +77,7 @@ public class MenuInfoRepositoryTest extends SysuiTestCase { anyInt()); mMenuInfoRepository = new MenuInfoRepository(mContext, mAccessibilityManager, - mMockSettingsContentsChanged, mSecureSettings); + mMockSettingsContentsChanged, mSecureSettings, mHearingAidDeviceManager); } @After @@ -103,4 +108,16 @@ public class MenuInfoRepositoryTest extends SysuiTestCase { verify(mMockSettingsContentsChanged).onTargetFeaturesChanged(any()); } + + @Test + @EnableFlags( + com.android.settingslib.flags.Flags.FLAG_HEARING_DEVICE_SET_CONNECTION_STATUS_REPORT) + public void registerObservers_addHearingDeviceTarget_verifyRegisterConnectionStatusListener() { + mShortcutTargets.add(ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.flattenToString()); + mMenuInfoRepository.registerObserversAndCallbacks(); + + verify(mHearingAidDeviceManager).registerConnectionStatusListener( + any(HearingAidDeviceManager.ConnectionStatusListener.class), any( + Executor.class)); + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java index 157cccc3d62f..241da5fbc444 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java @@ -41,6 +41,7 @@ import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.accessibility.utils.TestUtils; @@ -68,6 +69,8 @@ public class MenuItemAccessibilityDelegateTest extends SysuiTestCase { @Mock private AccessibilityManager mAccessibilityManager; + @Mock + private HearingAidDeviceManager mHearingAidDeviceManager; private final SecureSettings mSecureSettings = TestUtils.mockSecureSettings(); private RecyclerView mStubListView; private MenuView mMenuView; @@ -84,7 +87,7 @@ public class MenuItemAccessibilityDelegateTest extends SysuiTestCase { final MenuViewAppearance stubMenuViewAppearance = new MenuViewAppearance(mContext, stubWindowManager); final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager, - mSecureSettings); + mSecureSettings, mHearingAidDeviceManager); final int halfScreenHeight = stubWindowManager.getCurrentWindowMetrics().getBounds().height() / 2; diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java index 46f076a75116..fbd8a713a249 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java @@ -41,6 +41,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.accessibility.dialog.AccessibilityTarget; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.accessibility.MotionEventHelper; @@ -82,13 +83,15 @@ public class MenuListViewTouchHandlerTest extends SysuiTestCase { @Mock private AccessibilityManager mAccessibilityManager; + @Mock + private HearingAidDeviceManager mHearingAidDeviceManager; @Before public void setUp() throws Exception { final WindowManager windowManager = mContext.getSystemService(WindowManager.class); final SecureSettings secureSettings = TestUtils.mockSecureSettings(); final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager, - secureSettings); + secureSettings, mHearingAidDeviceManager); final MenuViewAppearance stubMenuViewAppearance = new MenuViewAppearance(mContext, windowManager); mStubMenuView = new MenuView(mContext, stubMenuViewModel, stubMenuViewAppearance, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java index fcdeff9ab683..4f043109a534 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java @@ -41,6 +41,7 @@ import androidx.test.filters.SmallTest; import com.android.app.viewcapture.ViewCapture; import com.android.app.viewcapture.ViewCaptureAwareWindowManager; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.SysuiTestCase; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.util.settings.SecureSettings; @@ -68,6 +69,8 @@ public class MenuViewLayerControllerTest extends SysuiTestCase { @Mock private AccessibilityManager mAccessibilityManager; + @Mock + private HearingAidDeviceManager mHearingAidDeviceManager; @Mock private SecureSettings mSecureSettings; @@ -93,7 +96,7 @@ public class MenuViewLayerControllerTest extends SysuiTestCase { when(mWindowMetrics.getWindowInsets()).thenReturn(stubDisplayInsets()); mMenuViewLayerController = new MenuViewLayerController(mContext, mWindowManager, viewCaptureAwareWm, mAccessibilityManager, mSecureSettings, - mock(NavigationModeController.class)); + mock(NavigationModeController.class), mHearingAidDeviceManager); } @Test diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java index ee8ce17cecd4..cb7c205742fc 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java @@ -37,6 +37,7 @@ import android.view.accessibility.AccessibilityManager; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.Flags; import com.android.systemui.Prefs; import com.android.systemui.SysuiTestCase; @@ -70,6 +71,8 @@ public class MenuViewTest extends SysuiTestCase { @Mock private AccessibilityManager mAccessibilityManager; + @Mock + private HearingAidDeviceManager mHearingAidDeviceManager; private SysuiTestableContext mSpyContext; @@ -90,7 +93,7 @@ public class MenuViewTest extends SysuiTestCase { final SecureSettings secureSettings = TestUtils.mockSecureSettings(); final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager, - secureSettings); + secureSettings, mHearingAidDeviceManager); final WindowManager stubWindowManager = mContext.getSystemService(WindowManager.class); mStubMenuViewAppearance = new MenuViewAppearance(mSpyContext, stubWindowManager); mMenuView = spy(new MenuView(mSpyContext, stubMenuViewModel, mStubMenuViewAppearance, diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java index 41b9d3372392..5f0acfa644dc 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java @@ -19,6 +19,7 @@ package com.android.systemui.accessibility.floatingmenu; import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; +import android.annotation.Nullable; import android.content.Context; import android.hardware.display.DisplayManager; import android.os.Handler; @@ -35,6 +36,7 @@ import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.internal.annotations.VisibleForTesting; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.accessibility.AccessibilityButtonModeObserver; import com.android.systemui.accessibility.AccessibilityButtonModeObserver.AccessibilityButtonMode; import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver; @@ -61,6 +63,7 @@ public class AccessibilityFloatingMenuController implements private final ViewCaptureAwareWindowManager mViewCaptureAwareWindowManager; private final DisplayManager mDisplayManager; private final AccessibilityManager mAccessibilityManager; + private final HearingAidDeviceManager mHearingAidDeviceManager; private final SecureSettings mSecureSettings; private final DisplayTracker mDisplayTracker; @@ -107,6 +110,7 @@ public class AccessibilityFloatingMenuController implements AccessibilityManager accessibilityManager, AccessibilityButtonTargetsObserver accessibilityButtonTargetsObserver, AccessibilityButtonModeObserver accessibilityButtonModeObserver, + @Nullable HearingAidDeviceManager hearingAidDeviceManager, KeyguardUpdateMonitor keyguardUpdateMonitor, SecureSettings secureSettings, DisplayTracker displayTracker, @@ -119,6 +123,7 @@ public class AccessibilityFloatingMenuController implements mAccessibilityManager = accessibilityManager; mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver; mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; + mHearingAidDeviceManager = hearingAidDeviceManager; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mSecureSettings = secureSettings; mDisplayTracker = displayTracker; @@ -201,7 +206,7 @@ public class AccessibilityFloatingMenuController implements TYPE_NAVIGATION_BAR_PANEL, /* options= */ null); mFloatingMenu = new MenuViewLayerController(windowContext, mWindowManager, mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings, - mNavigationModeController); + mNavigationModeController, mHearingAidDeviceManager); } mFloatingMenu.show(); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java index ffb5f3d47bcc..121b51f768e7 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java @@ -30,6 +30,7 @@ import static com.android.systemui.accessibility.floatingmenu.MenuViewAppearance import android.annotation.FloatRange; import android.annotation.IntDef; +import android.annotation.Nullable; import android.content.ComponentCallbacks; import android.content.Context; import android.content.pm.ActivityInfo; @@ -49,6 +50,8 @@ import androidx.annotation.NonNull; import com.android.internal.accessibility.dialog.AccessibilityTarget; import com.android.internal.annotations.VisibleForTesting; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; +import com.android.settingslib.utils.ThreadUtils; import com.android.systemui.Prefs; import com.android.systemui.util.settings.SecureSettings; @@ -80,8 +83,11 @@ class MenuInfoRepository { private final AccessibilityManager mAccessibilityManager; private final AccessibilityManager.AccessibilityServicesStateChangeListener mA11yServicesStateChangeListener = manager -> onTargetFeaturesChanged(); + private final HearingAidDeviceManager mHearingAidDeviceManager; + private final HearingAidDeviceManager.ConnectionStatusListener + mHearingDeviceStatusListener = this::onDevicesConnectionStatusChanged; private final Handler mHandler = new Handler(Looper.getMainLooper()); - private final OnSettingsContentsChanged mSettingsContentsCallback; + private final OnContentsChanged mSettingsContentsCallback; private final SecureSettings mSecureSettings; private Position mPercentagePosition; @@ -148,12 +154,14 @@ class MenuInfoRepository { }; MenuInfoRepository(Context context, AccessibilityManager accessibilityManager, - OnSettingsContentsChanged settingsContentsChanged, SecureSettings secureSettings) { + OnContentsChanged settingsContentsChanged, SecureSettings secureSettings, + @Nullable HearingAidDeviceManager hearingAidDeviceManager) { mContext = context; mAccessibilityManager = accessibilityManager; mConfiguration = new Configuration(context.getResources().getConfiguration()); mSettingsContentsCallback = settingsContentsChanged; mSecureSettings = secureSettings; + mHearingAidDeviceManager = hearingAidDeviceManager; mPercentagePosition = getStartPosition(); } @@ -185,6 +193,14 @@ class MenuInfoRepository { callback.onReady(getTargets(mContext, SOFTWARE)); } + void loadHearingDeviceStatus(OnInfoReady<Integer> callback) { + if (mHearingAidDeviceManager != null) { + callback.onReady(mHearingAidDeviceManager.getDevicesConnectionStatus()); + } else { + callback.onReady(HearingAidDeviceManager.ConnectionStatus.NO_DEVICE_BONDED); + } + } + void loadMenuSizeType(OnInfoReady<Integer> callback) { callback.onReady(getMenuSizeTypeFromSettings()); } @@ -222,8 +238,8 @@ class MenuInfoRepository { } private void onTargetFeaturesChanged() { - mSettingsContentsCallback.onTargetFeaturesChanged( - getTargets(mContext, SOFTWARE)); + List<AccessibilityTarget> targets = getTargets(mContext, SOFTWARE); + mSettingsContentsCallback.onTargetFeaturesChanged(targets); } private Position getStartPosition() { @@ -269,6 +285,24 @@ class MenuInfoRepository { mAccessibilityManager.addAccessibilityServicesStateChangeListener( mA11yServicesStateChangeListener); } + + if (com.android.settingslib.flags.Flags.hearingDeviceSetConnectionStatusReport()) { + registerConnectionStatusListener(); + } + } + + private void registerConnectionStatusListener() { + if (mHearingAidDeviceManager != null) { + mHearingAidDeviceManager.registerConnectionStatusListener( + mHearingDeviceStatusListener, ThreadUtils.getBackgroundExecutor()); + } + } + + private void unregisterConnectionStatusListener() { + if (mHearingAidDeviceManager != null) { + mHearingAidDeviceManager.unregisterConnectionStatusListener( + mHearingDeviceStatusListener); + } } void unregisterObserversAndCallbacks() { @@ -281,14 +315,18 @@ class MenuInfoRepository { mAccessibilityManager.removeAccessibilityServicesStateChangeListener( mA11yServicesStateChangeListener); } + + unregisterConnectionStatusListener(); } - interface OnSettingsContentsChanged { + interface OnContentsChanged { void onTargetFeaturesChanged(List<AccessibilityTarget> newTargetFeatures); void onSizeTypeChanged(int newSizeType); void onFadeEffectInfoChanged(MenuFadeEffectInfo fadeEffectInfo); + + void onDevicesConnectionStatusChanged(@HearingAidDeviceManager.ConnectionStatus int status); } interface OnInfoReady<T> { @@ -311,4 +349,9 @@ class MenuInfoRepository { ACCESSIBILITY_FLOATING_MENU_OPACITY, DEFAULT_OPACITY_VALUE, UserHandle.USER_CURRENT); } + + private void onDevicesConnectionStatusChanged( + @HearingAidDeviceManager.ConnectionStatus int status) { + mSettingsContentsCallback.onDevicesConnectionStatusChanged(status); + } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java index 9d9e7dfb7032..23fc546dd9b3 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java @@ -37,6 +37,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.internal.accessibility.dialog.AccessibilityTarget; import com.android.modules.expresslog.Counter; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.Flags; import com.android.systemui.util.settings.SecureSettings; @@ -65,8 +66,11 @@ class MenuView extends FrameLayout implements private final Observer<Integer> mSizeTypeObserver = this::onSizeTypeChanged; private final Observer<List<AccessibilityTarget>> mTargetFeaturesObserver = this::onTargetFeaturesChanged; + private final Observer<Integer> mHearingDeviceStatusObserver = + this::updateHearingDeviceStatus; + private final Observer<Integer> mHearingDeviceTargetIndexObserver = + this::updateHearingDeviceTargetIndex; private final MenuViewAppearance mMenuViewAppearance; - private boolean mIsMoveToTucked; private final MenuAnimationController mMenuAnimationController; @@ -357,6 +361,11 @@ class MenuView extends FrameLayout implements mMenuViewModel.getTargetFeaturesData().observeForever(mTargetFeaturesObserver); mMenuViewModel.getSizeTypeData().observeForever(mSizeTypeObserver); mMenuViewModel.getMoveToTuckedData().observeForever(mMoveToTuckedObserver); + if (com.android.settingslib.flags.Flags.hearingDeviceSetConnectionStatusReport()) { + mMenuViewModel.loadHearingDeviceStatus().observeForever(mHearingDeviceStatusObserver); + mMenuViewModel.getHearingDeviceTargetIndexData().observeForever( + mHearingDeviceTargetIndexObserver); + } setVisibility(VISIBLE); mMenuViewModel.registerObserversAndCallbacks(); getViewTreeObserver().addOnComputeInternalInsetsListener(this); @@ -371,6 +380,9 @@ class MenuView extends FrameLayout implements mMenuViewModel.getTargetFeaturesData().removeObserver(mTargetFeaturesObserver); mMenuViewModel.getSizeTypeData().removeObserver(mSizeTypeObserver); mMenuViewModel.getMoveToTuckedData().removeObserver(mMoveToTuckedObserver); + mMenuViewModel.getHearingDeviceStatusData().removeObserver(mHearingDeviceStatusObserver); + mMenuViewModel.getHearingDeviceTargetIndexData().removeObserver( + mHearingDeviceTargetIndexObserver); mMenuViewModel.unregisterObserversAndCallbacks(); getViewTreeObserver().removeOnComputeInternalInsetsListener(this); getViewTreeObserver().removeOnDrawListener(mSystemGestureExcludeUpdater); @@ -421,6 +433,14 @@ class MenuView extends FrameLayout implements parentView.setSystemGestureExclusionRects(Collections.singletonList(mBoundsInParent)); } + private void updateHearingDeviceStatus(@HearingAidDeviceManager.ConnectionStatus int status) { + // TODO: b/357882387 - To update status drawable according to the status here. + } + + private void updateHearingDeviceTargetIndex(int position) { + // TODO: b/357882387 - To update status drawable according to the status here. + } + /** * Interface definition for the {@link AccessibilityTarget} list changes. */ diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java index cb96e7859fba..184518ac35eb 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java @@ -24,6 +24,7 @@ import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; import com.android.app.viewcapture.ViewCaptureAwareWindowManager; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.util.settings.SecureSettings; @@ -39,11 +40,12 @@ class MenuViewLayerController implements IAccessibilityFloatingMenu { MenuViewLayerController(Context context, WindowManager windowManager, ViewCaptureAwareWindowManager viewCaptureAwareWindowManager, AccessibilityManager accessibilityManager, SecureSettings secureSettings, - NavigationModeController navigationModeController) { + NavigationModeController navigationModeController, + HearingAidDeviceManager hearingAidDeviceManager) { mWindowManager = viewCaptureAwareWindowManager; MenuViewModel menuViewModel = new MenuViewModel( - context, accessibilityManager, secureSettings); + context, accessibilityManager, secureSettings, hearingAidDeviceManager); MenuViewAppearance menuViewAppearance = new MenuViewAppearance(context, windowManager); mMenuViewLayer = new MenuViewLayer(context, windowManager, accessibilityManager, diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java index f924784a5535..8b7d6a18bb85 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java @@ -16,13 +16,20 @@ package com.android.systemui.accessibility.floatingmenu; +import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME; + +import static java.util.Collections.emptyList; + +import android.content.ComponentName; import android.content.Context; import android.view.accessibility.AccessibilityManager; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Transformations; import com.android.internal.accessibility.dialog.AccessibilityTarget; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.util.settings.SecureSettings; import java.util.List; @@ -31,9 +38,9 @@ import java.util.List; * The view model provides the menu information from the repository{@link MenuInfoRepository} for * the menu view{@link MenuView}. */ -class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged { +class MenuViewModel implements MenuInfoRepository.OnContentsChanged { private final MutableLiveData<List<AccessibilityTarget>> mTargetFeaturesData = - new MutableLiveData<>(); + new MutableLiveData<>(emptyList()); private final MutableLiveData<Integer> mSizeTypeData = new MutableLiveData<>(); private final MutableLiveData<MenuFadeEffectInfo> mFadeEffectInfoData = new MutableLiveData<>(); @@ -41,12 +48,18 @@ class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged { private final MutableLiveData<Boolean> mDockTooltipData = new MutableLiveData<>(); private final MutableLiveData<Boolean> mMigrationTooltipData = new MutableLiveData<>(); private final MutableLiveData<Position> mPercentagePositionData = new MutableLiveData<>(); + private final MutableLiveData<Integer> mHearingDeviceStatusData = new MutableLiveData<>( + HearingAidDeviceManager.ConnectionStatus.NO_DEVICE_BONDED); + private final LiveData<Integer> mHearingDeviceTargetIndex = Transformations.map( + mTargetFeaturesData, this::getHearingDeviceTargetIndex); + private final MenuInfoRepository mInfoRepository; MenuViewModel(Context context, AccessibilityManager accessibilityManager, - SecureSettings secureSettings) { + SecureSettings secureSettings, HearingAidDeviceManager hearingAidDeviceManager) { mInfoRepository = new MenuInfoRepository(context, - accessibilityManager, /* settingsContentsChanged= */ this, secureSettings); + accessibilityManager, /* settingsContentsChanged= */ this, secureSettings, + hearingAidDeviceManager); } @Override @@ -64,6 +77,12 @@ class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged { mFadeEffectInfoData.setValue(fadeEffectInfo); } + @Override + public void onDevicesConnectionStatusChanged( + @HearingAidDeviceManager.ConnectionStatus int status) { + mHearingDeviceStatusData.postValue(status); + } + void updateMenuMoveToTucked(boolean isMoveToTucked) { mInfoRepository.updateMoveToTucked(isMoveToTucked); } @@ -115,6 +134,19 @@ class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged { return mTargetFeaturesData; } + LiveData<Integer> loadHearingDeviceStatus() { + mInfoRepository.loadHearingDeviceStatus(mHearingDeviceStatusData::setValue); + return mHearingDeviceStatusData; + } + + LiveData<Integer> getHearingDeviceStatusData() { + return mHearingDeviceStatusData; + } + + LiveData<Integer> getHearingDeviceTargetIndexData() { + return mHearingDeviceTargetIndex; + } + void registerObserversAndCallbacks() { mInfoRepository.registerObserversAndCallbacks(); } @@ -122,4 +154,16 @@ class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged { void unregisterObserversAndCallbacks() { mInfoRepository.unregisterObserversAndCallbacks(); } + + private int getHearingDeviceTargetIndex(List<AccessibilityTarget> targetList) { + final int listSize = targetList.size(); + for (int index = 0; index < listSize; index++) { + AccessibilityTarget target = targetList.get(index); + if (ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.equals( + ComponentName.unflattenFromString(target.getId()))) { + return index; + } + } + return -1; + } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SettingsLibraryModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SettingsLibraryModule.java index 14626e1e6515..e72dfadd620f 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SettingsLibraryModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SettingsLibraryModule.java @@ -22,6 +22,7 @@ import android.content.Context; import android.os.Handler; import android.os.UserHandle; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.systemui.dagger.qualifiers.Background; @@ -41,4 +42,16 @@ public class SettingsLibraryModule { @Background Handler bgHandler) { return LocalBluetoothManager.create(context, bgHandler, UserHandle.ALL); } + + @SuppressLint("MissingPermission") + @SysUISingleton + @Provides + @Nullable + static HearingAidDeviceManager provideHearingAidDeviceManager( + @Nullable LocalBluetoothManager localBluetoothManager) { + if (localBluetoothManager == null) { + return null; + } + return localBluetoothManager.getCachedDeviceManager().getHearingAidDeviceManager(); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java index 51a7b5f6f979..bc9d4c7fa0e6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java @@ -42,6 +42,7 @@ import com.android.app.viewcapture.ViewCapture; import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.Dependency; import com.android.systemui.SysuiTestCase; import com.android.systemui.accessibility.AccessibilityButtonModeObserver; @@ -95,6 +96,8 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase { private Lazy<ViewCapture> mLazyViewCapture; @Mock private NavigationModeController mNavigationModeController; + @Mock + private HearingAidDeviceManager mHearingAidDeviceManager; @Before public void setUp() throws Exception { @@ -170,7 +173,7 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase { mController = setUpController(); mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager, mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings, - mNavigationModeController); + mNavigationModeController, mHearingAidDeviceManager); captureKeyguardUpdateMonitorCallback(); mKeyguardCallback.onUserUnlocked(); @@ -198,7 +201,7 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase { mController = setUpController(); mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager, mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings, - mNavigationModeController); + mNavigationModeController, mHearingAidDeviceManager); captureKeyguardUpdateMonitorCallback(); mKeyguardCallback.onUserSwitching(fakeUserId); @@ -213,7 +216,7 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase { mController = setUpController(); mController.mFloatingMenu = new MenuViewLayerController(mContextWrapper, mWindowManager, mViewCaptureAwareWindowManager, mAccessibilityManager, mSecureSettings, - mNavigationModeController); + mNavigationModeController, mHearingAidDeviceManager); captureKeyguardUpdateMonitorCallback(); mKeyguardCallback.onUserUnlocked(); mKeyguardCallback.onKeyguardVisibilityChanged(true); @@ -368,9 +371,9 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase { final AccessibilityFloatingMenuController controller = new AccessibilityFloatingMenuController(mContextWrapper, windowManager, viewCaptureAwareWindowManager, displayManager, mAccessibilityManager, - mTargetsObserver, mModeObserver, mKeyguardUpdateMonitor, mSecureSettings, - displayTracker, mNavigationModeController, new Handler( - mTestableLooper.getLooper())); + mTargetsObserver, mModeObserver, mHearingAidDeviceManager, + mKeyguardUpdateMonitor, mSecureSettings, displayTracker, + mNavigationModeController, new Handler(mTestableLooper.getLooper())); controller.init(); return controller; diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java index dddaabb66022..856c37934251 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java @@ -26,7 +26,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import android.graphics.PointF; - import android.testing.TestableLooper; import android.view.View; import android.view.ViewPropertyAnimator; @@ -40,6 +39,7 @@ import androidx.dynamicanimation.animation.SpringForce; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.Prefs; import com.android.systemui.SysuiTestCase; import com.android.systemui.accessibility.utils.TestUtils; @@ -74,6 +74,8 @@ public class MenuAnimationControllerTest extends SysuiTestCase { @Mock private AccessibilityManager mAccessibilityManager; + @Mock + private HearingAidDeviceManager mHearingAidDeviceManager; @Before public void setUp() throws Exception { @@ -82,7 +84,7 @@ public class MenuAnimationControllerTest extends SysuiTestCase { stubWindowManager); final SecureSettings secureSettings = TestUtils.mockSecureSettings(); final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager, - secureSettings); + secureSettings, mHearingAidDeviceManager); mMenuView = spy(new MenuView(mContext, stubMenuViewModel, stubMenuViewAppearance, secureSettings)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java index 400b3b388c31..33cfb3890e71 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java @@ -77,6 +77,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.accessibility.common.ShortcutConstants; import com.android.internal.accessibility.dialog.AccessibilityTarget; import com.android.internal.messages.nano.SystemMessageProto; +import com.android.settingslib.bluetooth.HearingAidDeviceManager; import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestableContext; @@ -140,6 +141,8 @@ public class MenuViewLayerTest extends SysuiTestCase { @Mock private AccessibilityManager mStubAccessibilityManager; @Mock + private HearingAidDeviceManager mHearingAidDeviceManager; + @Mock private PackageManager mMockPackageManager; private final SecureSettings mSecureSettings = TestUtils.mockSecureSettings(); @@ -160,7 +163,7 @@ public class MenuViewLayerTest extends SysuiTestCase { doReturn(mWindowMetrics).when(mStubWindowManager).getCurrentWindowMetrics(); mMenuViewModel = new MenuViewModel( - mSpyContext, mStubAccessibilityManager, mSecureSettings); + mSpyContext, mStubAccessibilityManager, mSecureSettings, mHearingAidDeviceManager); MenuViewAppearance menuViewAppearance = new MenuViewAppearance( mSpyContext, mStubWindowManager); mMenuView = spy( @@ -419,9 +422,10 @@ public class MenuViewLayerTest extends SysuiTestCase { @Test @EnableFlags(Flags.FLAG_FLOATING_MENU_DRAG_TO_EDIT) public void onDismissAction_incrementsTexMetricDismiss() { - mMenuViewModel.onTargetFeaturesChanged( - List.of(new TestAccessibilityTarget(mSpyContext, 1234), - new TestAccessibilityTarget(mSpyContext, 5678))); + List<AccessibilityTarget> testTargets = new ArrayList<>(); + testTargets.add(new TestAccessibilityTarget(mSpyContext, 1234)); + testTargets.add(new TestAccessibilityTarget(mSpyContext, 5678)); + mMenuViewModel.onTargetFeaturesChanged(testTargets); mMenuViewLayer.dispatchAccessibilityAction(R.id.action_remove_menu); @@ -431,9 +435,10 @@ public class MenuViewLayerTest extends SysuiTestCase { @Test @EnableFlags(Flags.FLAG_FLOATING_MENU_DRAG_TO_EDIT) public void onEditAction_incrementsTexMetricEdit() { - mMenuViewModel.onTargetFeaturesChanged( - List.of(new TestAccessibilityTarget(mSpyContext, 1234), - new TestAccessibilityTarget(mSpyContext, 5678))); + List<AccessibilityTarget> testTargets = new ArrayList<>(); + testTargets.add(new TestAccessibilityTarget(mSpyContext, 1234)); + testTargets.add(new TestAccessibilityTarget(mSpyContext, 5678)); + mMenuViewModel.onTargetFeaturesChanged(testTargets); mMenuViewLayer.dispatchAccessibilityAction(R.id.action_edit); |