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