1 /** 2 * Copyright (C) 2017 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.utils; 16 17 import static org.hamcrest.CoreMatchers.allOf; 18 import static org.hamcrest.CoreMatchers.both; 19 20 import android.app.UiAutomation; 21 import android.app.UiAutomation.AccessibilityEventFilter; 22 import android.view.accessibility.AccessibilityEvent; 23 import android.view.accessibility.AccessibilityWindowInfo; 24 25 import androidx.annotation.NonNull; 26 27 import org.hamcrest.Description; 28 import org.hamcrest.TypeSafeMatcher; 29 30 import java.util.List; 31 import java.util.function.BiPredicate; 32 33 /** 34 * Utility class for creating AccessibilityEventFilters 35 */ 36 public class AccessibilityEventFilterUtils { filterForEventType(int eventType)37 public static AccessibilityEventFilter filterForEventType(int eventType) { 38 return (new AccessibilityEventTypeMatcher(eventType))::matches; 39 } 40 filterWindowContentChangedWithChangeTypes(int changes)41 public static AccessibilityEventFilter filterWindowContentChangedWithChangeTypes(int changes) { 42 return (both(new AccessibilityEventTypeMatcher( 43 AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)).and( 44 new ContentChangesMatcher(changes)))::matches; 45 } 46 filterWindowsChangedWithChangeTypes(int changes)47 public static AccessibilityEventFilter filterWindowsChangedWithChangeTypes(int changes) { 48 return (both(new AccessibilityEventTypeMatcher(AccessibilityEvent.TYPE_WINDOWS_CHANGED)) 49 .and(new WindowChangesMatcher(changes)))::matches; 50 } 51 filterForEventTypeWithResource(int eventType, String ResourceName)52 public static AccessibilityEventFilter filterForEventTypeWithResource(int eventType, 53 String ResourceName) { 54 TypeSafeMatcher<AccessibilityEvent> matchResourceName = new PropertyMatcher<>( 55 ResourceName, "Resource name", 56 (event, expect) -> event.getSource() != null 57 && event.getSource().getViewIdResourceName().equals(expect)); 58 return (both(new AccessibilityEventTypeMatcher(eventType)).and(matchResourceName))::matches; 59 } 60 filterForEventTypeWithAction(int eventType, int action)61 public static AccessibilityEventFilter filterForEventTypeWithAction(int eventType, int action) { 62 TypeSafeMatcher<AccessibilityEvent> matchAction = 63 new PropertyMatcher<>( 64 action, "Action", (event, expect) -> event.getAction() == action); 65 return (both(new AccessibilityEventTypeMatcher(eventType)).and(matchAction))::matches; 66 } 67 filterWindowsChangeTypesAndWindowTitle( @onNull UiAutomation uiAutomation, int changeTypes, @NonNull String title)68 public static AccessibilityEventFilter filterWindowsChangeTypesAndWindowTitle( 69 @NonNull UiAutomation uiAutomation, int changeTypes, @NonNull String title) { 70 return allOf(new AccessibilityEventTypeMatcher(AccessibilityEvent.TYPE_WINDOWS_CHANGED), 71 new WindowChangesMatcher(changeTypes), 72 new WindowTitleMatcher(uiAutomation, title))::matches; 73 } 74 filterWindowsChangTypesAndWindowId(int windowId, int changeTypes)75 public static AccessibilityEventFilter filterWindowsChangTypesAndWindowId(int windowId, 76 int changeTypes) { 77 return allOf(new AccessibilityEventTypeMatcher(AccessibilityEvent.TYPE_WINDOWS_CHANGED), 78 new WindowChangesMatcher(changeTypes), 79 new WindowIdMatcher(windowId))::matches; 80 } 81 82 public static class AccessibilityEventTypeMatcher extends TypeSafeMatcher<AccessibilityEvent> { 83 private int mType; 84 AccessibilityEventTypeMatcher(int type)85 public AccessibilityEventTypeMatcher(int type) { 86 super(); 87 mType = type; 88 } 89 90 @Override matchesSafely(AccessibilityEvent event)91 protected boolean matchesSafely(AccessibilityEvent event) { 92 return event.getEventType() == mType; 93 } 94 95 @Override describeTo(Description description)96 public void describeTo(Description description) { 97 description.appendText("Matching to type " + mType); 98 } 99 } 100 101 public static class WindowChangesMatcher extends TypeSafeMatcher<AccessibilityEvent> { 102 private int mWindowChanges; 103 WindowChangesMatcher(int windowChanges)104 public WindowChangesMatcher(int windowChanges) { 105 super(); 106 mWindowChanges = windowChanges; 107 } 108 109 @Override matchesSafely(AccessibilityEvent event)110 protected boolean matchesSafely(AccessibilityEvent event) { 111 return (event.getWindowChanges() & mWindowChanges) == mWindowChanges; 112 } 113 114 @Override describeTo(Description description)115 public void describeTo(Description description) { 116 description.appendText("With window change type " + mWindowChanges); 117 } 118 } 119 120 public static class ContentChangesMatcher extends TypeSafeMatcher<AccessibilityEvent> { 121 private int mContentChanges; 122 ContentChangesMatcher(int contentChanges)123 public ContentChangesMatcher(int contentChanges) { 124 super(); 125 mContentChanges = contentChanges; 126 } 127 128 @Override matchesSafely(AccessibilityEvent event)129 protected boolean matchesSafely(AccessibilityEvent event) { 130 return (event.getContentChangeTypes() & mContentChanges) == mContentChanges; 131 } 132 133 @Override describeTo(Description description)134 public void describeTo(Description description) { 135 description.appendText("With content change type " + mContentChanges); 136 } 137 } 138 139 public static class PropertyMatcher<T> extends TypeSafeMatcher<AccessibilityEvent> { 140 private T mProperty; 141 private String mDescription; 142 private BiPredicate<AccessibilityEvent, T> mComparator; 143 PropertyMatcher(T property, String description, BiPredicate<AccessibilityEvent, T> comparator)144 public PropertyMatcher(T property, String description, 145 BiPredicate<AccessibilityEvent, T> comparator) { 146 super(); 147 mProperty = property; 148 mDescription = description; 149 mComparator = comparator; 150 } 151 152 @Override matchesSafely(AccessibilityEvent event)153 protected boolean matchesSafely(AccessibilityEvent event) { 154 return mComparator.test(event, mProperty); 155 } 156 157 @Override describeTo(Description description)158 public void describeTo(Description description) { 159 description.appendText("Matching to " + mDescription + " " + mProperty.toString()); 160 } 161 } 162 163 public static class WindowTitleMatcher extends TypeSafeMatcher<AccessibilityEvent> { 164 private final UiAutomation mUiAutomation; 165 private final String mTitle; 166 WindowTitleMatcher(@onNull UiAutomation uiAutomation, @NonNull String title)167 public WindowTitleMatcher(@NonNull UiAutomation uiAutomation, @NonNull String title) { 168 super(); 169 mUiAutomation = uiAutomation; 170 mTitle = title; 171 } 172 173 @Override matchesSafely(AccessibilityEvent event)174 protected boolean matchesSafely(AccessibilityEvent event) { 175 final List<AccessibilityWindowInfo> windows = mUiAutomation.getWindows(); 176 final int eventWindowId = event.getWindowId(); 177 for (AccessibilityWindowInfo info : windows) { 178 if (eventWindowId == info.getId() && mTitle.equals(info.getTitle())) { 179 return true; 180 } 181 } 182 return false; 183 } 184 185 @Override describeTo(Description description)186 public void describeTo(Description description) { 187 description.appendText("With window title " + mTitle); 188 } 189 } 190 191 public static class WindowIdMatcher extends TypeSafeMatcher<AccessibilityEvent> { 192 private int mWindowId; 193 WindowIdMatcher(int windowId)194 public WindowIdMatcher(int windowId) { 195 super(); 196 mWindowId = windowId; 197 } 198 199 @Override matchesSafely(AccessibilityEvent event)200 protected boolean matchesSafely(AccessibilityEvent event) { 201 return event.getWindowId() == mWindowId; 202 } 203 204 @Override describeTo(Description description)205 public void describeTo(Description description) { 206 description.appendText("With window Id " + mWindowId); 207 } 208 } 209 } 210