Loading packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java +15 −5 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.accessibility.accessibilitymenu; import android.Manifest; import android.accessibilityservice.AccessibilityButtonController; import android.accessibilityservice.AccessibilityService; import android.app.KeyguardManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; Loading Loading @@ -82,6 +83,9 @@ public class AccessibilityMenuService extends AccessibilityService // TODO(b/136716947): Support multi-display once a11y framework side is ready. private DisplayManager mDisplayManager; private KeyguardManager mKeyguardManager; private final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() { int mRotation; Loading Loading @@ -114,7 +118,7 @@ public class AccessibilityMenuService extends AccessibilityService private final BroadcastReceiver mToggleMenuReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { mA11yMenuLayout.toggleVisibility(); toggleVisibility(); } }; Loading Loading @@ -159,10 +163,7 @@ public class AccessibilityMenuService extends AccessibilityService */ @Override public void onClicked(AccessibilityButtonController controller) { if (SystemClock.uptimeMillis() - mLastTimeTouchedOutside > BUTTON_CLICK_TIMEOUT) { mA11yMenuLayout.toggleVisibility(); } toggleVisibility(); } /** Loading Loading @@ -209,6 +210,7 @@ public class AccessibilityMenuService extends AccessibilityService mDisplayManager = getSystemService(DisplayManager.class); mDisplayManager.registerDisplayListener(mDisplayListener, null); mAudioManager = getSystemService(AudioManager.class); mKeyguardManager = getSystemService(KeyguardManager.class); sInitialized = true; } Loading Loading @@ -379,4 +381,12 @@ public class AccessibilityMenuService extends AccessibilityService } return false; } private void toggleVisibility() { boolean locked = mKeyguardManager != null && mKeyguardManager.isKeyguardLocked(); if (!locked && SystemClock.uptimeMillis() - mLastTimeTouchedOutside > BUTTON_CLICK_TIMEOUT) { mA11yMenuLayout.toggleVisibility(); } } } packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java +65 −16 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import static com.google.common.truth.Truth.assertThat; import android.accessibilityservice.AccessibilityServiceInfo; import android.app.Instrumentation; import android.app.KeyguardManager; import android.app.UiAutomation; import android.content.BroadcastReceiver; import android.content.Context; Loading @@ -44,6 +45,7 @@ import android.media.AudioManager; import android.os.PowerManager; import android.provider.Settings; import android.util.Log; import android.view.Display; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; Loading @@ -69,15 +71,19 @@ public class AccessibilityMenuServiceTest { private static final int CLICK_ID = AccessibilityNodeInfo.ACTION_CLICK; private static final int TIMEOUT_SERVICE_STATUS_CHANGE_S = 5; private static final int TIMEOUT_UI_CHANGE_S = 10; private static final int TIMEOUT_UI_CHANGE_S = 5; private static final int NO_GLOBAL_ACTION = -1; private static final String INPUT_KEYEVENT_KEYCODE_BACK = "input keyevent KEYCODE_BACK"; private static final String TEST_PIN = "1234"; private static Instrumentation sInstrumentation; private static UiAutomation sUiAutomation; private static AtomicInteger sLastGlobalAction; private static AccessibilityManager sAccessibilityManager; private static PowerManager sPowerManager; private static KeyguardManager sKeyguardManager; private static DisplayManager sDisplayManager; @BeforeClass public static void classSetup() throws Throwable { Loading @@ -85,8 +91,14 @@ public class AccessibilityMenuServiceTest { sInstrumentation = InstrumentationRegistry.getInstrumentation(); sUiAutomation = sInstrumentation.getUiAutomation( UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES); sUiAutomation.adoptShellPermissionIdentity( UiAutomation.ALL_PERMISSIONS.toArray(new String[0])); final Context context = sInstrumentation.getTargetContext(); sAccessibilityManager = context.getSystemService(AccessibilityManager.class); sPowerManager = context.getSystemService(PowerManager.class); sKeyguardManager = context.getSystemService(KeyguardManager.class); sDisplayManager = context.getSystemService(DisplayManager.class); // Disable all a11yServices if any are active. if (!sAccessibilityManager.getEnabledAccessibilityServiceList( Loading Loading @@ -123,12 +135,16 @@ public class AccessibilityMenuServiceTest { @AfterClass public static void classTeardown() throws Throwable { clearPin(); Settings.Secure.putString(sInstrumentation.getTargetContext().getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, ""); } @Before public void setup() throws Throwable { clearPin(); wakeUpScreen(); sUiAutomation.executeShellCommand("input keyevent KEYCODE_MENU"); openMenu(); } Loading @@ -138,11 +154,43 @@ public class AccessibilityMenuServiceTest { sLastGlobalAction.set(NO_GLOBAL_ACTION); } private static void clearPin() throws Throwable { sUiAutomation.executeShellCommand("locksettings clear --old " + TEST_PIN); TestUtils.waitUntil("Device did not register as unlocked & insecure.", TIMEOUT_SERVICE_STATUS_CHANGE_S, () -> !sKeyguardManager.isDeviceSecure()); } private static void setPin() throws Throwable { sUiAutomation.executeShellCommand("locksettings set-pin " + TEST_PIN); TestUtils.waitUntil("Device did not recognize as locked & secure.", TIMEOUT_SERVICE_STATUS_CHANGE_S, () -> sKeyguardManager.isDeviceSecure()); } private static boolean isMenuVisible() { AccessibilityNodeInfo root = sUiAutomation.getRootInActiveWindow(); return root != null && root.getPackageName().toString().equals(PACKAGE_NAME); } private static void wakeUpScreen() throws Throwable { sUiAutomation.executeShellCommand("input keyevent KEYCODE_WAKEUP"); TestUtils.waitUntil("Screen did not wake up.", TIMEOUT_UI_CHANGE_S, () -> sPowerManager.isInteractive()); } private static void closeScreen() throws Throwable { Display display = sDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); setPin(); sUiAutomation.performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN); TestUtils.waitUntil("Screen did not close.", TIMEOUT_UI_CHANGE_S, () -> !sPowerManager.isInteractive() && display.getState() == Display.STATE_OFF ); } private static void openMenu() throws Throwable { Intent intent = new Intent(PACKAGE_NAME + INTENT_TOGGLE_MENU); sInstrumentation.getContext().sendBroadcast(intent); Loading Loading @@ -381,23 +429,24 @@ public class AccessibilityMenuServiceTest { @Test public void testOnScreenLock_closesMenu() throws Throwable { openMenu(); Context context = sInstrumentation.getTargetContext(); PowerManager powerManager = context.getSystemService(PowerManager.class); assertThat(powerManager).isNotNull(); assertThat(powerManager.isInteractive()).isTrue(); closeScreen(); wakeUpScreen(); sUiAutomation.performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN); TestUtils.waitUntil("Screen did not become locked", TIMEOUT_UI_CHANGE_S, () -> !powerManager.isInteractive()); assertThat(isMenuVisible()).isFalse(); } sUiAutomation.executeShellCommand("input keyevent KEYCODE_WAKEUP"); TestUtils.waitUntil("Screen did not wake up", TIMEOUT_UI_CHANGE_S, () -> powerManager.isInteractive()); @Test public void testOnScreenLock_cannotOpenMenu() throws Throwable { closeScreen(); wakeUpScreen(); assertThat(isMenuVisible()).isFalse(); boolean timedOut = false; try { openMenu(); } catch (AssertionError e) { // Expected timedOut = true; } assertThat(timedOut).isTrue(); } } Loading
packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java +15 −5 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.accessibility.accessibilitymenu; import android.Manifest; import android.accessibilityservice.AccessibilityButtonController; import android.accessibilityservice.AccessibilityService; import android.app.KeyguardManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; Loading Loading @@ -82,6 +83,9 @@ public class AccessibilityMenuService extends AccessibilityService // TODO(b/136716947): Support multi-display once a11y framework side is ready. private DisplayManager mDisplayManager; private KeyguardManager mKeyguardManager; private final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() { int mRotation; Loading Loading @@ -114,7 +118,7 @@ public class AccessibilityMenuService extends AccessibilityService private final BroadcastReceiver mToggleMenuReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { mA11yMenuLayout.toggleVisibility(); toggleVisibility(); } }; Loading Loading @@ -159,10 +163,7 @@ public class AccessibilityMenuService extends AccessibilityService */ @Override public void onClicked(AccessibilityButtonController controller) { if (SystemClock.uptimeMillis() - mLastTimeTouchedOutside > BUTTON_CLICK_TIMEOUT) { mA11yMenuLayout.toggleVisibility(); } toggleVisibility(); } /** Loading Loading @@ -209,6 +210,7 @@ public class AccessibilityMenuService extends AccessibilityService mDisplayManager = getSystemService(DisplayManager.class); mDisplayManager.registerDisplayListener(mDisplayListener, null); mAudioManager = getSystemService(AudioManager.class); mKeyguardManager = getSystemService(KeyguardManager.class); sInitialized = true; } Loading Loading @@ -379,4 +381,12 @@ public class AccessibilityMenuService extends AccessibilityService } return false; } private void toggleVisibility() { boolean locked = mKeyguardManager != null && mKeyguardManager.isKeyguardLocked(); if (!locked && SystemClock.uptimeMillis() - mLastTimeTouchedOutside > BUTTON_CLICK_TIMEOUT) { mA11yMenuLayout.toggleVisibility(); } } }
packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java +65 −16 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import static com.google.common.truth.Truth.assertThat; import android.accessibilityservice.AccessibilityServiceInfo; import android.app.Instrumentation; import android.app.KeyguardManager; import android.app.UiAutomation; import android.content.BroadcastReceiver; import android.content.Context; Loading @@ -44,6 +45,7 @@ import android.media.AudioManager; import android.os.PowerManager; import android.provider.Settings; import android.util.Log; import android.view.Display; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; Loading @@ -69,15 +71,19 @@ public class AccessibilityMenuServiceTest { private static final int CLICK_ID = AccessibilityNodeInfo.ACTION_CLICK; private static final int TIMEOUT_SERVICE_STATUS_CHANGE_S = 5; private static final int TIMEOUT_UI_CHANGE_S = 10; private static final int TIMEOUT_UI_CHANGE_S = 5; private static final int NO_GLOBAL_ACTION = -1; private static final String INPUT_KEYEVENT_KEYCODE_BACK = "input keyevent KEYCODE_BACK"; private static final String TEST_PIN = "1234"; private static Instrumentation sInstrumentation; private static UiAutomation sUiAutomation; private static AtomicInteger sLastGlobalAction; private static AccessibilityManager sAccessibilityManager; private static PowerManager sPowerManager; private static KeyguardManager sKeyguardManager; private static DisplayManager sDisplayManager; @BeforeClass public static void classSetup() throws Throwable { Loading @@ -85,8 +91,14 @@ public class AccessibilityMenuServiceTest { sInstrumentation = InstrumentationRegistry.getInstrumentation(); sUiAutomation = sInstrumentation.getUiAutomation( UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES); sUiAutomation.adoptShellPermissionIdentity( UiAutomation.ALL_PERMISSIONS.toArray(new String[0])); final Context context = sInstrumentation.getTargetContext(); sAccessibilityManager = context.getSystemService(AccessibilityManager.class); sPowerManager = context.getSystemService(PowerManager.class); sKeyguardManager = context.getSystemService(KeyguardManager.class); sDisplayManager = context.getSystemService(DisplayManager.class); // Disable all a11yServices if any are active. if (!sAccessibilityManager.getEnabledAccessibilityServiceList( Loading Loading @@ -123,12 +135,16 @@ public class AccessibilityMenuServiceTest { @AfterClass public static void classTeardown() throws Throwable { clearPin(); Settings.Secure.putString(sInstrumentation.getTargetContext().getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, ""); } @Before public void setup() throws Throwable { clearPin(); wakeUpScreen(); sUiAutomation.executeShellCommand("input keyevent KEYCODE_MENU"); openMenu(); } Loading @@ -138,11 +154,43 @@ public class AccessibilityMenuServiceTest { sLastGlobalAction.set(NO_GLOBAL_ACTION); } private static void clearPin() throws Throwable { sUiAutomation.executeShellCommand("locksettings clear --old " + TEST_PIN); TestUtils.waitUntil("Device did not register as unlocked & insecure.", TIMEOUT_SERVICE_STATUS_CHANGE_S, () -> !sKeyguardManager.isDeviceSecure()); } private static void setPin() throws Throwable { sUiAutomation.executeShellCommand("locksettings set-pin " + TEST_PIN); TestUtils.waitUntil("Device did not recognize as locked & secure.", TIMEOUT_SERVICE_STATUS_CHANGE_S, () -> sKeyguardManager.isDeviceSecure()); } private static boolean isMenuVisible() { AccessibilityNodeInfo root = sUiAutomation.getRootInActiveWindow(); return root != null && root.getPackageName().toString().equals(PACKAGE_NAME); } private static void wakeUpScreen() throws Throwable { sUiAutomation.executeShellCommand("input keyevent KEYCODE_WAKEUP"); TestUtils.waitUntil("Screen did not wake up.", TIMEOUT_UI_CHANGE_S, () -> sPowerManager.isInteractive()); } private static void closeScreen() throws Throwable { Display display = sDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); setPin(); sUiAutomation.performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN); TestUtils.waitUntil("Screen did not close.", TIMEOUT_UI_CHANGE_S, () -> !sPowerManager.isInteractive() && display.getState() == Display.STATE_OFF ); } private static void openMenu() throws Throwable { Intent intent = new Intent(PACKAGE_NAME + INTENT_TOGGLE_MENU); sInstrumentation.getContext().sendBroadcast(intent); Loading Loading @@ -381,23 +429,24 @@ public class AccessibilityMenuServiceTest { @Test public void testOnScreenLock_closesMenu() throws Throwable { openMenu(); Context context = sInstrumentation.getTargetContext(); PowerManager powerManager = context.getSystemService(PowerManager.class); assertThat(powerManager).isNotNull(); assertThat(powerManager.isInteractive()).isTrue(); closeScreen(); wakeUpScreen(); sUiAutomation.performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN); TestUtils.waitUntil("Screen did not become locked", TIMEOUT_UI_CHANGE_S, () -> !powerManager.isInteractive()); assertThat(isMenuVisible()).isFalse(); } sUiAutomation.executeShellCommand("input keyevent KEYCODE_WAKEUP"); TestUtils.waitUntil("Screen did not wake up", TIMEOUT_UI_CHANGE_S, () -> powerManager.isInteractive()); @Test public void testOnScreenLock_cannotOpenMenu() throws Throwable { closeScreen(); wakeUpScreen(); assertThat(isMenuVisible()).isFalse(); boolean timedOut = false; try { openMenu(); } catch (AssertionError e) { // Expected timedOut = true; } assertThat(timedOut).isTrue(); } }