1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.accessibilityservice.cts; 18 19 import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.AccessibilityEventTypeMatcher; 20 import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.ContentChangesMatcher; 21 import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityAndWaitForItToBeOnscreen; 22 import static android.accessibilityservice.cts.utils.AsyncUtils.DEFAULT_TIMEOUT_MS; 23 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED; 24 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED; 25 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE; 26 import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; 27 28 import static org.hamcrest.Matchers.both; 29 import static org.junit.Assert.assertEquals; 30 import static org.junit.Assert.assertNull; 31 32 import android.accessibility.cts.common.AccessibilityDumpOnFailureRule; 33 import android.accessibilityservice.cts.activities.AccessibilityEndToEndActivity; 34 import android.app.Activity; 35 import android.app.Instrumentation; 36 import android.app.UiAutomation; 37 import android.app.UiAutomation.AccessibilityEventFilter; 38 import android.platform.test.annotations.Presubmit; 39 import android.view.View; 40 import android.view.accessibility.AccessibilityNodeInfo; 41 42 import androidx.test.InstrumentationRegistry; 43 import androidx.test.rule.ActivityTestRule; 44 import androidx.test.runner.AndroidJUnit4; 45 46 import com.android.compatibility.common.util.CddTest; 47 48 import org.junit.Before; 49 import org.junit.BeforeClass; 50 import org.junit.Rule; 51 import org.junit.Test; 52 import org.junit.rules.RuleChain; 53 import org.junit.runner.RunWith; 54 55 /** 56 * Tests reporting of window-like views 57 */ 58 @RunWith(AndroidJUnit4.class) 59 @CddTest(requirements = {"3.10/C-1-1,C-1-2"}) 60 @Presubmit 61 public class AccessibilityPaneTest { 62 private static Instrumentation sInstrumentation; 63 private static UiAutomation sUiAutomation; 64 65 private Activity mActivity; 66 private View mPaneView; 67 68 private ActivityTestRule<AccessibilityEndToEndActivity> mActivityRule = 69 new ActivityTestRule<>(AccessibilityEndToEndActivity.class, false, false); 70 71 private AccessibilityDumpOnFailureRule mDumpOnFailureRule = 72 new AccessibilityDumpOnFailureRule(); 73 74 private final AccessibilityEventFilter mPaneAppearsFilter = 75 both(new AccessibilityEventTypeMatcher(TYPE_WINDOW_STATE_CHANGED)).and( 76 new ContentChangesMatcher(CONTENT_CHANGE_TYPE_PANE_APPEARED))::matches; 77 private final AccessibilityEventFilter mPaneDisappearsFilter = 78 both(new AccessibilityEventTypeMatcher(TYPE_WINDOW_STATE_CHANGED)).and( 79 new ContentChangesMatcher(CONTENT_CHANGE_TYPE_PANE_DISAPPEARED))::matches; 80 81 @Rule 82 public final RuleChain mRuleChain = RuleChain 83 .outerRule(mActivityRule) 84 .around(mDumpOnFailureRule); 85 86 @BeforeClass oneTimeSetup()87 public static void oneTimeSetup() throws Exception { 88 sInstrumentation = InstrumentationRegistry.getInstrumentation(); 89 sUiAutomation = sInstrumentation.getUiAutomation(); 90 } 91 92 @Before setUp()93 public void setUp() throws Exception { 94 mActivity = launchActivityAndWaitForItToBeOnscreen( 95 sInstrumentation, sUiAutomation, mActivityRule); 96 sInstrumentation.runOnMainSync(() -> { 97 mPaneView = mActivity.findViewById(R.id.button); 98 }); 99 } 100 101 @Test paneTitleFromXml_reportedToAccessibility()102 public void paneTitleFromXml_reportedToAccessibility() { 103 String paneTitle = sInstrumentation.getContext().getString(R.string.paneTitle); 104 assertEquals(paneTitle, mPaneView.getAccessibilityPaneTitle()); 105 AccessibilityNodeInfo paneNode = getPaneNode(); 106 assertEquals(paneTitle, paneNode.getPaneTitle()); 107 } 108 109 @Test windowLikeViewSettersWork_andNewValuesReportedToAccessibility()110 public void windowLikeViewSettersWork_andNewValuesReportedToAccessibility() throws Exception { 111 final String newTitle = "Here's a new title"; 112 113 sUiAutomation.executeAndWaitForEvent(() -> sInstrumentation.runOnMainSync(() -> { 114 mPaneView.setAccessibilityPaneTitle(newTitle); 115 assertEquals(newTitle, mPaneView.getAccessibilityPaneTitle()); 116 }), (new ContentChangesMatcher(CONTENT_CHANGE_TYPE_PANE_TITLE))::matches, 117 DEFAULT_TIMEOUT_MS); 118 119 AccessibilityNodeInfo windowLikeNode = getPaneNode(); 120 assertEquals(newTitle, windowLikeNode.getPaneTitle()); 121 122 // Disappear 123 sUiAutomation.executeAndWaitForEvent(() -> sInstrumentation.runOnMainSync(() -> { 124 mPaneView.setAccessibilityPaneTitle(null); 125 assertNull(mPaneView.getAccessibilityPaneTitle()); 126 }), mPaneDisappearsFilter, DEFAULT_TIMEOUT_MS); 127 128 windowLikeNode.refresh(); 129 assertNull(windowLikeNode.getPaneTitle()); 130 131 // Appear 132 sUiAutomation.executeAndWaitForEvent(() -> sInstrumentation.runOnMainSync(() -> { 133 mPaneView.setAccessibilityPaneTitle(newTitle); 134 assertEquals(newTitle, mPaneView.getAccessibilityPaneTitle()); 135 }), mPaneAppearsFilter, DEFAULT_TIMEOUT_MS); 136 137 windowLikeNode.refresh(); 138 assertEquals(newTitle, windowLikeNode.getPaneTitle()); 139 } 140 141 @Test windowLikeViewVisibility_reportAsWindowStateChanges()142 public void windowLikeViewVisibility_reportAsWindowStateChanges() throws Exception { 143 sUiAutomation.executeAndWaitForEvent(setPaneViewVisibility(View.GONE), 144 mPaneDisappearsFilter, DEFAULT_TIMEOUT_MS); 145 146 sUiAutomation.executeAndWaitForEvent(setPaneViewVisibility(View.VISIBLE), 147 mPaneAppearsFilter, DEFAULT_TIMEOUT_MS); 148 149 sUiAutomation.executeAndWaitForEvent(setPaneViewParentVisibility(View.GONE), 150 mPaneDisappearsFilter, DEFAULT_TIMEOUT_MS); 151 152 sUiAutomation.executeAndWaitForEvent(setPaneViewParentVisibility(View.VISIBLE), 153 mPaneAppearsFilter, DEFAULT_TIMEOUT_MS); 154 } 155 getPaneNode()156 private AccessibilityNodeInfo getPaneNode() { 157 return sUiAutomation.getRootInActiveWindow().findAccessibilityNodeInfosByViewId( 158 "android.accessibilityservice.cts:id/button").get(0); 159 } 160 setPaneViewVisibility(int visibility)161 private Runnable setPaneViewVisibility(int visibility) { 162 return () -> sInstrumentation.runOnMainSync( 163 () -> mPaneView.setVisibility(visibility)); 164 } 165 setPaneViewParentVisibility(int visibility)166 private Runnable setPaneViewParentVisibility(int visibility) { 167 return () -> sInstrumentation.runOnMainSync( 168 () -> ((View) mPaneView.getParent()).setVisibility(visibility)); 169 } 170 } 171