Handle the phone get booted case to show accessibility floating menu

* AccessibilityManager might not ready when the phone just got booted.

Cherry picked from commit bf0ab7163d

Bug: 173940864
Test: atest AccessibilityFloatingMenuControllerTest
Change-Id: I0339597cd53ca5daade427fef257bfddb3b86bd8
Merged-In: I0339597cd53ca5daade427fef257bfddb3b86bd8
This commit is contained in:
jasonwshsu
2021-01-14 21:58:27 +08:00
parent 5154c4cfae
commit e24d701f4c
2 changed files with 75 additions and 3 deletions

View File

@@ -20,6 +20,7 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATIN
import android.content.Context;
import android.text.TextUtils;
import android.view.accessibility.AccessibilityManager;
import androidx.annotation.MainThread;
@@ -36,9 +37,11 @@ import javax.inject.Inject;
@SysUISingleton
public class AccessibilityFloatingMenuController implements
AccessibilityButtonModeObserver.ModeChangedListener,
AccessibilityButtonTargetsObserver.TargetsChangedListener {
AccessibilityButtonTargetsObserver.TargetsChangedListener,
AccessibilityManager.AccessibilityStateChangeListener {
private final Context mContext;
private final AccessibilityManager mAccessibilityManager;
private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
private final AccessibilityButtonTargetsObserver mAccessibilityButtonTargetsObserver;
@@ -54,13 +57,21 @@ public class AccessibilityFloatingMenuController implements
mContext = context;
mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver;
mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
mAccessibilityButtonModeObserver.addListener(this);
mAccessibilityButtonTargetsObserver.addListener(this);
mBtnMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode();
mBtnTargets = mAccessibilityButtonTargetsObserver.getCurrentAccessibilityButtonTargets();
handleFloatingMenuVisibility(mBtnMode, mBtnTargets);
// Accessibility floating menu widget needs accessibility service to work, but system
// accessibility might be unavailable during the phone get booted, hence it needs to wait
// for accessibility manager callback to work.
mAccessibilityManager.addAccessibilityStateChangeListener(this);
if (mAccessibilityManager.isEnabled()) {
handleFloatingMenuVisibility(mBtnMode, mBtnTargets);
mAccessibilityManager.removeAccessibilityStateChangeListener(this);
}
}
/**
@@ -86,6 +97,23 @@ public class AccessibilityFloatingMenuController implements
handleFloatingMenuVisibility(mBtnMode, mBtnTargets);
}
/**
* Handles visibility of the accessibility floating menu when system accessibility state
* changes.
* If system accessibility become available onAccessibilityStateChanged(true), then we don't
* need to listen to this listener anymore.
*
* @param enabled Whether accessibility is enabled.
*/
@Override
public void onAccessibilityStateChanged(boolean enabled) {
if (enabled) {
handleFloatingMenuVisibility(mBtnMode, mBtnTargets);
}
mAccessibilityManager.removeAccessibilityStateChangeListener(this);
}
private void handleFloatingMenuVisibility(@AccessibilityButtonMode int mode, String targets) {
if (shouldShowFloatingMenu(mode, targets)) {
showFloatingMenu();

View File

@@ -24,10 +24,12 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.accessibility.AccessibilityManager;
import androidx.test.filters.SmallTest;
@@ -36,8 +38,12 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
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;
/** Test for {@link AccessibilityFloatingMenuController}. */
@RunWith(AndroidTestingRunner.class)
@@ -47,9 +53,14 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase {
private static final String TEST_A11Y_BTN_TARGETS = "Magnification";
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
private AccessibilityFloatingMenuController mController;
private AccessibilityButtonTargetsObserver mTargetsObserver;
private AccessibilityButtonModeObserver mModeObserver;
@Mock
private AccessibilityManager mMockA11yManager;
@Test
public void initController_registerListeners() {
@@ -59,6 +70,37 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase {
any(AccessibilityButtonTargetsObserver.TargetsChangedListener.class));
verify(mModeObserver).addListener(
any(AccessibilityButtonModeObserver.ModeChangedListener.class));
verify(mMockA11yManager).addAccessibilityStateChangeListener(any(
AccessibilityManager.AccessibilityStateChangeListener.class));
}
@Test
public void initController_accessibilityManagerEnabled_showWidget() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, TEST_A11Y_BTN_TARGETS);
when(mMockA11yManager.isEnabled()).thenReturn(true);
mController = setUpController();
assertThat(mController.mFloatingMenu).isNotNull();
verify(mMockA11yManager).removeAccessibilityStateChangeListener(mController);
}
@Test
public void initController_accessibilityManagerDisabledThenCallbackToEnabled_showWidget() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, TEST_A11Y_BTN_TARGETS);
when(mMockA11yManager.isEnabled()).thenReturn(false);
mController = setUpController();
mController.onAccessibilityStateChanged(true);
assertThat(mController.mFloatingMenu).isNotNull();
verify(mMockA11yManager).removeAccessibilityStateChangeListener(mController);
}
@Test
@@ -154,7 +196,9 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase {
private AccessibilityFloatingMenuController setUpController() {
mTargetsObserver = spy(Dependency.get(AccessibilityButtonTargetsObserver.class));
mModeObserver = spy(Dependency.get(AccessibilityButtonModeObserver.class));
mContext.addMockSystemService(AccessibilityManager.class, mMockA11yManager);
return new AccessibilityFloatingMenuController(mContext, mTargetsObserver, mModeObserver);
return new AccessibilityFloatingMenuController(mContext, mTargetsObserver,
mModeObserver);
}
}