1 /* 2 * Copyright (C) 2017 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.autofillservice.cts; 18 19 import static android.autofillservice.cts.Helper.CONNECTION_TIMEOUT_MS; 20 21 import static com.google.common.truth.Truth.assertWithMessage; 22 23 import android.view.View; 24 import android.view.autofill.AutofillManager.AutofillCallback; 25 26 import java.util.concurrent.BlockingQueue; 27 import java.util.concurrent.LinkedBlockingQueue; 28 import java.util.concurrent.TimeUnit; 29 30 /** 31 * Custom {@link AutofillCallback} used to recover events during tests. 32 */ 33 final class MyAutofillCallback extends AutofillCallback { 34 35 private final BlockingQueue<MyEvent> mEvents = new LinkedBlockingQueue<>(); 36 37 @Override onAutofillEvent(View view, int event)38 public void onAutofillEvent(View view, int event) { 39 mEvents.offer(new MyEvent(view, event)); 40 } 41 42 @Override onAutofillEvent(View view, int childId, int event)43 public void onAutofillEvent(View view, int childId, int event) { 44 mEvents.offer(new MyEvent(view, childId, event)); 45 } 46 47 /** 48 * Gets the next available event or fail if it times out. 49 */ getEvent()50 MyEvent getEvent() throws InterruptedException { 51 final MyEvent event = mEvents.poll(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS); 52 if (event == null) { 53 throw new RetryableException("no event in %d ms", CONNECTION_TIMEOUT_MS); 54 } 55 return event; 56 } 57 58 /** 59 * Used to assert there is no event left behind. 60 */ assertNumberUnhandledEvents(int expected)61 void assertNumberUnhandledEvents(int expected) { 62 assertWithMessage("Invalid number of events left").that(mEvents.size()).isEqualTo(expected); 63 } 64 65 /** 66 * Convenience method to assert an UI shown event for the given view was received. 67 */ assertUiShownEvent(View expectedView)68 MyEvent assertUiShownEvent(View expectedView) throws InterruptedException { 69 final MyEvent event = getEvent(); 70 assertWithMessage("Invalid type on event %s", event).that(event.event) 71 .isEqualTo(EVENT_INPUT_SHOWN); 72 assertWithMessage("Invalid view on event %s", event).that(event.view) 73 .isSameAs(expectedView); 74 return event; 75 } 76 77 /** 78 * Convenience method to assert an UI shown event for the given virtual view was received. 79 */ assertUiShownEvent(View expectedView, int expectedChildId)80 void assertUiShownEvent(View expectedView, int expectedChildId) throws InterruptedException { 81 final MyEvent event = assertUiShownEvent(expectedView); 82 assertWithMessage("Invalid child on event %s", event).that(event.childId) 83 .isSameAs(expectedChildId); 84 } 85 86 /** 87 * Convenience method to assert an UI hidden event for the given view was received. 88 */ assertUiHiddenEvent(View expectedView)89 MyEvent assertUiHiddenEvent(View expectedView) throws InterruptedException { 90 final MyEvent event = getEvent(); 91 assertWithMessage("Invalid type on event %s", event).that(event.event) 92 .isEqualTo(EVENT_INPUT_HIDDEN); 93 assertWithMessage("Invalid view on event %s", event).that(event.view) 94 .isSameAs(expectedView); 95 return event; 96 } 97 98 /** 99 * Convenience method to assert an UI hidden event for the given view was received. 100 */ assertUiHiddenEvent(View expectedView, int expectedChildId)101 void assertUiHiddenEvent(View expectedView, int expectedChildId) throws InterruptedException { 102 final MyEvent event = assertUiHiddenEvent(expectedView); 103 assertWithMessage("Invalid child on event %s", event).that(event.childId) 104 .isSameAs(expectedChildId); 105 } 106 107 /** 108 * Convenience method to assert an UI unavailable event for the given view was received. 109 */ assertUiUnavailableEvent(View expectedView)110 MyEvent assertUiUnavailableEvent(View expectedView) throws InterruptedException { 111 final MyEvent event = getEvent(); 112 assertWithMessage("Invalid type on event %s", event).that(event.event) 113 .isEqualTo(EVENT_INPUT_UNAVAILABLE); 114 assertWithMessage("Invalid view on event %s", event).that(event.view) 115 .isSameAs(expectedView); 116 return event; 117 } 118 119 /** 120 * Convenience method to assert an UI unavailable event for the given view was received. 121 */ assertUiUnavailableEvent(View expectedView, int expectedChildId)122 void assertUiUnavailableEvent(View expectedView, int expectedChildId) 123 throws InterruptedException { 124 final MyEvent event = assertUiUnavailableEvent(expectedView); 125 assertWithMessage("Invalid child on event %s", event).that(event.childId) 126 .isSameAs(expectedChildId); 127 } 128 129 private static final class MyEvent { 130 public final View view; 131 public final int childId; 132 public final int event; 133 MyEvent(View view, int event)134 MyEvent(View view, int event) { 135 this(view, View.NO_ID, event); 136 } 137 MyEvent(View view, int childId, int event)138 MyEvent(View view, int childId, int event) { 139 this.view = view; 140 this.childId = childId; 141 this.event = event; 142 } 143 144 @Override toString()145 public String toString() { 146 return event + ": " + view + " (childId: " + childId + ")"; 147 } 148 } 149 } 150