• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 com.android.systemui.classifier;
18 
19 import android.view.MotionEvent;
20 
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.ListIterator;
26 
27 /**
28  * Maintains an ordered list of the last N milliseconds of MotionEvents.
29  *
30  * This class is simply a convenience class designed to look like a simple list, but that
31  * automatically discards old MotionEvents. It functions much like a queue - first in first out -
32  * but does not have a fixed size like a circular buffer.
33  */
34 public class TimeLimitedMotionEventBuffer implements List<MotionEvent> {
35 
36     private final List<MotionEvent> mMotionEvents;
37     private final long mMaxAgeMs;
38 
TimeLimitedMotionEventBuffer(long maxAgeMs)39     public TimeLimitedMotionEventBuffer(long maxAgeMs) {
40         super();
41         mMaxAgeMs = maxAgeMs;
42         mMotionEvents = new ArrayList<>();
43     }
44 
ejectOldEvents()45     private void ejectOldEvents() {
46         if (mMotionEvents.isEmpty()) {
47             return;
48         }
49         Iterator<MotionEvent> iter = listIterator();
50         long mostRecentMs = mMotionEvents.get(mMotionEvents.size() - 1).getEventTime();
51         while (iter.hasNext()) {
52             MotionEvent ev = iter.next();
53             if (mostRecentMs - ev.getEventTime() > mMaxAgeMs) {
54                 iter.remove();
55                 ev.recycle();
56             }
57         }
58     }
59 
60     @Override
add(int index, MotionEvent element)61     public void add(int index, MotionEvent element) {
62         throw new UnsupportedOperationException();
63     }
64 
65     @Override
remove(int index)66     public MotionEvent remove(int index) {
67         return mMotionEvents.remove(index);
68     }
69 
70     @Override
indexOf(Object o)71     public int indexOf(Object o) {
72         return mMotionEvents.indexOf(o);
73     }
74 
75     @Override
lastIndexOf(Object o)76     public int lastIndexOf(Object o) {
77         return mMotionEvents.lastIndexOf(o);
78     }
79 
80     @Override
size()81     public int size() {
82         return mMotionEvents.size();
83     }
84 
85     @Override
isEmpty()86     public boolean isEmpty() {
87         return mMotionEvents.isEmpty();
88     }
89 
90     @Override
contains(Object o)91     public boolean contains(Object o) {
92         return mMotionEvents.contains(o);
93     }
94 
95     @Override
iterator()96     public Iterator<MotionEvent> iterator() {
97         return mMotionEvents.iterator();
98     }
99 
100     @Override
toArray()101     public Object[] toArray() {
102         return mMotionEvents.toArray();
103     }
104 
105     @Override
toArray(T[] a)106     public <T> T[] toArray(T[] a) {
107         return mMotionEvents.toArray(a);
108     }
109 
110     @Override
add(MotionEvent element)111     public boolean add(MotionEvent element) {
112         boolean result = mMotionEvents.add(element);
113         ejectOldEvents();
114         return result;
115     }
116 
117     @Override
remove(Object o)118     public boolean remove(Object o) {
119         return mMotionEvents.remove(o);
120     }
121 
122     @Override
containsAll(Collection<?> c)123     public boolean containsAll(Collection<?> c) {
124         return mMotionEvents.containsAll(c);
125     }
126 
127     @Override
addAll(Collection<? extends MotionEvent> collection)128     public boolean addAll(Collection<? extends MotionEvent> collection) {
129         boolean result = mMotionEvents.addAll(collection);
130         ejectOldEvents();
131         return result;
132     }
133 
134     @Override
addAll(int index, Collection<? extends MotionEvent> elements)135     public boolean addAll(int index, Collection<? extends MotionEvent> elements) {
136         throw new UnsupportedOperationException();
137     }
138 
139     @Override
removeAll(Collection<?> c)140     public boolean removeAll(Collection<?> c) {
141         return mMotionEvents.removeAll(c);
142     }
143 
144     @Override
retainAll(Collection<?> c)145     public boolean retainAll(Collection<?> c) {
146         return mMotionEvents.retainAll(c);
147     }
148 
149     @Override
clear()150     public void clear() {
151         mMotionEvents.clear();
152     }
153 
154     @Override
equals(Object o)155     public boolean equals(Object o) {
156         return mMotionEvents.equals(o);
157     }
158 
159     @Override
hashCode()160     public int hashCode() {
161         return mMotionEvents.hashCode();
162     }
163 
164     @Override
get(int index)165     public MotionEvent get(int index) {
166         return mMotionEvents.get(index);
167     }
168 
169     @Override
set(int index, MotionEvent element)170     public MotionEvent set(int index, MotionEvent element) {
171         throw new UnsupportedOperationException();
172     }
173 
174     @Override
listIterator()175     public ListIterator<MotionEvent> listIterator() {
176         return new Iter(0);
177     }
178 
179     @Override
listIterator(int index)180     public ListIterator<MotionEvent> listIterator(int index) {
181         return new Iter(index);
182     }
183 
184     @Override
subList(int fromIndex, int toIndex)185     public List<MotionEvent> subList(int fromIndex, int toIndex) {
186         return mMotionEvents.subList(fromIndex, toIndex);
187     }
188 
189     class Iter implements ListIterator<MotionEvent> {
190 
191         private final ListIterator<MotionEvent> mIterator;
192 
Iter(int index)193         Iter(int index) {
194             this.mIterator = mMotionEvents.listIterator(index);
195         }
196 
197         @Override
hasNext()198         public boolean hasNext() {
199             return mIterator.hasNext();
200         }
201 
202         @Override
next()203         public MotionEvent next() {
204             return mIterator.next();
205         }
206 
207         @Override
hasPrevious()208         public boolean hasPrevious() {
209             return mIterator.hasPrevious();
210         }
211 
212         @Override
previous()213         public MotionEvent previous() {
214             return mIterator.previous();
215         }
216 
217         @Override
nextIndex()218         public int nextIndex() {
219             return mIterator.nextIndex();
220         }
221 
222         @Override
previousIndex()223         public int previousIndex() {
224             return mIterator.previousIndex();
225         }
226 
227         @Override
remove()228         public void remove() {
229             mIterator.remove();
230         }
231 
232         @Override
set(MotionEvent motionEvent)233         public void set(MotionEvent motionEvent) {
234             throw new UnsupportedOperationException();
235         }
236 
237         @Override
add(MotionEvent element)238         public void add(MotionEvent element) {
239             throw new UnsupportedOperationException();
240         }
241     }
242 }
243