Home | History | Annotate | Download | only in internal
      1 /*
      2  * Copyright (C) 2010 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.inputmethod.keyboard.internal;
     18 
     19 import android.util.Log;
     20 
     21 import java.util.ArrayList;
     22 
     23 public final class PointerTrackerQueue {
     24     private static final String TAG = PointerTrackerQueue.class.getSimpleName();
     25     private static final boolean DEBUG = false;
     26 
     27     public interface Element {
     28         public boolean isModifier();
     29         public boolean isInDraggingFinger();
     30         public void onPhantomUpEvent(long eventTime);
     31         public void cancelTrackingForAction();
     32     }
     33 
     34     private static final int INITIAL_CAPACITY = 10;
     35     // Note: {@link #mExpandableArrayOfActivePointers} and {@link #mArraySize} are synchronized by
     36     // {@link #mExpandableArrayOfActivePointers}
     37     private final ArrayList<Element> mExpandableArrayOfActivePointers =
     38             new ArrayList<>(INITIAL_CAPACITY);
     39     private int mArraySize = 0;
     40 
     41     public int size() {
     42         synchronized (mExpandableArrayOfActivePointers) {
     43             return mArraySize;
     44         }
     45     }
     46 
     47     public void add(final Element pointer) {
     48         synchronized (mExpandableArrayOfActivePointers) {
     49             if (DEBUG) {
     50                 Log.d(TAG, "add: " + pointer + " " + this);
     51             }
     52             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
     53             final int arraySize = mArraySize;
     54             if (arraySize < expandableArray.size()) {
     55                 expandableArray.set(arraySize, pointer);
     56             } else {
     57                 expandableArray.add(pointer);
     58             }
     59             mArraySize = arraySize + 1;
     60         }
     61     }
     62 
     63     public void remove(final Element pointer) {
     64         synchronized (mExpandableArrayOfActivePointers) {
     65             if (DEBUG) {
     66                 Log.d(TAG, "remove: " + pointer + " " + this);
     67             }
     68             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
     69             final int arraySize = mArraySize;
     70             int newIndex = 0;
     71             for (int index = 0; index < arraySize; index++) {
     72                 final Element element = expandableArray.get(index);
     73                 if (element == pointer) {
     74                     if (newIndex != index) {
     75                         Log.w(TAG, "Found duplicated element in remove: " + pointer);
     76                     }
     77                     continue; // Remove this element from the expandableArray.
     78                 }
     79                 if (newIndex != index) {
     80                     // Shift this element toward the beginning of the expandableArray.
     81                     expandableArray.set(newIndex, element);
     82                 }
     83                 newIndex++;
     84             }
     85             mArraySize = newIndex;
     86         }
     87     }
     88 
     89     public Element getOldestElement() {
     90         synchronized (mExpandableArrayOfActivePointers) {
     91             return (mArraySize == 0) ? null : mExpandableArrayOfActivePointers.get(0);
     92         }
     93     }
     94 
     95     public void releaseAllPointersOlderThan(final Element pointer, final long eventTime) {
     96         synchronized (mExpandableArrayOfActivePointers) {
     97             if (DEBUG) {
     98                 Log.d(TAG, "releaseAllPointerOlderThan: " + pointer + " " + this);
     99             }
    100             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    101             final int arraySize = mArraySize;
    102             int newIndex, index;
    103             for (newIndex = index = 0; index < arraySize; index++) {
    104                 final Element element = expandableArray.get(index);
    105                 if (element == pointer) {
    106                     break; // Stop releasing elements.
    107                 }
    108                 if (!element.isModifier()) {
    109                     element.onPhantomUpEvent(eventTime);
    110                     continue; // Remove this element from the expandableArray.
    111                 }
    112                 if (newIndex != index) {
    113                     // Shift this element toward the beginning of the expandableArray.
    114                     expandableArray.set(newIndex, element);
    115                 }
    116                 newIndex++;
    117             }
    118             // Shift rest of the expandableArray.
    119             int count = 0;
    120             for (; index < arraySize; index++) {
    121                 final Element element = expandableArray.get(index);
    122                 if (element == pointer) {
    123                     count++;
    124                     if (count > 1) {
    125                         Log.w(TAG, "Found duplicated element in releaseAllPointersOlderThan: "
    126                                 + pointer);
    127                     }
    128                 }
    129                 if (newIndex != index) {
    130                     // Shift this element toward the beginning of the expandableArray.
    131                     expandableArray.set(newIndex, expandableArray.get(index));
    132                 }
    133                 newIndex++;
    134             }
    135             mArraySize = newIndex;
    136         }
    137     }
    138 
    139     public void releaseAllPointers(final long eventTime) {
    140         releaseAllPointersExcept(null, eventTime);
    141     }
    142 
    143     public void releaseAllPointersExcept(final Element pointer, final long eventTime) {
    144         synchronized (mExpandableArrayOfActivePointers) {
    145             if (DEBUG) {
    146                 if (pointer == null) {
    147                     Log.d(TAG, "releaseAllPointers: " + this);
    148                 } else {
    149                     Log.d(TAG, "releaseAllPointerExcept: " + pointer + " " + this);
    150                 }
    151             }
    152             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    153             final int arraySize = mArraySize;
    154             int newIndex = 0, count = 0;
    155             for (int index = 0; index < arraySize; index++) {
    156                 final Element element = expandableArray.get(index);
    157                 if (element == pointer) {
    158                     count++;
    159                     if (count > 1) {
    160                         Log.w(TAG, "Found duplicated element in releaseAllPointersExcept: "
    161                                 + pointer);
    162                     }
    163                 } else {
    164                     element.onPhantomUpEvent(eventTime);
    165                     continue; // Remove this element from the expandableArray.
    166                 }
    167                 if (newIndex != index) {
    168                     // Shift this element toward the beginning of the expandableArray.
    169                     expandableArray.set(newIndex, element);
    170                 }
    171                 newIndex++;
    172             }
    173             mArraySize = newIndex;
    174         }
    175     }
    176 
    177     public boolean hasModifierKeyOlderThan(final Element pointer) {
    178         synchronized (mExpandableArrayOfActivePointers) {
    179             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    180             final int arraySize = mArraySize;
    181             for (int index = 0; index < arraySize; index++) {
    182                 final Element element = expandableArray.get(index);
    183                 if (element == pointer) {
    184                     return false; // Stop searching modifier key.
    185                 }
    186                 if (element.isModifier()) {
    187                     return true;
    188                 }
    189             }
    190             return false;
    191         }
    192     }
    193 
    194     public boolean isAnyInDraggingFinger() {
    195         synchronized (mExpandableArrayOfActivePointers) {
    196             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    197             final int arraySize = mArraySize;
    198             for (int index = 0; index < arraySize; index++) {
    199                 final Element element = expandableArray.get(index);
    200                 if (element.isInDraggingFinger()) {
    201                     return true;
    202                 }
    203             }
    204             return false;
    205         }
    206     }
    207 
    208     public void cancelAllPointerTrackers() {
    209         synchronized (mExpandableArrayOfActivePointers) {
    210             if (DEBUG) {
    211                 Log.d(TAG, "cancelAllPointerTracker: " + this);
    212             }
    213             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    214             final int arraySize = mArraySize;
    215             for (int index = 0; index < arraySize; index++) {
    216                 final Element element = expandableArray.get(index);
    217                 element.cancelTrackingForAction();
    218             }
    219         }
    220     }
    221 
    222     @Override
    223     public String toString() {
    224         synchronized (mExpandableArrayOfActivePointers) {
    225             final StringBuilder sb = new StringBuilder();
    226             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
    227             final int arraySize = mArraySize;
    228             for (int index = 0; index < arraySize; index++) {
    229                 final Element element = expandableArray.get(index);
    230                 if (sb.length() > 0) {
    231                     sb.append(" ");
    232                 }
    233                 sb.append(element.toString());
    234             }
    235             return "[" + sb.toString() + "]";
    236         }
    237     }
    238 }
    239