diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java index 96ea5b45282b0..27aade5e6bf8e 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java +++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java @@ -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; @@ -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; @@ -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(); } }; @@ -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(); } /** @@ -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; } @@ -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(); + } + } } diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java index 7277392f18414..9d1af0e2375a6 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java +++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java @@ -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; @@ -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; @@ -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 { @@ -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( @@ -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(); } @@ -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); @@ -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(); - - sUiAutomation.performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN); - TestUtils.waitUntil("Screen did not become locked", - TIMEOUT_UI_CHANGE_S, - () -> !powerManager.isInteractive()); - - sUiAutomation.executeShellCommand("input keyevent KEYCODE_WAKEUP"); - TestUtils.waitUntil("Screen did not wake up", - TIMEOUT_UI_CHANGE_S, - () -> powerManager.isInteractive()); + closeScreen(); + wakeUpScreen(); assertThat(isMenuVisible()).isFalse(); } + + @Test + public void testOnScreenLock_cannotOpenMenu() throws Throwable { + closeScreen(); + wakeUpScreen(); + + boolean timedOut = false; + try { + openMenu(); + } catch (AssertionError e) { + // Expected + timedOut = true; + } + assertThat(timedOut).isTrue(); + } }