| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.systemui.classifier.brightline; |
| |
| import android.view.MotionEvent; |
| |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.ListIterator; |
| |
| /** |
| * Maintains an ordered list of the last N milliseconds of MotionEvents. |
| * |
| * This class is simply a convenience class designed to look like a simple list, but that |
| * automatically discards old MotionEvents. It functions much like a queue - first in first out - |
| * but does not have a fixed size like a circular buffer. |
| */ |
| public class TimeLimitedMotionEventBuffer implements List<MotionEvent> { |
| |
| private final LinkedList<MotionEvent> mMotionEvents; |
| private long mMaxAgeMs; |
| |
| TimeLimitedMotionEventBuffer(long maxAgeMs) { |
| super(); |
| this.mMaxAgeMs = maxAgeMs; |
| this.mMotionEvents = new LinkedList<>(); |
| } |
| |
| private void ejectOldEvents() { |
| if (mMotionEvents.isEmpty()) { |
| return; |
| } |
| Iterator<MotionEvent> iter = listIterator(); |
| long mostRecentMs = mMotionEvents.getLast().getEventTime(); |
| while (iter.hasNext()) { |
| MotionEvent ev = iter.next(); |
| if (mostRecentMs - ev.getEventTime() > mMaxAgeMs) { |
| iter.remove(); |
| ev.recycle(); |
| } |
| } |
| } |
| |
| @Override |
| public void add(int index, MotionEvent element) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public MotionEvent remove(int index) { |
| return mMotionEvents.remove(index); |
| } |
| |
| @Override |
| public int indexOf(Object o) { |
| return mMotionEvents.indexOf(o); |
| } |
| |
| @Override |
| public int lastIndexOf(Object o) { |
| return mMotionEvents.lastIndexOf(o); |
| } |
| |
| @Override |
| public int size() { |
| return mMotionEvents.size(); |
| } |
| |
| @Override |
| public boolean isEmpty() { |
| return mMotionEvents.isEmpty(); |
| } |
| |
| @Override |
| public boolean contains(Object o) { |
| return mMotionEvents.contains(o); |
| } |
| |
| @Override |
| public Iterator<MotionEvent> iterator() { |
| return mMotionEvents.iterator(); |
| } |
| |
| @Override |
| public Object[] toArray() { |
| return mMotionEvents.toArray(); |
| } |
| |
| @Override |
| public <T> T[] toArray(T[] a) { |
| return mMotionEvents.toArray(a); |
| } |
| |
| @Override |
| public boolean add(MotionEvent element) { |
| boolean result = mMotionEvents.add(element); |
| ejectOldEvents(); |
| return result; |
| } |
| |
| @Override |
| public boolean remove(Object o) { |
| return mMotionEvents.remove(o); |
| } |
| |
| @Override |
| public boolean containsAll(Collection<?> c) { |
| return mMotionEvents.containsAll(c); |
| } |
| |
| @Override |
| public boolean addAll(Collection<? extends MotionEvent> collection) { |
| boolean result = mMotionEvents.addAll(collection); |
| ejectOldEvents(); |
| return result; |
| } |
| |
| @Override |
| public boolean addAll(int index, Collection<? extends MotionEvent> elements) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean removeAll(Collection<?> c) { |
| return mMotionEvents.removeAll(c); |
| } |
| |
| @Override |
| public boolean retainAll(Collection<?> c) { |
| return mMotionEvents.retainAll(c); |
| } |
| |
| @Override |
| public void clear() { |
| mMotionEvents.clear(); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| return mMotionEvents.equals(o); |
| } |
| |
| @Override |
| public int hashCode() { |
| return mMotionEvents.hashCode(); |
| } |
| |
| @Override |
| public MotionEvent get(int index) { |
| return mMotionEvents.get(index); |
| } |
| |
| @Override |
| public MotionEvent set(int index, MotionEvent element) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public ListIterator<MotionEvent> listIterator() { |
| return new Iter(0); |
| } |
| |
| @Override |
| public ListIterator<MotionEvent> listIterator(int index) { |
| return new Iter(index); |
| } |
| |
| @Override |
| public List<MotionEvent> subList(int fromIndex, int toIndex) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| class Iter implements ListIterator<MotionEvent> { |
| |
| private final ListIterator<MotionEvent> mIterator; |
| |
| Iter(int index) { |
| this.mIterator = mMotionEvents.listIterator(index); |
| } |
| |
| @Override |
| public boolean hasNext() { |
| return mIterator.hasNext(); |
| } |
| |
| @Override |
| public MotionEvent next() { |
| return mIterator.next(); |
| } |
| |
| @Override |
| public boolean hasPrevious() { |
| return mIterator.hasPrevious(); |
| } |
| |
| @Override |
| public MotionEvent previous() { |
| return mIterator.previous(); |
| } |
| |
| @Override |
| public int nextIndex() { |
| return mIterator.nextIndex(); |
| } |
| |
| @Override |
| public int previousIndex() { |
| return mIterator.previousIndex(); |
| } |
| |
| @Override |
| public void remove() { |
| mIterator.remove(); |
| } |
| |
| @Override |
| public void set(MotionEvent motionEvent) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void add(MotionEvent element) { |
| throw new UnsupportedOperationException(); |
| } |
| } |
| } |