1 /* 2 * Copyright (C) 2019 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.utils; 18 19 import static android.view.MotionEvent.ACTION_HOVER_MOVE; 20 import static java.util.concurrent.TimeUnit.SECONDS; 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assert.fail; 25 26 import android.view.MotionEvent; 27 import android.view.View; 28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.concurrent.BlockingQueue; 31 import java.util.concurrent.LinkedBlockingQueue; 32 33 /** This Listener listens for and logs hover events so they can be checked later by tests. */ 34 public class EventCapturingHoverListener implements View.OnHoverListener { 35 36 private boolean shouldConsumeEvents; // whether or not to keep events from propagating to other 37 // listeners 38 private final BlockingQueue<MotionEvent> mEvents = new LinkedBlockingQueue<>(); 39 EventCapturingHoverListener(boolean shouldConsumeEvents)40 public EventCapturingHoverListener(boolean shouldConsumeEvents) { 41 this.shouldConsumeEvents = shouldConsumeEvents; 42 } 43 EventCapturingHoverListener()44 public EventCapturingHoverListener() { 45 this.shouldConsumeEvents = true; 46 } 47 48 @Override onHover(View view, MotionEvent MotionEvent)49 public boolean onHover(View view, MotionEvent MotionEvent) { 50 assertTrue(mEvents.offer(MotionEvent.obtain(MotionEvent))); 51 return shouldConsumeEvents; 52 } 53 54 /** Insure that no hover events have been detected. */ assertNonePropagated()55 public void assertNonePropagated() { 56 try { 57 long waitTime = 1; // seconds 58 MotionEvent event = mEvents.poll(waitTime, SECONDS); 59 if (event != null) { 60 fail("Unexpected touch event " + event.toString()); 61 } 62 } catch (InterruptedException e) { 63 throw new RuntimeException(e); 64 } 65 } 66 67 /** 68 * Check for the specified hover events. Note that specifying ACTION_HOVER_MOVE will match one 69 * or more consecutive ACTION_HOVER_MOVE events. 70 */ assertPropagated(int... eventTypes)71 public void assertPropagated(int... eventTypes) { 72 MotionEvent ev; 73 long waitTime = 5; // seconds 74 try { 75 List<String> expected = new ArrayList<>(); 76 List<String> received = new ArrayList<>(); 77 for (int e : eventTypes) { 78 expected.add(MotionEvent.actionToString(e)); 79 } 80 ev = mEvents.poll(waitTime, SECONDS); 81 assertNotNull( 82 "Expected " + expected + " but none present after " + waitTime + " seconds", 83 ev); 84 // By this point there is at least one received event. 85 received.add(MotionEvent.actionToString(ev.getActionMasked())); 86 ev = mEvents.poll(waitTime, SECONDS); 87 while (ev != null) { 88 int action = ev.getActionMasked(); 89 if (action != ACTION_HOVER_MOVE) { 90 received.add(MotionEvent.actionToString(action)); 91 } else { 92 // Add the current event if the previous received event was not ACTION_MOVE 93 String prev = received.get(received.size() - 1); 94 if (!prev.equals(MotionEvent.actionToString(ACTION_HOVER_MOVE))) { 95 received.add(MotionEvent.actionToString(action)); 96 } 97 } 98 ev = mEvents.poll(waitTime, SECONDS); 99 } 100 assertEquals(expected, received); 101 } catch (InterruptedException e) { 102 throw new RuntimeException(e); 103 } 104 } 105 } 106