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 05e1d3f0e126b..f79c3d27b2ec6 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java @@ -30,13 +30,21 @@ import static com.android.systemui.accessibility.floatingmenu.MenuViewAppearance import android.annotation.FloatRange; import android.annotation.IntDef; +import android.content.ComponentCallbacks; import android.content.Context; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; import android.database.ContentObserver; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; +import android.util.Log; +import android.view.accessibility.AccessibilityManager; + +import androidx.annotation.NonNull; import com.android.internal.accessibility.dialog.AccessibilityTarget; import com.android.internal.annotations.VisibleForTesting; @@ -50,6 +58,9 @@ import java.util.List; * Stores and observe the settings contents for the menu view. */ class MenuInfoRepository { + private static final String TAG = "MenuInfoRepository"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG) || Build.IS_DEBUGGABLE; + @FloatRange(from = 0.0, to = 1.0) private static final float DEFAULT_MENU_POSITION_X_PERCENT = 1.0f; @@ -60,6 +71,10 @@ class MenuInfoRepository { private static final int DEFAULT_MIGRATION_TOOLTIP_VALUE_PROMPT = MigrationPrompt.DISABLED; private final Context mContext; + private final Configuration mConfiguration; + private final AccessibilityManager mAccessibilityManager; + private final AccessibilityManager.AccessibilityServicesStateChangeListener + mA11yServicesStateChangeListener = manager -> onTargetFeaturesChanged(); private final Handler mHandler = new Handler(Looper.getMainLooper()); private final OnSettingsContentsChanged mSettingsContentsCallback; private Position mPercentagePosition; @@ -74,12 +89,12 @@ class MenuInfoRepository { int ENABLED = 1; } - private final ContentObserver mMenuTargetFeaturesContentObserver = + @VisibleForTesting + final ContentObserver mMenuTargetFeaturesContentObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { - mSettingsContentsCallback.onTargetFeaturesChanged( - getTargets(mContext, ACCESSIBILITY_BUTTON)); + onTargetFeaturesChanged(); } }; @@ -102,8 +117,35 @@ class MenuInfoRepository { } }; - MenuInfoRepository(Context context, OnSettingsContentsChanged settingsContentsChanged) { + @VisibleForTesting + final ComponentCallbacks mComponentCallbacks = new ComponentCallbacks() { + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) { + final int diff = newConfig.diff(mConfiguration); + + if (DEBUG) { + Log.d(TAG, "onConfigurationChanged = " + Configuration.configurationDiffToString( + diff)); + } + + if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) { + onTargetFeaturesChanged(); + } + + mConfiguration.setTo(newConfig); + } + + @Override + public void onLowMemory() { + // Do nothing. + } + }; + + MenuInfoRepository(Context context, AccessibilityManager accessibilityManager, + OnSettingsContentsChanged settingsContentsChanged) { mContext = context; + mAccessibilityManager = accessibilityManager; + mConfiguration = new Configuration(context.getResources().getConfiguration()); mSettingsContentsCallback = settingsContentsChanged; mPercentagePosition = getStartPosition(); @@ -172,6 +214,11 @@ class MenuInfoRepository { UserHandle.USER_CURRENT); } + private void onTargetFeaturesChanged() { + mSettingsContentsCallback.onTargetFeaturesChanged( + getTargets(mContext, ACCESSIBILITY_BUTTON)); + } + private Position getStartPosition() { final String absolutePositionString = Prefs.getString(mContext, Prefs.Key.ACCESSIBILITY_FLOATING_MENU_POSITION, /* defaultValue= */ null); @@ -181,7 +228,7 @@ class MenuInfoRepository { : Position.fromString(absolutePositionString); } - void registerContentObservers() { + void registerObserversAndCallbacks() { mContext.getContentResolver().registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS), /* notifyForDescendants */ false, mMenuTargetFeaturesContentObserver, @@ -202,12 +249,20 @@ class MenuInfoRepository { Settings.Secure.getUriFor(ACCESSIBILITY_FLOATING_MENU_OPACITY), /* notifyForDescendants */ false, mMenuFadeOutContentObserver, UserHandle.USER_CURRENT); + mContext.registerComponentCallbacks(mComponentCallbacks); + + mAccessibilityManager.addAccessibilityServicesStateChangeListener( + mA11yServicesStateChangeListener); } - void unregisterContentObservers() { + void unregisterObserversAndCallbacks() { mContext.getContentResolver().unregisterContentObserver(mMenuTargetFeaturesContentObserver); mContext.getContentResolver().unregisterContentObserver(mMenuSizeContentObserver); mContext.getContentResolver().unregisterContentObserver(mMenuFadeOutContentObserver); + mContext.unregisterComponentCallbacks(mComponentCallbacks); + + mAccessibilityManager.removeAccessibilityServicesStateChangeListener( + mA11yServicesStateChangeListener); } interface OnSettingsContentsChanged { 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 986aa51ecce1a..a36a3e2af2d4f 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuView.java @@ -299,7 +299,7 @@ class MenuView extends FrameLayout implements mMenuViewModel.getSizeTypeData().observeForever(mSizeTypeObserver); mMenuViewModel.getMoveToTuckedData().observeForever(mMoveToTuckedObserver); setVisibility(VISIBLE); - mMenuViewModel.registerContentObservers(); + mMenuViewModel.registerObserversAndCallbacks(); getViewTreeObserver().addOnComputeInternalInsetsListener(this); getViewTreeObserver().addOnDrawListener(mSystemGestureExcludeUpdater); } @@ -312,7 +312,7 @@ class MenuView extends FrameLayout implements mMenuViewModel.getTargetFeaturesData().removeObserver(mTargetFeaturesObserver); mMenuViewModel.getSizeTypeData().removeObserver(mSizeTypeObserver); mMenuViewModel.getMoveToTuckedData().removeObserver(mMoveToTuckedObserver); - mMenuViewModel.unregisterContentObservers(); + mMenuViewModel.unregisterObserversAndCallbacks(); getViewTreeObserver().removeOnComputeInternalInsetsListener(this); getViewTreeObserver().removeOnDrawListener(mSystemGestureExcludeUpdater); } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java index 9e22451f62683..08ab6f96cdbcd 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java @@ -156,7 +156,7 @@ class MenuViewLayer extends FrameLayout implements mAccessibilityManager = accessibilityManager; mFloatingMenu = floatingMenu; - mMenuViewModel = new MenuViewModel(context); + mMenuViewModel = new MenuViewModel(context, accessibilityManager); mMenuViewAppearance = new MenuViewAppearance(context, windowManager); mMenuView = new MenuView(context, mMenuViewModel, mMenuViewAppearance); mMenuAnimationController = mMenuView.getMenuAnimationController(); 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 5fea3b0ba2f98..eec84672f17cd 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java @@ -17,6 +17,7 @@ package com.android.systemui.accessibility.floatingmenu; import android.content.Context; +import android.view.accessibility.AccessibilityManager; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; @@ -41,8 +42,9 @@ class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged { private final MutableLiveData mPercentagePositionData = new MutableLiveData<>(); private final MenuInfoRepository mInfoRepository; - MenuViewModel(Context context) { - mInfoRepository = new MenuInfoRepository(context, /* settingsContentsChanged= */ this); + MenuViewModel(Context context, AccessibilityManager accessibilityManager) { + mInfoRepository = new MenuInfoRepository(context, + accessibilityManager, /* settingsContentsChanged= */ this); } @Override @@ -111,11 +113,11 @@ class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged { return mTargetFeaturesData; } - void registerContentObservers() { - mInfoRepository.registerContentObservers(); + void registerObserversAndCallbacks() { + mInfoRepository.registerObserversAndCallbacks(); } - void unregisterContentObservers() { - mInfoRepository.unregisterContentObservers(); + void unregisterObserversAndCallbacks() { + mInfoRepository.unregisterObserversAndCallbacks(); } } \ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DismissAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DismissAnimationControllerTest.java index a36105e11514b..a4b9b0849457c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DismissAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DismissAnimationControllerTest.java @@ -22,6 +22,7 @@ import static org.mockito.Mockito.verify; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.WindowManager; +import android.view.accessibility.AccessibilityManager; import androidx.test.filters.SmallTest; @@ -29,8 +30,12 @@ import com.android.systemui.SysuiTestCase; import com.android.wm.shell.bubbles.DismissView; 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; /** Tests for {@link DismissAnimationController}. */ @SmallTest @@ -40,10 +45,16 @@ public class DismissAnimationControllerTest extends SysuiTestCase { private DismissAnimationController mDismissAnimationController; private DismissView mDismissView; + @Rule + public MockitoRule mockito = MockitoJUnit.rule(); + + @Mock + private AccessibilityManager mAccessibilityManager; + @Before public void setUp() throws Exception { final WindowManager stubWindowManager = mContext.getSystemService(WindowManager.class); - final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext); + final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager); final MenuViewAppearance stubMenuViewAppearance = new MenuViewAppearance(mContext, stubWindowManager); final MenuView stubMenuView = new MenuView(mContext, stubMenuViewModel, 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 0cdd6e2ce85e7..7356184d4879e 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 @@ -31,6 +31,7 @@ import android.testing.TestableLooper; import android.view.View; import android.view.ViewPropertyAnimator; import android.view.WindowManager; +import android.view.accessibility.AccessibilityManager; import androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.FlingAnimation; @@ -43,9 +44,13 @@ import com.android.systemui.SysuiTestCase; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.Optional; @@ -61,12 +66,18 @@ public class MenuAnimationControllerTest extends SysuiTestCase { private MenuView mMenuView; private TestMenuAnimationController mMenuAnimationController; + @Rule + public MockitoRule mockito = MockitoJUnit.rule(); + + @Mock + private AccessibilityManager mAccessibilityManager; + @Before public void setUp() throws Exception { final WindowManager stubWindowManager = mContext.getSystemService(WindowManager.class); final MenuViewAppearance stubMenuViewAppearance = new MenuViewAppearance(mContext, stubWindowManager); - final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext); + final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager); mMenuView = spy(new MenuView(mContext, stubMenuViewModel, stubMenuViewAppearance)); mViewPropertyAnimator = spy(mMenuView.animate()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java index e62a3295a7e27..06340afb48920 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java @@ -16,16 +16,23 @@ package com.android.systemui.accessibility.floatingmenu; +import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; + import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; +import android.content.Context; +import android.content.res.Configuration; import android.testing.AndroidTestingRunner; +import android.view.accessibility.AccessibilityManager; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -34,6 +41,10 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + /** Tests for {@link MenuInfoRepository}. */ @RunWith(AndroidTestingRunner.class) @SmallTest @@ -41,14 +52,29 @@ public class MenuInfoRepositoryTest extends SysuiTestCase { @Rule public MockitoRule mockito = MockitoJUnit.rule(); + @Mock + private AccessibilityManager mAccessibilityManager; + @Mock private MenuInfoRepository.OnSettingsContentsChanged mMockSettingsContentsChanged; private MenuInfoRepository mMenuInfoRepository; + private final List mShortcutTargets = new ArrayList<>(); @Before public void setUp() { - mMenuInfoRepository = new MenuInfoRepository(mContext, mMockSettingsContentsChanged); + mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager); + mShortcutTargets.add(MAGNIFICATION_CONTROLLER_NAME); + doReturn(mShortcutTargets).when(mAccessibilityManager).getAccessibilityShortcutTargets( + anyInt()); + + mMenuInfoRepository = new MenuInfoRepository(mContext, mAccessibilityManager, + mMockSettingsContentsChanged); + } + + @After + public void tearDown() { + mShortcutTargets.clear(); } @Test @@ -64,4 +90,14 @@ public class MenuInfoRepositoryTest extends SysuiTestCase { verify(mMockSettingsContentsChanged).onFadeEffectInfoChanged(any(MenuFadeEffectInfo.class)); } + + @Test + public void localeChange_verifyTargetFeaturesChanged() { + final Configuration configuration = new Configuration(); + configuration.setLocale(Locale.TAIWAN); + + mMenuInfoRepository.mComponentCallbacks.onConfigurationChanged(configuration); + + verify(mMockSettingsContentsChanged).onTargetFeaturesChanged(any()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java index 78ee627a9a2f4..f17b1cfe3c88c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java @@ -29,6 +29,7 @@ import android.graphics.Rect; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.WindowManager; +import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; @@ -55,6 +56,9 @@ public class MenuItemAccessibilityDelegateTest extends SysuiTestCase { @Rule public MockitoRule mockito = MockitoJUnit.rule(); + @Mock + private AccessibilityManager mAccessibilityManager; + @Mock private DismissAnimationController.DismissCallback mStubDismissCallback; @@ -69,7 +73,7 @@ public class MenuItemAccessibilityDelegateTest extends SysuiTestCase { final WindowManager stubWindowManager = mContext.getSystemService(WindowManager.class); final MenuViewAppearance stubMenuViewAppearance = new MenuViewAppearance(mContext, stubWindowManager); - final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext); + final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager); final int halfScreenHeight = stubWindowManager.getCurrentWindowMetrics().getBounds().height() / 2; diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java index d29ebb86686f5..ed9562d838723 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java @@ -31,6 +31,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.MotionEvent; import android.view.WindowManager; +import android.view.accessibility.AccessibilityManager; import androidx.recyclerview.widget.RecyclerView; import androidx.test.filters.SmallTest; @@ -42,8 +43,12 @@ import com.android.wm.shell.bubbles.DismissView; import org.junit.After; 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.Collections; @@ -64,10 +69,16 @@ public class MenuListViewTouchHandlerTest extends SysuiTestCase { private RecyclerView mStubListView; private DismissView mDismissView; + @Rule + public MockitoRule mockito = MockitoJUnit.rule(); + + @Mock + private AccessibilityManager mAccessibilityManager; + @Before public void setUp() throws Exception { final WindowManager windowManager = mContext.getSystemService(WindowManager.class); - final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext); + final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager); final MenuViewAppearance stubMenuViewAppearance = new MenuViewAppearance(mContext, windowManager); mStubMenuView = new MenuView(mContext, stubMenuViewModel, stubMenuViewAppearance); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java index 742ee53e99b6e..5a1a6db927424 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java @@ -29,6 +29,7 @@ import android.graphics.drawable.GradientDrawable; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.WindowManager; +import android.view.accessibility.AccessibilityManager; import androidx.test.filters.SmallTest; @@ -37,8 +38,12 @@ import com.android.systemui.SysuiTestCase; import org.junit.After; 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; /** Tests for {@link MenuView}. */ @RunWith(AndroidTestingRunner.class) @@ -52,12 +57,18 @@ public class MenuViewTest extends SysuiTestCase { private String mLastPosition; private MenuViewAppearance mStubMenuViewAppearance; + @Rule + public MockitoRule mockito = MockitoJUnit.rule(); + + @Mock + private AccessibilityManager mAccessibilityManager; + @Before public void setUp() throws Exception { mUiModeManager = mContext.getSystemService(UiModeManager.class); mNightMode = mUiModeManager.getNightMode(); mUiModeManager.setNightMode(MODE_NIGHT_YES); - final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext); + final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager); final WindowManager stubWindowManager = mContext.getSystemService(WindowManager.class); mStubMenuViewAppearance = new MenuViewAppearance(mContext, stubWindowManager); mMenuView = spy(new MenuView(mContext, stubMenuViewModel, mStubMenuViewAppearance));