/* * Copyright (C) 2010 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.inputmethod.keyboard.internal; import android.util.Log; import java.util.ArrayList; public final class PointerTrackerQueue { private static final String TAG = PointerTrackerQueue.class.getSimpleName(); private static final boolean DEBUG = false; public interface Element { public boolean isModifier(); public boolean isInDraggingFinger(); public void onPhantomUpEvent(long eventTime); public void cancelTrackingForAction(); } private static final int INITIAL_CAPACITY = 10; // Note: {@link #mExpandableArrayOfActivePointers} and {@link #mArraySize} are synchronized by // {@link #mExpandableArrayOfActivePointers} private final ArrayList mExpandableArrayOfActivePointers = new ArrayList<>(INITIAL_CAPACITY); private int mArraySize = 0; public int size() { synchronized (mExpandableArrayOfActivePointers) { return mArraySize; } } public void add(final Element pointer) { synchronized (mExpandableArrayOfActivePointers) { if (DEBUG) { Log.d(TAG, "add: " + pointer + " " + this); } final ArrayList expandableArray = mExpandableArrayOfActivePointers; final int arraySize = mArraySize; if (arraySize < expandableArray.size()) { expandableArray.set(arraySize, pointer); } else { expandableArray.add(pointer); } mArraySize = arraySize + 1; } } public void remove(final Element pointer) { synchronized (mExpandableArrayOfActivePointers) { if (DEBUG) { Log.d(TAG, "remove: " + pointer + " " + this); } final ArrayList expandableArray = mExpandableArrayOfActivePointers; final int arraySize = mArraySize; int newIndex = 0; for (int index = 0; index < arraySize; index++) { final Element element = expandableArray.get(index); if (element == pointer) { if (newIndex != index) { Log.w(TAG, "Found duplicated element in remove: " + pointer); } continue; // Remove this element from the expandableArray. } if (newIndex != index) { // Shift this element toward the beginning of the expandableArray. expandableArray.set(newIndex, element); } newIndex++; } mArraySize = newIndex; } } public Element getOldestElement() { synchronized (mExpandableArrayOfActivePointers) { return (mArraySize == 0) ? null : mExpandableArrayOfActivePointers.get(0); } } public void releaseAllPointersOlderThan(final Element pointer, final long eventTime) { synchronized (mExpandableArrayOfActivePointers) { if (DEBUG) { Log.d(TAG, "releaseAllPointerOlderThan: " + pointer + " " + this); } final ArrayList expandableArray = mExpandableArrayOfActivePointers; final int arraySize = mArraySize; int newIndex, index; for (newIndex = index = 0; index < arraySize; index++) { final Element element = expandableArray.get(index); if (element == pointer) { break; // Stop releasing elements. } if (!element.isModifier()) { element.onPhantomUpEvent(eventTime); continue; // Remove this element from the expandableArray. } if (newIndex != index) { // Shift this element toward the beginning of the expandableArray. expandableArray.set(newIndex, element); } newIndex++; } // Shift rest of the expandableArray. int count = 0; for (; index < arraySize; index++) { final Element element = expandableArray.get(index); if (element == pointer) { count++; if (count > 1) { Log.w(TAG, "Found duplicated element in releaseAllPointersOlderThan: " + pointer); } } if (newIndex != index) { // Shift this element toward the beginning of the expandableArray. expandableArray.set(newIndex, expandableArray.get(index)); } newIndex++; } mArraySize = newIndex; } } public void releaseAllPointers(final long eventTime) { releaseAllPointersExcept(null, eventTime); } public void releaseAllPointersExcept(final Element pointer, final long eventTime) { synchronized (mExpandableArrayOfActivePointers) { if (DEBUG) { if (pointer == null) { Log.d(TAG, "releaseAllPointers: " + this); } else { Log.d(TAG, "releaseAllPointerExcept: " + pointer + " " + this); } } final ArrayList expandableArray = mExpandableArrayOfActivePointers; final int arraySize = mArraySize; int newIndex = 0, count = 0; for (int index = 0; index < arraySize; index++) { final Element element = expandableArray.get(index); if (element == pointer) { count++; if (count > 1) { Log.w(TAG, "Found duplicated element in releaseAllPointersExcept: " + pointer); } } else { element.onPhantomUpEvent(eventTime); continue; // Remove this element from the expandableArray. } if (newIndex != index) { // Shift this element toward the beginning of the expandableArray. expandableArray.set(newIndex, element); } newIndex++; } mArraySize = newIndex; } } public boolean hasModifierKeyOlderThan(final Element pointer) { synchronized (mExpandableArrayOfActivePointers) { final ArrayList expandableArray = mExpandableArrayOfActivePointers; final int arraySize = mArraySize; for (int index = 0; index < arraySize; index++) { final Element element = expandableArray.get(index); if (element == pointer) { return false; // Stop searching modifier key. } if (element.isModifier()) { return true; } } return false; } } public boolean isAnyInDraggingFinger() { synchronized (mExpandableArrayOfActivePointers) { final ArrayList expandableArray = mExpandableArrayOfActivePointers; final int arraySize = mArraySize; for (int index = 0; index < arraySize; index++) { final Element element = expandableArray.get(index); if (element.isInDraggingFinger()) { return true; } } return false; } } public void cancelAllPointerTrackers() { synchronized (mExpandableArrayOfActivePointers) { if (DEBUG) { Log.d(TAG, "cancelAllPointerTracker: " + this); } final ArrayList expandableArray = mExpandableArrayOfActivePointers; final int arraySize = mArraySize; for (int index = 0; index < arraySize; index++) { final Element element = expandableArray.get(index); element.cancelTrackingForAction(); } } } @Override public String toString() { synchronized (mExpandableArrayOfActivePointers) { final StringBuilder sb = new StringBuilder(); final ArrayList expandableArray = mExpandableArrayOfActivePointers; final int arraySize = mArraySize; for (int index = 0; index < arraySize; index++) { final Element element = expandableArray.get(index); if (sb.length() > 0) { sb.append(" "); } sb.append(element.toString()); } return "[" + sb.toString() + "]"; } } }