diff options
| author | 2023-02-02 12:59:07 -0800 | |
|---|---|---|
| committer | 2023-03-04 01:51:13 +0000 | |
| commit | abdfd6f63b53db8b836e7734789efdf59618b42e (patch) | |
| tree | b2225765cc44e4d844d8d64f096d0b0d46db2c6c | |
| parent | 5c6c582940cf4509d5a1ea987f6b41c7666a0d00 (diff) | |
AccessibilityMenuService test class setup & initial test.
Bug: 265173123
Test: atest AccessibilityMenuServiceTests
Change-Id: I388e02b58bf582ae6b481804c5f34883e8692e5f
9 files changed, 356 insertions, 7 deletions
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp index 140c10da922e..f358417e6bea 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp +++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp @@ -18,6 +18,15 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } +// This filegroup is used by menu tests. +filegroup { + name: "AccessibilityMenuSource", + srcs: [ + "src/**/AccessibilityMenuService.java", + "src/**/A11yMenuShortcut.java", + ], +} + android_app { name: "AccessibilityMenu", diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml index 39e5a8c6876b..a902c5b54b7b 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml +++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/shortcutItem" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="@dimen/grid_item_padding" 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 c1f2aa86c6b5..8ca64d2505ce 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 @@ -16,6 +16,7 @@ package com.android.systemui.accessibility.accessibilitymenu; +import android.Manifest; import android.accessibilityservice.AccessibilityButtonController; import android.accessibilityservice.AccessibilityService; import android.content.BroadcastReceiver; @@ -51,8 +52,12 @@ import java.util.List; /** @hide */ public class AccessibilityMenuService extends AccessibilityService implements View.OnTouchListener { - private static final String TAG = "A11yMenuService"; + public static final String PACKAGE_NAME = AccessibilityMenuService.class.getPackageName(); + public static final String INTENT_TOGGLE_MENU = ".toggle_menu"; + public static final String INTENT_HIDE_MENU = ".hide_menu"; + + private static final String TAG = "A11yMenuService"; private static final long BUFFER_MILLISECONDS_TO_PREVENT_UPDATE_FAILURE = 100L; private static final int BRIGHTNESS_UP_INCREMENT_GAMMA = @@ -74,7 +79,8 @@ public class AccessibilityMenuService extends AccessibilityService // TODO(b/136716947): Support multi-display once a11y framework side is ready. private DisplayManager mDisplayManager; - final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() { + private final DisplayManager.DisplayListener mDisplayListener = + new DisplayManager.DisplayListener() { int mRotation; @Override @@ -95,13 +101,20 @@ public class AccessibilityMenuService extends AccessibilityService } }; - final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + private final BroadcastReceiver mHideMenuReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { mA11yMenuLayout.hideMenu(); } }; + private final BroadcastReceiver mToggleMenuReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + mA11yMenuLayout.toggleVisibility(); + } + }; + /** * Update a11y menu layout when large button setting is changed. */ @@ -172,7 +185,19 @@ public class AccessibilityMenuService extends AccessibilityService protected void onServiceConnected() { mA11yMenuLayout = new A11yMenuOverlayLayout(this); - registerReceiver(mBroadcastReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); + IntentFilter hideMenuFilter = new IntentFilter(); + hideMenuFilter.addAction(Intent.ACTION_SCREEN_OFF); + hideMenuFilter.addAction(PACKAGE_NAME + INTENT_HIDE_MENU); + + // Including WRITE_SECURE_SETTINGS enforces that we only listen to apps + // with the restricted WRITE_SECURE_SETTINGS permission who broadcast this intent. + registerReceiver(mHideMenuReceiver, hideMenuFilter, + Manifest.permission.WRITE_SECURE_SETTINGS, null, + Context.RECEIVER_EXPORTED); + registerReceiver(mToggleMenuReceiver, + new IntentFilter(PACKAGE_NAME + INTENT_TOGGLE_MENU), + Manifest.permission.WRITE_SECURE_SETTINGS, null, + Context.RECEIVER_EXPORTED); mPrefs = PreferenceManager.getDefaultSharedPreferences(this); mPrefs.registerOnSharedPreferenceChangeListener(mSharedPreferenceChangeListener); @@ -260,7 +285,8 @@ public class AccessibilityMenuService extends AccessibilityService * @param increment The increment amount in gamma-space */ private void adjustBrightness(int increment) { - BrightnessInfo info = getDisplay().getBrightnessInfo(); + Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); + BrightnessInfo info = display.getBrightnessInfo(); int gamma = BrightnessUtils.convertLinearToGammaFloat( info.brightness, info.brightnessMinimum, @@ -275,7 +301,7 @@ public class AccessibilityMenuService extends AccessibilityService info.brightnessMinimum, info.brightnessMaximum ); - mDisplayManager.setBrightness(getDisplayId(), brightness); + mDisplayManager.setBrightness(display.getDisplayId(), brightness); mA11yMenuLayout.showSnackbar( getString(R.string.brightness_percentage_label, (gamma / (BrightnessUtils.GAMMA_SPACE_MAX / 100)))); @@ -310,7 +336,8 @@ public class AccessibilityMenuService extends AccessibilityService @Override public boolean onUnbind(Intent intent) { - unregisterReceiver(mBroadcastReceiver); + unregisterReceiver(mHideMenuReceiver); + unregisterReceiver(mToggleMenuReceiver); mPrefs.unregisterOnSharedPreferenceChangeListener(mSharedPreferenceChangeListener); sInitialized = false; return super.onUnbind(intent); diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java index 6f0fe374d6f6..6ae65cb6d8f6 100644 --- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java +++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java @@ -21,6 +21,7 @@ import android.view.LayoutInflater; import android.view.TouchDelegate; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.BaseAdapter; import android.widget.ImageButton; import android.widget.TextView; @@ -146,6 +147,15 @@ public class A11yMenuAdapter extends BaseAdapter { shortcutIconButton.setBackground( mShortcutDrawableUtils.createAdaptiveIconDrawable(shortcutItem.imageColor)); + + shortcutIconButton.setAccessibilityDelegate(new View.AccessibilityDelegate() { + @Override + public void onInitializeAccessibilityNodeInfo( + View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + info.setUniqueId(host.getTag().toString()); + } + }); } } } diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp new file mode 100644 index 000000000000..1757dda84eef --- /dev/null +++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp @@ -0,0 +1,43 @@ +// +// Copyright (C) 2023 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_test { + name: "AccessibilityMenuServiceTests", + certificate: "platform", + libs: [ + "android.test.runner", + "android.test.base", + ], + static_libs: [ + "androidx.test.core", + "androidx.test.runner", + "androidx.test.ext.junit", + "compatibility-device-util-axt", + "platform-test-annotations", + "truth-prebuilt", + ], + srcs: [ + "src/**/*.java", + ":AccessibilityMenuSource", + ], + platform_apis: true, + test_suites: ["device-tests"], + instrumentation_for: "AccessibilityMenu", +} diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml new file mode 100644 index 000000000000..7be6ca742376 --- /dev/null +++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2023 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="com.android.systemui.accessibility.accessibilitymenu.tests"> + + <!-- Needed to write to Settings.Secure to enable and disable the service under test. --> + <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> + <uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"/> + + <application android:debuggable="true"> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.systemui.accessibility.accessibilitymenu.tests" + android:label="AccessibilityMenu Test Cases"> + </instrumentation> +</manifest>
\ No newline at end of file diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidTest.xml b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidTest.xml new file mode 100644 index 000000000000..39bee5392720 --- /dev/null +++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidTest.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2023 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Runs AccessibilityMenu Test Cases."> + <option name="test-tag" value="AccessibilityMenuServiceTests" /> + + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true" /> + <option name="test-file-name" value="AccessibilityMenuServiceTests.apk" /> + <option name="aapt-version" value="AAPT2" /> + </target_preparer> + + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.systemui.accessibility.accessibilitymenu.tests" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> + </test> +</configuration>
\ No newline at end of file diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/TEST_MAPPING b/packages/SystemUI/accessibility/accessibilitymenu/tests/TEST_MAPPING new file mode 100644 index 000000000000..2bd52b552698 --- /dev/null +++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "AccessibilityMenuServiceTests", + "options": [ + { + "include-annotation": "android.platform.test.annotations.Presubmit" + }, + { + "exclude-annotation": "android.support.test.filters.FlakyTest" + } + ] + } + ] +}
\ No newline at end of file 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 new file mode 100644 index 000000000000..529a70c1ab18 --- /dev/null +++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.accessibility.accessibilitymenu.tests; + +import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.INTENT_HIDE_MENU; +import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.INTENT_TOGGLE_MENU; +import static com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService.PACKAGE_NAME; + +import android.accessibilityservice.AccessibilityServiceInfo; +import android.app.Instrumentation; +import android.app.UiAutomation; +import android.content.Context; +import android.content.Intent; +import android.hardware.display.BrightnessInfo; +import android.hardware.display.DisplayManager; +import android.provider.Settings; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.compatibility.common.util.TestUtils; +import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut.ShortcutId; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; + +@RunWith(AndroidJUnit4.class) +public class AccessibilityMenuServiceTest { + private static final String TAG = "A11yMenuServiceTest"; + + private static final int TIMEOUT_SERVICE_STATUS_CHANGE_S = 5; + private static final int TIMEOUT_UI_CHANGE_S = 5; + + private static Instrumentation sInstrumentation; + private static UiAutomation sUiAutomation; + + private static AccessibilityManager sAccessibilityManager; + + @BeforeClass + public static void classSetup() throws Throwable { + final String serviceName = PACKAGE_NAME + "/.AccessibilityMenuService"; + sInstrumentation = InstrumentationRegistry.getInstrumentation(); + sUiAutomation = sInstrumentation.getUiAutomation( + UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES); + final Context context = sInstrumentation.getContext(); + sAccessibilityManager = context.getSystemService(AccessibilityManager.class); + + // Disable all a11yServices if any are active. + if (!sAccessibilityManager.getEnabledAccessibilityServiceList( + AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) { + Settings.Secure.putString(context.getContentResolver(), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, ""); + TestUtils.waitUntil("Failed to disable all services", + TIMEOUT_SERVICE_STATUS_CHANGE_S, + () -> sAccessibilityManager.getEnabledAccessibilityServiceList( + AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()); + } + + // Enable a11yMenu service. + Settings.Secure.putString(context.getContentResolver(), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, serviceName); + + TestUtils.waitUntil("Failed to enable service", + TIMEOUT_SERVICE_STATUS_CHANGE_S, + () -> sAccessibilityManager.getEnabledAccessibilityServiceList( + AccessibilityServiceInfo.FEEDBACK_ALL_MASK).stream().filter( + info -> info.getId().contains(serviceName)).count() == 1); + } + + @AfterClass + public static void classTeardown() throws Throwable { + Settings.Secure.putString(sInstrumentation.getTargetContext().getContentResolver(), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, ""); + } + + private boolean isMenuVisible() { + return sUiAutomation.getRootInActiveWindow() != null + && sUiAutomation.getRootInActiveWindow().getPackageName().toString().equals( + PACKAGE_NAME); + } + + private void openMenu() throws Throwable { + if (isMenuVisible()) { + return; + } + Intent intent = new Intent(PACKAGE_NAME + INTENT_TOGGLE_MENU); + sInstrumentation.getContext().sendBroadcast(intent); + TestUtils.waitUntil("Timed out before menu could appear.", + TIMEOUT_UI_CHANGE_S, () -> isMenuVisible()); + } + + private void closeMenu() throws Throwable { + if (!isMenuVisible()) { + return; + } + Intent intent = new Intent(PACKAGE_NAME + INTENT_HIDE_MENU); + sInstrumentation.getContext().sendBroadcast(intent); + TestUtils.waitUntil("Timed out before menu could close.", + TIMEOUT_UI_CHANGE_S, () -> !isMenuVisible()); + } + + private List<AccessibilityNodeInfo> getGridButtonList() { + return sUiAutomation.getRootInActiveWindow() + .findAccessibilityNodeInfosByViewId(PACKAGE_NAME + ":id/shortcutIconBtn"); + } + + private AccessibilityNodeInfo findGridButtonInfo( + List<AccessibilityNodeInfo> buttons, String text) { + for (AccessibilityNodeInfo button: buttons) { + if (button.getUniqueId().equals(text)) { + return button; + } + } + return null; + } + + @Test + public void testAdjustBrightness() throws Throwable { + openMenu(); + + Context context = sInstrumentation.getTargetContext(); + DisplayManager displayManager = context.getSystemService( + DisplayManager.class); + float resetBrightness = displayManager.getBrightness(context.getDisplayId()); + + List<AccessibilityNodeInfo> buttons = getGridButtonList(); + AccessibilityNodeInfo brightnessUpButton = findGridButtonInfo(buttons, + String.valueOf(ShortcutId.ID_BRIGHTNESS_UP_VALUE.ordinal())); + AccessibilityNodeInfo brightnessDownButton = findGridButtonInfo(buttons, + String.valueOf(ShortcutId.ID_BRIGHTNESS_DOWN_VALUE.ordinal())); + + int clickId = AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.getId(); + BrightnessInfo brightnessInfo = displayManager.getDisplay( + context.getDisplayId()).getBrightnessInfo(); + + try { + displayManager.setBrightness(context.getDisplayId(), brightnessInfo.brightnessMinimum); + TestUtils.waitUntil("Could not change to minimum brightness", + TIMEOUT_UI_CHANGE_S, + () -> displayManager.getBrightness(context.getDisplayId()) + == brightnessInfo.brightnessMinimum); + brightnessUpButton.performAction(clickId); + TestUtils.waitUntil("Did not detect an increase in brightness.", + TIMEOUT_UI_CHANGE_S, + () -> displayManager.getBrightness(context.getDisplayId()) + > brightnessInfo.brightnessMinimum); + + displayManager.setBrightness(context.getDisplayId(), brightnessInfo.brightnessMaximum); + TestUtils.waitUntil("Could not change to maximum brightness", + TIMEOUT_UI_CHANGE_S, + () -> displayManager.getBrightness(context.getDisplayId()) + == brightnessInfo.brightnessMaximum); + brightnessDownButton.performAction(clickId); + TestUtils.waitUntil("Did not detect a decrease in brightness.", + TIMEOUT_UI_CHANGE_S, + () -> displayManager.getBrightness(context.getDisplayId()) + < brightnessInfo.brightnessMaximum); + } finally { + displayManager.setBrightness(context.getDisplayId(), resetBrightness); + closeMenu(); + } + } +} |