1 /** 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 * express or implied. See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15 package android.accessibilityservice.cts; 16 17 import static android.accessibility.cts.common.AccessibilityShortcutSettingsRule.ACCESSIBILITY_BUTTON; 18 import static android.accessibilityservice.AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON; 19 import static android.app.UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES; 20 21 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 22 23 import static org.junit.Assert.assertTrue; 24 25 import android.accessibility.cts.common.AccessibilityDumpOnFailureRule; 26 import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule; 27 import android.accessibilityservice.AccessibilityServiceInfo; 28 import android.app.Instrumentation; 29 import android.app.Service; 30 import android.app.UiAutomation; 31 import android.content.ComponentName; 32 import android.os.Build; 33 import android.platform.test.annotations.AppModeFull; 34 import android.text.TextUtils; 35 import android.view.accessibility.AccessibilityManager; 36 37 import androidx.test.InstrumentationRegistry; 38 import androidx.test.runner.AndroidJUnit4; 39 40 import org.junit.AfterClass; 41 import org.junit.Before; 42 import org.junit.BeforeClass; 43 import org.junit.Rule; 44 import org.junit.Test; 45 import org.junit.rules.RuleChain; 46 import org.junit.runner.RunWith; 47 48 import java.util.List; 49 50 /** 51 * Test to verify accessibility button targeting sdk 29 APIs. 52 */ 53 @AppModeFull 54 @RunWith(AndroidJUnit4.class) 55 public class AccessibilityButtonSdk29Test { 56 private static Instrumentation sInstrumentation; 57 private static UiAutomation sUiAutomation; 58 59 private InstrumentedAccessibilityServiceTestRule<StubAccessibilityButtonSdk29Service> 60 mServiceRule = new InstrumentedAccessibilityServiceTestRule<>( 61 StubAccessibilityButtonSdk29Service.class); 62 63 private AccessibilityDumpOnFailureRule mDumpOnFailureRule = 64 new AccessibilityDumpOnFailureRule(); 65 66 @Rule 67 public final RuleChain mRuleChain = RuleChain 68 .outerRule(mServiceRule) 69 .around(mDumpOnFailureRule); 70 71 private StubAccessibilityButtonSdk29Service mService; 72 private AccessibilityServiceInfo mServiceInfo; 73 private ComponentName mServiceComponentName; 74 private AccessibilityManager mAccessibilityManager; 75 76 @BeforeClass oneTimeSetup()77 public static void oneTimeSetup() { 78 sInstrumentation = InstrumentationRegistry.getInstrumentation(); 79 sUiAutomation = sInstrumentation.getUiAutomation(FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES); 80 } 81 82 @AfterClass postTestTearDown()83 public static void postTestTearDown() { 84 sUiAutomation.destroy(); 85 } 86 87 @Before setUp()88 public void setUp() { 89 mAccessibilityManager = (AccessibilityManager) sInstrumentation.getContext() 90 .getSystemService(Service.ACCESSIBILITY_SERVICE); 91 mService = mServiceRule.getService(); 92 mServiceInfo = mService.getServiceInfo(); 93 mServiceComponentName = new ComponentName( 94 mServiceInfo.getResolveInfo().serviceInfo.packageName, 95 mServiceInfo.getResolveInfo().serviceInfo.name); 96 97 mServiceInfo.flags |= FLAG_REQUEST_ACCESSIBILITY_BUTTON; 98 mService.setServiceInfo(mServiceInfo); 99 mServiceInfo = mService.getServiceInfo(); 100 assertTrue(mService.getApplicationInfo().targetSdkVersion == Build.VERSION_CODES.Q); 101 assertTrue((mServiceInfo.flags & FLAG_REQUEST_ACCESSIBILITY_BUTTON) 102 == FLAG_REQUEST_ACCESSIBILITY_BUTTON); 103 } 104 105 @Test testUpdateRequestAccessibilityButtonFlag_succeeds()106 public void testUpdateRequestAccessibilityButtonFlag_succeeds() { 107 mServiceInfo.flags &= ~FLAG_REQUEST_ACCESSIBILITY_BUTTON; 108 mService.setServiceInfo(mServiceInfo); 109 assertTrue("Update flagRequestAccessibilityButton should succeed", 110 mService.getServiceInfo().flags == mServiceInfo.flags); 111 } 112 113 @Test getA11yBtn_withLegacyReqA11yBtnService_succeeds()114 public void getA11yBtn_withLegacyReqA11yBtnService_succeeds() { 115 runWithShellPermissionIdentity(sUiAutomation, () -> { 116 final List<String> targets = mAccessibilityManager.getAccessibilityShortcutTargets( 117 ACCESSIBILITY_BUTTON); 118 assertTrue("Single Tap should contain legacy accessibility service.", 119 shortcutTargetListContains(targets, mServiceComponentName)); 120 }); 121 } 122 123 /** 124 * Return true if the {@code shortcutTargets} contains the given component name. 125 * 126 * @param shortcutTargets A list of shortcut targets. 127 * @param name The component name. 128 * @return {@code true} if the {@code shortcutTargets} contains the given component name. 129 */ shortcutTargetListContains(List<String> shortcutTargets, ComponentName name)130 private boolean shortcutTargetListContains(List<String> shortcutTargets, ComponentName name) { 131 for (int i = 0; i < shortcutTargets.size(); i++) { 132 final String stringName = shortcutTargets.get(i); 133 if (TextUtils.isEmpty(stringName)) { 134 continue; 135 } 136 if (name.equals(ComponentName.unflattenFromString(stringName))) return true; 137 } 138 return false; 139 } 140 } 141