Merge "Import translations. DO NOT MERGE"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 4debdc2..0c3ccec 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -160,6 +160,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodSession.*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodCallback.*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/current.txt b/api/current.txt
index bb070c7..520d0fe 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -30194,6 +30194,8 @@
     method public void addFooterView(android.view.View);
     method public void addHeaderView(android.view.View, java.lang.Object, boolean);
     method public void addHeaderView(android.view.View);
+    method public boolean areFooterDividersEnabled();
+    method public boolean areHeaderDividersEnabled();
     method protected android.view.View findViewTraversal(int);
     method protected android.view.View findViewWithTagTraversal(java.lang.Object);
     method public android.widget.ListAdapter getAdapter();
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index bb0a6e1..4bd9b37 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -206,6 +206,7 @@
         }
         mSize = 0;
     }
+
     /**
      * Create a new ArrayMap with the mappings from the given ArrayMap.
      */
@@ -216,7 +217,6 @@
         }
     }
 
-
     /**
      * Make the array map empty.  All storage is released.
      */
@@ -236,8 +236,8 @@
      */
     public void ensureCapacity(int minimumCapacity) {
         if (mHashes.length < minimumCapacity) {
-            int[] ohashes = mHashes;
-            Object[] oarray = mArray;
+            final int[] ohashes = mHashes;
+            final Object[] oarray = mArray;
             allocArrays(minimumCapacity);
             if (mSize > 0) {
                 System.arraycopy(ohashes, 0, mHashes, 0, mSize);
@@ -493,6 +493,63 @@
         return mSize;
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * <p>This implementation returns false if the object is not a map, or
+     * if the maps have different sizes. Otherwise, for each key in this map,
+     * values of both maps are compared. If the values for any key are not
+     * equal, the method returns false, otherwise it returns true.
+     */
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (object instanceof Map) {
+            Map<?, ?> map = (Map<?, ?>) object;
+            if (size() != map.size()) {
+                return false;
+            }
+
+            try {
+                for (int i=0; i<mSize; i++) {
+                    K key = keyAt(i);
+                    V mine = valueAt(i);
+                    Object theirs = map.get(key);
+                    if (mine == null) {
+                        if (theirs != null || !map.containsKey(key)) {
+                            return false;
+                        }
+                    } else if (!mine.equals(theirs)) {
+                        return false;
+                    }
+                }
+            } catch (NullPointerException ignored) {
+                return false;
+            } catch (ClassCastException ignored) {
+                return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        final int[] hashes = mHashes;
+        final Object[] array = mArray;
+        int result = 0;
+        for (int i = 0, v = 1, s = mSize; i < s; i++, v+=2) {
+            Object value = array[v];
+            result += hashes[i] ^ (value == null ? 0 : value.hashCode());
+        }
+        return result;
+    }
+
     // ------------------------------------------------------------------------
     // Interop with traditional Java containers.  Not as efficient as using
     // specialized collection APIs.
@@ -632,64 +689,4 @@
     public Collection<V> values() {
         return getCollection().getValues();
     }
-
-    /**
-     * {@inheritDoc}
-     *
-     * <p>This implementation returns false if the object is not a map, or
-     * if the maps have different sizes. Otherwise, for each key in this map,
-     * values of both maps are compared. If the values for any key are not
-     * equal, the method returns false, otherwise it returns true.
-     */
-    @Override
-    public boolean equals(Object object) {
-        if (this == object) {
-            return true;
-        }
-        if (object instanceof Map) {
-            Map<?, ?> map = (Map<?, ?>) object;
-            if (size() != map.size()) {
-                return false;
-            }
-
-            try {
-                for (int i=0; i<mSize; i++) {
-                    K key = keyAt(i);
-                    V mine = valueAt(i);
-                    Object theirs = map.get(key);
-                    if (mine == null) {
-                        if (theirs != null || !map.containsKey(key)) {
-                            return false;
-                        }
-                    } else if (!mine.equals(theirs)) {
-                        return false;
-                    }
-                }
-            } catch (NullPointerException ignored) {
-                return false;
-            } catch (ClassCastException ignored) {
-                return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * <p>This implementation sums a hashcode using all keys and values.
-     */
-    @Override
-    public int hashCode() {
-        int result = 0;
-        for (int i=0; i<mSize; i++) {
-            K key = keyAt(i);
-            V value = valueAt(i);
-            result += (key == null ? 0 : key.hashCode())
-                    ^ (value == null ? 0 : value.hashCode());
-        }
-        return result;
-    }
-
 }
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
new file mode 100644
index 0000000..a84c47c
--- /dev/null
+++ b/core/java/android/util/ArraySet.java
@@ -0,0 +1,599 @@
+/*
+ * Copyright (C) 2013 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 android.util;
+
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * ArraySet is a generic set data structure that is designed to be more memory efficient than a
+ * traditional {@link java.util.HashSet}.  The design is very similar to
+ * {@link ArrayMap}, with all of the caveats described there.  This implementation is
+ * separate from ArrayMap, however, so the Object array contains only one item for each
+ * entry in the set (instead of a pair for a mapping).
+ *
+ * <p>Note that this implementation is not intended to be appropriate for data structures
+ * that may contain large numbers of items.  It is generally slower than a traditional
+ * HashSet, since lookups require a binary search and adds and removes require inserting
+ * and deleting entries in the array.  For containers holding up to hundreds of items,
+ * the performance difference is not significant, less than 50%.  For larger numbers of items
+ * this data structure should be avoided.</p>
+ *
+ * <p><b>Note:</b> unlike {@link java.util.HashSet}, this container does not support
+ * null values.</p>
+ *
+ * <p>Because this container is intended to better balance memory use, unlike most other
+ * standard Java containers it will shrink its array as items are removed from it.  Currently
+ * you have no control over this shrinking -- if you set a capacity and then remove an
+ * item, it may reduce the capacity to better match the current size.  In the future an
+ * explicitly call to set the capacity should turn off this aggressive shrinking behavior.</p>
+ *
+ * @hide
+ */
+public final class ArraySet<E> implements Collection<E>, Set<E> {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "ArraySet";
+
+    /**
+     * The minimum amount by which the capacity of a ArraySet will increase.
+     * This is tuned to be relatively space-efficient.
+     */
+    private static final int BASE_SIZE = 4;
+
+    /**
+     * Maximum number of entries to have in array caches.
+     */
+    private static final int CACHE_SIZE = 10;
+
+    /**
+     * Caches of small array objects to avoid spamming garbage.  The cache
+     * Object[] variable is a pointer to a linked list of array objects.
+     * The first entry in the array is a pointer to the next array in the
+     * list; the second entry is a pointer to the int[] hash code array for it.
+     */
+    static Object[] mBaseCache;
+    static int mBaseCacheSize;
+    static Object[] mTwiceBaseCache;
+    static int mTwiceBaseCacheSize;
+
+    int[] mHashes;
+    Object[] mArray;
+    int mSize;
+    MapCollections<E, E> mCollections;
+
+    private int indexOf(Object key, int hash) {
+        final int N = mSize;
+
+        // Important fast case: if nothing is in here, nothing to look for.
+        if (N == 0) {
+            return ~0;
+        }
+
+        int index = SparseArray.binarySearch(mHashes, N, hash);
+
+        // If the hash code wasn't found, then we have no entry for this key.
+        if (index < 0) {
+            return index;
+        }
+
+        // If the key at the returned index matches, that's what we want.
+        if (mArray[index].equals(key)) {
+            return index;
+        }
+
+        // Search for a matching key after the index.
+        int end;
+        for (end = index + 1; end < N && mHashes[end] == hash; end++) {
+            if (mArray[end].equals(key)) return end;
+        }
+
+        // Search for a matching key before the index.
+        for (int i = index - 1; i >= 0 && mHashes[i] == hash; i--) {
+            if (mArray[i].equals(key)) return i;
+        }
+
+        // Key not found -- return negative value indicating where a
+        // new entry for this key should go.  We use the end of the
+        // hash chain to reduce the number of array entries that will
+        // need to be copied when inserting.
+        return ~end;
+    }
+
+    private void allocArrays(final int size) {
+        if (size == (BASE_SIZE*2)) {
+            synchronized (ArraySet.class) {
+                if (mTwiceBaseCache != null) {
+                    final Object[] array = mTwiceBaseCache;
+                    mArray = array;
+                    mTwiceBaseCache = (Object[])array[0];
+                    mHashes = (int[])array[1];
+                    array[0] = array[1] = null;
+                    mTwiceBaseCacheSize--;
+                    if (DEBUG) Log.d(TAG, "Retrieving 2x cache " + mHashes
+                            + " now have " + mTwiceBaseCacheSize + " entries");
+                    return;
+                }
+            }
+        } else if (size == BASE_SIZE) {
+            synchronized (ArraySet.class) {
+                if (mBaseCache != null) {
+                    final Object[] array = mBaseCache;
+                    mArray = array;
+                    mBaseCache = (Object[])array[0];
+                    mHashes = (int[])array[1];
+                    array[0] = array[1] = null;
+                    mBaseCacheSize--;
+                    if (DEBUG) Log.d(TAG, "Retrieving 1x cache " + mHashes
+                            + " now have " + mBaseCacheSize + " entries");
+                    return;
+                }
+            }
+        }
+
+        mHashes = new int[size];
+        mArray = new Object[size];
+    }
+
+    private static void freeArrays(final int[] hashes, final Object[] array, final int size) {
+        if (hashes.length == (BASE_SIZE*2)) {
+            synchronized (ArraySet.class) {
+                if (mTwiceBaseCacheSize < CACHE_SIZE) {
+                    array[0] = mTwiceBaseCache;
+                    array[1] = hashes;
+                    for (int i=size-1; i>=2; i--) {
+                        array[i] = null;
+                    }
+                    mTwiceBaseCache = array;
+                    mTwiceBaseCacheSize++;
+                    if (DEBUG) Log.d(TAG, "Storing 2x cache " + array
+                            + " now have " + mTwiceBaseCacheSize + " entries");
+                }
+            }
+        } else if (hashes.length == BASE_SIZE) {
+            synchronized (ArraySet.class) {
+                if (mBaseCacheSize < CACHE_SIZE) {
+                    array[0] = mBaseCache;
+                    array[1] = hashes;
+                    for (int i=size-1; i>=2; i--) {
+                        array[i] = null;
+                    }
+                    mBaseCache = array;
+                    mBaseCacheSize++;
+                    if (DEBUG) Log.d(TAG, "Storing 1x cache " + array
+                            + " now have " + mBaseCacheSize + " entries");
+                }
+            }
+        }
+    }
+
+    /**
+     * Create a new empty ArraySet.  The default capacity of an array map is 0, and
+     * will grow once items are added to it.
+     */
+    public ArraySet() {
+        mHashes = SparseArray.EMPTY_INTS;
+        mArray = SparseArray.EMPTY_OBJECTS;
+        mSize = 0;
+    }
+
+    /**
+     * Create a new ArraySet with a given initial capacity.
+     */
+    public ArraySet(int capacity) {
+        if (capacity == 0) {
+            mHashes = SparseArray.EMPTY_INTS;
+            mArray = SparseArray.EMPTY_OBJECTS;
+        } else {
+            allocArrays(capacity);
+        }
+        mSize = 0;
+    }
+
+    /**
+     * Create a new ArraySet with the mappings from the given ArraySet.
+     */
+    public ArraySet(ArraySet set) {
+        this();
+        if (set != null) {
+            addAll(set);
+        }
+    }
+
+
+    /**
+     * Make the array map empty.  All storage is released.
+     */
+    @Override
+    public void clear() {
+        if (mSize != 0) {
+            freeArrays(mHashes, mArray, mSize);
+            mHashes = SparseArray.EMPTY_INTS;
+            mArray = SparseArray.EMPTY_OBJECTS;
+            mSize = 0;
+        }
+    }
+
+    /**
+     * Ensure the array map can hold at least <var>minimumCapacity</var>
+     * items.
+     */
+    public void ensureCapacity(int minimumCapacity) {
+        if (mHashes.length < minimumCapacity) {
+            final int[] ohashes = mHashes;
+            final Object[] oarray = mArray;
+            allocArrays(minimumCapacity);
+            if (mSize > 0) {
+                System.arraycopy(ohashes, 0, mHashes, 0, mSize);
+                System.arraycopy(oarray, 0, mArray, 0, mSize);
+            }
+            freeArrays(ohashes, oarray, mSize);
+        }
+    }
+
+    /**
+     * Check whether a value exists in the set.
+     *
+     * @param key The value to search for.
+     * @return Returns true if the value exists, else false.
+     */
+    @Override
+    public boolean contains(Object key) {
+        return indexOf(key, key.hashCode()) >= 0;
+    }
+
+    /**
+     * Return the value at the given index in the array.
+     * @param index The desired index, must be between 0 and {@link #size()}-1.
+     * @return Returns the value stored at the given index.
+     */
+    public E valueAt(int index) {
+        return (E)mArray[index];
+    }
+
+    /**
+     * Return true if the array map contains no items.
+     */
+    @Override
+    public boolean isEmpty() {
+        return mSize <= 0;
+    }
+
+    /**
+     * Adds the specified object to this set. The set is not modified if it
+     * already contains the object.
+     *
+     * @param value the object to add.
+     * @return {@code true} if this set is modified, {@code false} otherwise.
+     * @throws ClassCastException
+     *             when the class of the object is inappropriate for this set.
+     */
+    @Override
+    public boolean add(E value) {
+        final int hash = value.hashCode();
+        int index = indexOf(value, hash);
+        if (index >= 0) {
+            return false;
+        }
+
+        index = ~index;
+        if (mSize >= mHashes.length) {
+            final int n = mSize >= (BASE_SIZE*2) ? (mSize+(mSize>>1))
+                    : (mSize >= BASE_SIZE ? (BASE_SIZE*2) : BASE_SIZE);
+
+            if (DEBUG) Log.d(TAG, "add: grow from " + mHashes.length + " to " + n);
+
+            final int[] ohashes = mHashes;
+            final Object[] oarray = mArray;
+            allocArrays(n);
+
+            if (mHashes.length > 0) {
+                if (DEBUG) Log.d(TAG, "add: copy 0-" + mSize + " to 0");
+                System.arraycopy(ohashes, 0, mHashes, 0, ohashes.length);
+                System.arraycopy(oarray, 0, mArray, 0, oarray.length);
+            }
+
+            freeArrays(ohashes, oarray, mSize);
+        }
+
+        if (index < mSize) {
+            if (DEBUG) Log.d(TAG, "add: move " + index + "-" + (mSize-index)
+                    + " to " + (index+1));
+            System.arraycopy(mHashes, index, mHashes, index + 1, mSize - index);
+            System.arraycopy(mArray, index, mArray, index + 1, mSize - index);
+        }
+
+        mHashes[index] = hash;
+        mArray[index] = value;
+        mSize++;
+        return true;
+    }
+
+    /**
+     * Perform a {@link #add(Object)} of all values in <var>array</var>
+     * @param array The array whose contents are to be retrieved.
+     */
+    public void putAll(ArraySet<? extends E> array) {
+        final int N = array.mSize;
+        ensureCapacity(mSize + N);
+        if (mSize == 0) {
+            if (N > 0) {
+                System.arraycopy(array.mHashes, 0, mHashes, 0, N);
+                System.arraycopy(array.mArray, 0, mArray, 0, N);
+                mSize = N;
+            }
+        } else {
+            for (int i=0; i<N; i++) {
+                add(array.valueAt(i));
+            }
+        }
+    }
+
+    /**
+     * Removes the specified object from this set.
+     *
+     * @param object the object to remove.
+     * @return {@code true} if this set was modified, {@code false} otherwise.
+     */
+    @Override
+    public boolean remove(Object object) {
+        int index = indexOf(object, object.hashCode());
+        if (index >= 0) {
+            removeAt(index);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Remove the key/value mapping at the given index.
+     * @param index The desired index, must be between 0 and {@link #size()}-1.
+     * @return Returns the value that was stored at this index.
+     */
+    public E removeAt(int index) {
+        final E old = (E)mArray[index];
+        if (mSize <= 1) {
+            // Now empty.
+            if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to 0");
+            freeArrays(mHashes, mArray, mSize);
+            mHashes = SparseArray.EMPTY_INTS;
+            mArray = SparseArray.EMPTY_OBJECTS;
+            mSize = 0;
+        } else {
+            if (mHashes.length > (BASE_SIZE*2) && mSize < mHashes.length/3) {
+                // Shrunk enough to reduce size of arrays.  We don't allow it to
+                // shrink smaller than (BASE_SIZE*2) to avoid flapping between
+                // that and BASE_SIZE.
+                final int n = mSize > (BASE_SIZE*2) ? (mSize + (mSize>>1)) : (BASE_SIZE*2);
+
+                if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to " + n);
+
+                final int[] ohashes = mHashes;
+                final Object[] oarray = mArray;
+                allocArrays(n);
+
+                mSize--;
+                if (index > 0) {
+                    if (DEBUG) Log.d(TAG, "remove: copy from 0-" + index + " to 0");
+                    System.arraycopy(ohashes, 0, mHashes, 0, index);
+                    System.arraycopy(oarray, 0, mArray, 0, index);
+                }
+                if (index < mSize) {
+                    if (DEBUG) Log.d(TAG, "remove: copy from " + (index+1) + "-" + mSize
+                            + " to " + index);
+                    System.arraycopy(ohashes, index + 1, mHashes, index, mSize - index);
+                    System.arraycopy(oarray, index + 1, mArray, index, mSize - index);
+                }
+            } else {
+                mSize--;
+                if (index < mSize) {
+                    if (DEBUG) Log.d(TAG, "remove: move " + (index+1) + "-" + mSize
+                            + " to " + index);
+                    System.arraycopy(mHashes, index + 1, mHashes, index, mSize - index);
+                    System.arraycopy(mArray, index + 1, mArray, index, mSize - index);
+                }
+                mArray[mSize] = null;
+            }
+        }
+        return old;
+    }
+
+    /**
+     * Return the number of items in this array map.
+     */
+    @Override
+    public int size() {
+        return mSize;
+    }
+
+    @Override
+    public Object[] toArray() {
+        Object[] result = new Object[mSize];
+        System.arraycopy(mArray, 0, result, 0, mSize);
+        return result;
+    }
+
+    @Override
+    public <T> T[] toArray(T[] array) {
+        if (array.length < mSize) {
+            @SuppressWarnings("unchecked") T[] newArray
+                = (T[]) Array.newInstance(array.getClass().getComponentType(), mSize);
+            array = newArray;
+        }
+        System.arraycopy(mArray, 0, array, 0, mSize);
+        if (array.length > mSize) {
+            array[mSize] = null;
+        }
+        return array;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>This implementation returns false if the object is not a set, or
+     * if the sets have different sizes.  Otherwise, for each value in this
+     * set, it checks to make sure the value also exists in the other set.
+     * If any value doesn't exist, the method returns false; otherwise, it
+     * returns true.
+     */
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (object instanceof Set) {
+            Set<?> set = (Set<?>) object;
+            if (size() != set.size()) {
+                return false;
+            }
+
+            try {
+                for (int i=0; i<mSize; i++) {
+                    E mine = valueAt(i);
+                    if (!set.contains(mine)) {
+                        return false;
+                    }
+                }
+            } catch (NullPointerException ignored) {
+                return false;
+            } catch (ClassCastException ignored) {
+                return false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        final int[] hashes = mHashes;
+        int result = 0;
+        for (int i = 0, s = mSize; i < s; i++) {
+            result += hashes[i];
+        }
+        return result;
+    }
+
+    // ------------------------------------------------------------------------
+    // Interop with traditional Java containers.  Not as efficient as using
+    // specialized collection APIs.
+    // ------------------------------------------------------------------------
+
+    private MapCollections<E, E> getCollection() {
+        if (mCollections == null) {
+            mCollections = new MapCollections<E, E>() {
+                @Override
+                protected int colGetSize() {
+                    return mSize;
+                }
+
+                @Override
+                protected Object colGetEntry(int index, int offset) {
+                    return mArray[index];
+                }
+
+                @Override
+                protected int colIndexOfKey(Object key) {
+                    return indexOf(key, key.hashCode());
+                }
+
+                @Override
+                protected int colIndexOfValue(Object value) {
+                    return indexOf(value, value.hashCode());
+                }
+
+                @Override
+                protected Map<E, E> colGetMap() {
+                    throw new UnsupportedOperationException("not a map");
+                }
+
+                @Override
+                protected void colPut(E key, E value) {
+                    add(key);
+                }
+
+                @Override
+                protected E colSetValue(int index, E value) {
+                    throw new UnsupportedOperationException("not a map");
+                }
+
+                @Override
+                protected void colRemoveAt(int index) {
+                    removeAt(index);
+                }
+
+                @Override
+                protected void colClear() {
+                    clear();
+                }
+            };
+        }
+        return mCollections;
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+        return getCollection().getKeySet().iterator();
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> collection) {
+        Iterator<?> it = collection.iterator();
+        while (it.hasNext()) {
+            if (!contains(it.next())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends E> collection) {
+        ensureCapacity(mSize + collection.size());
+        boolean added = false;
+        for (E value : collection) {
+            added |= add(value);
+        }
+        return added;
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> collection) {
+        boolean removed = false;
+        for (Object value : collection) {
+            removed |= remove(value);
+        }
+        return removed;
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> collection) {
+        boolean removed = false;
+        for (int i=mSize-1; i>=0; i--) {
+            if (!collection.contains(mArray[i])) {
+                removeAt(i);
+                removed = true;
+            }
+        }
+        return removed;
+    }
+}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 6291e62..c735dd7 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -408,11 +408,6 @@
         public int getLidState();
 
         /**
-         * Creates an input channel that will receive all input from the input dispatcher.
-         */
-        public InputChannel monitorInput(String name);
-
-        /**
          * Switch the keyboard layout for the given device.
          * Direction should be +1 or -1 to go to the next or previous keyboard layout.
          */
@@ -425,6 +420,21 @@
          * Return the window manager lock needed to correctly call "Lw" methods.
          */
         public Object getWindowManagerLock();
+
+        /** Register a system listener for touch events */
+        void registerPointerEventListener(PointerEventListener listener);
+
+        /** Unregister a system listener for touch events */
+        void unregisterPointerEventListener(PointerEventListener listener);
+    }
+
+    public interface PointerEventListener {
+        /**
+         * 1. onPointerEvent will be called on the service.UiThread.
+         * 2. motionEvent will be recycled after onPointerEvent returns so if it is needed later a
+         * copy() must be made and the copy must be recycled.
+         **/
+        public void onPointerEvent(MotionEvent motionEvent);
     }
 
     /** Window has been added to the screen. */
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index fc9c000..aa33384 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -37,12 +38,13 @@
  */
 class FastScroller {
     private static final String TAG = "FastScroller";
-   
+
     // Minimum number of pages to justify showing a fast scroll thumb
     private static int MIN_PAGES = 4;
     // Scroll thumb not showing
     private static final int STATE_NONE = 0;
     // Not implemented yet - fade-in transition
+    @SuppressWarnings("unused")
     private static final int STATE_ENTER = 1;
     // Scroll thumb visible and moving along with the scrollbar
     private static final int STATE_VISIBLE = 2;
@@ -75,7 +77,7 @@
 
     private static final int OVERLAY_FLOATING = 0;
     private static final int OVERLAY_AT_THUMB = 1;
-    
+
     private Drawable mThumbDrawable;
     private Drawable mOverlayDrawable;
     private Drawable mTrackDrawable;
@@ -89,6 +91,7 @@
 
     private RectF mOverlayPos;
     private int mOverlaySize;
+    private int mOverlayPadding;
 
     AbsListView mList;
     boolean mScrollCompleted;
@@ -97,21 +100,21 @@
     private int mListOffset;
     private int mItemCount = -1;
     private boolean mLongList;
-    
+
     private Object [] mSections;
     private String mSectionText;
     private boolean mDrawOverlay;
     private ScrollFade mScrollFade;
-    
+
     private int mState;
-    
+
     private Handler mHandler = new Handler();
-    
+
     BaseAdapter mListAdapter;
     private SectionIndexer mSectionIndexer;
 
     private boolean mChangedBounds;
-    
+
     private int mPosition;
 
     private boolean mAlwaysShow;
@@ -130,6 +133,7 @@
     private final Rect mTmpRect = new Rect();
 
     private final Runnable mDeferStartDrag = new Runnable() {
+        @Override
         public void run() {
             if (mList.mIsAttached) {
                 beginDrag();
@@ -237,11 +241,11 @@
         mState = state;
         refreshDrawableState();
     }
-    
+
     public int getState() {
         return mState;
     }
-    
+
     private void resetThumbPos() {
         final int viewWidth = mList.getWidth();
         // Bounds are always top right. Y coordinate get's translated during draw
@@ -255,7 +259,7 @@
         }
         mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX);
     }
-    
+
     private void useThumbDrawable(Context context, Drawable drawable) {
         mThumbDrawable = drawable;
         if (drawable instanceof NinePatchDrawable) {
@@ -272,20 +276,23 @@
 
     private void init(Context context) {
         // Get both the scrollbar states drawables
-        TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS);
+        final TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS);
         useThumbDrawable(context, ta.getDrawable(THUMB_DRAWABLE));
         mTrackDrawable = ta.getDrawable(TRACK_DRAWABLE);
-        
+
         mOverlayDrawableLeft = ta.getDrawable(PREVIEW_BACKGROUND_LEFT);
         mOverlayDrawableRight = ta.getDrawable(PREVIEW_BACKGROUND_RIGHT);
         mOverlayPosition = ta.getInt(OVERLAY_POSITION, OVERLAY_FLOATING);
-        
+
         mScrollCompleted = true;
 
         getSectionsFromIndexer();
 
-        mOverlaySize = context.getResources().getDimensionPixelSize(
+        final Resources res = context.getResources();
+        mOverlaySize = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.fastscroll_overlay_size);
+        mOverlayPadding = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.fastscroll_overlay_padding);
         mOverlayPos = new RectF();
         mScrollFade = new ScrollFade();
         mPaint = new Paint();
@@ -302,7 +309,7 @@
         if (mList.getWidth() > 0 && mList.getHeight() > 0) {
             onSizeChanged(mList.getWidth(), mList.getHeight(), 0, 0);
         }
-        
+
         mState = STATE_NONE;
         refreshDrawableState();
 
@@ -315,17 +322,17 @@
 
         setScrollbarPosition(mList.getVerticalScrollbarPosition());
     }
-    
+
     void stop() {
         setState(STATE_NONE);
     }
-    
+
     boolean isVisible() {
         return !(mState == STATE_NONE);
     }
-    
+
     public void draw(Canvas canvas) {
-        
+
         if (mState == STATE_NONE) {
             // No need to draw anything
             return;
@@ -371,44 +378,53 @@
 
         // If user is dragging the scroll bar, draw the alphabet overlay
         if (mState == STATE_DRAGGING && mDrawOverlay) {
-            if (mOverlayPosition == OVERLAY_AT_THUMB) {
-                int left = 0;
-                switch (mPosition) {
-                    default:
-                    case View.SCROLLBAR_POSITION_RIGHT:
-                        left = Math.max(0,
-                                mThumbDrawable.getBounds().left - mThumbW - mOverlaySize);
-                        break;
-                    case View.SCROLLBAR_POSITION_LEFT:
-                        left = Math.min(mThumbDrawable.getBounds().right + mThumbW,
-                                mList.getWidth() - mOverlaySize);
-                        break;
-                }
-
-                int top = Math.max(0,
-                        Math.min(y + (mThumbH - mOverlaySize) / 2, mList.getHeight() - mOverlaySize));
-
-                final RectF pos = mOverlayPos;
-                pos.left = left;
-                pos.right = pos.left + mOverlaySize;
-                pos.top = top;
-                pos.bottom = pos.top + mOverlaySize;
-                if (mOverlayDrawable != null) {
-                    mOverlayDrawable.setBounds((int) pos.left, (int) pos.top,
-                            (int) pos.right, (int) pos.bottom);
-                }
-            }
-            mOverlayDrawable.draw(canvas);
+            final Drawable overlay = mOverlayDrawable;
             final Paint paint = mPaint;
-            float descent = paint.descent();
-            final RectF rectF = mOverlayPos;
+            final String sectionText = mSectionText;
             final Rect tmpRect = mTmpRect;
-            mOverlayDrawable.getPadding(tmpRect);
-            final int hOff = (tmpRect.right - tmpRect.left) / 2;
-            final int vOff = (tmpRect.bottom - tmpRect.top) / 2;
-            canvas.drawText(mSectionText, (int) (rectF.left + rectF.right) / 2 - hOff,
-                    (int) (rectF.bottom + rectF.top) / 2 + mOverlaySize / 4 - descent - vOff,
-                    paint);
+
+            // TODO: Use a text view in an overlay for transition animations and
+            // handling of text overflow.
+            paint.getTextBounds(sectionText, 0, sectionText.length(), tmpRect);
+            final int textWidth = tmpRect.width();
+            final int textHeight = tmpRect.height();
+
+            overlay.getPadding(tmpRect);
+            final int overlayWidth = Math.max(
+                    mOverlaySize, textWidth + tmpRect.left + tmpRect.right + mOverlayPadding * 2);
+            final int overlayHeight = Math.max(
+                    mOverlaySize, textHeight + tmpRect.top + tmpRect.bottom + mOverlayPadding * 2);
+            final RectF pos = mOverlayPos;
+
+            if (mOverlayPosition == OVERLAY_AT_THUMB) {
+                final Rect thumbBounds = mThumbDrawable.getBounds();
+
+                switch (mPosition) {
+                    case View.SCROLLBAR_POSITION_LEFT:
+                        pos.left = Math.min(
+                                thumbBounds.right + mThumbW, mList.getWidth() - overlayWidth);
+                        break;
+                    case View.SCROLLBAR_POSITION_RIGHT:
+                    default:
+                        pos.left = Math.max(0, thumbBounds.left - mThumbW - overlayWidth);
+                        break;
+                }
+
+                pos.top = Math.max(0, Math.min(
+                        y + (mThumbH - overlayHeight) / 2, mList.getHeight() - overlayHeight));
+            }
+
+            pos.right = pos.left + overlayWidth;
+            pos.bottom = pos.top + overlayHeight;
+
+            overlay.setBounds((int) pos.left, (int) pos.top, (int) pos.right, (int) pos.bottom);
+            overlay.draw(canvas);
+
+            final float hOff = (tmpRect.right - tmpRect.left) / 2.0f;
+            final float vOff = (tmpRect.bottom - tmpRect.top) / 2.0f;
+            final float cX = pos.centerX() - hOff;
+            final float cY = pos.centerY() + (overlayHeight / 4.0f) - paint.descent() - vOff;
+            canvas.drawText(mSectionText, cX, cY, paint);
         } else if (mState == STATE_EXIT) {
             if (alpha == 0) { // Done with exit
                 setState(STATE_NONE);
@@ -467,7 +483,7 @@
         }
     }
 
-    void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 
+    void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
             int totalItemCount) {
         // Are there enough pages to require fast scroll? Recompute only if total count changes
         if (mItemCount != totalItemCount && visibleItemCount > 0) {
@@ -577,7 +593,7 @@
             if (section < nSections - 1) {
                 nextIndex = mSectionIndexer.getPositionForSection(section + 1);
             }
-            
+
             // Find the previous index if we're slicing the previous section
             if (nextIndex == index) {
                 // Non-existent letter
@@ -597,9 +613,9 @@
                 }
             }
             // Find the next index, in case the assumed next index is not
-            // unique. For instance, if there is no P, then request for P's 
+            // unique. For instance, if there is no P, then request for P's
             // position actually returns Q's. So we need to look ahead to make
-            // sure that there is really a Q at Q's position. If not, move 
+            // sure that there is really a Q at Q's position. If not, move
             // further down...
             int nextNextSection = nextSection + 1;
             while (nextNextSection < nSections &&
@@ -609,18 +625,18 @@
             }
             // Compute the beginning and ending scroll range percentage of the
             // currently visible letter. This could be equal to or greater than
-            // (1 / nSections). 
+            // (1 / nSections).
             float fPrev = (float) prevSection / nSections;
             float fNext = (float) nextSection / nSections;
             if (prevSection == exactSection && position - fPrev < fThreshold) {
                 index = prevIndex;
             } else {
-                index = prevIndex + (int) ((nextIndex - prevIndex) * (position - fPrev) 
+                index = prevIndex + (int) ((nextIndex - prevIndex) * (position - fPrev)
                     / (fNext - fPrev));
             }
             // Don't overflow
             if (index > count - 1) index = count - 1;
-            
+
             if (mList instanceof ExpandableListView) {
                 ExpandableListView expList = (ExpandableListView) mList;
                 expList.setSelectionFromTop(expList.getFlatListPosition(
@@ -705,7 +721,7 @@
         mList.onTouchEvent(cancelFling);
         cancelFling.recycle();
     }
-    
+
     void cancelPendingDrag() {
         mList.removeCallbacks(mDeferStartDrag);
         mPendingDrag = false;
@@ -862,18 +878,18 @@
     }
 
     public class ScrollFade implements Runnable {
-        
+
         long mStartTime;
         long mFadeDuration;
         static final int ALPHA_MAX = 208;
         static final long FADE_DURATION = 200;
-        
+
         void startFade() {
             mFadeDuration = FADE_DURATION;
             mStartTime = SystemClock.uptimeMillis();
             setState(STATE_EXIT);
         }
-        
+
         int getAlpha() {
             if (getState() != STATE_EXIT) {
                 return ALPHA_MAX;
@@ -883,17 +899,18 @@
             if (now > mStartTime + mFadeDuration) {
                 alpha = 0;
             } else {
-                alpha = (int) (ALPHA_MAX - ((now - mStartTime) * ALPHA_MAX) / mFadeDuration); 
+                alpha = (int) (ALPHA_MAX - ((now - mStartTime) * ALPHA_MAX) / mFadeDuration);
             }
             return alpha;
         }
-        
+
+        @Override
         public void run() {
             if (getState() != STATE_EXIT) {
                 startFade();
                 return;
             }
-            
+
             if (getAlpha() > 0) {
                 mList.invalidate();
             } else {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 001d99c..ee22811 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -240,35 +240,39 @@
     }
 
     /**
-     * Add a fixed view to appear at the top of the list. If addHeaderView is
+     * Add a fixed view to appear at the top of the list. If this method is
      * called more than once, the views will appear in the order they were
      * added. Views added using this call can take focus if they want.
      * <p>
-     * NOTE: Call this before calling setAdapter. This is so ListView can wrap
-     * the supplied cursor with one that will also account for header and footer
-     * views.
+     * Note: When first introduced, this method could only be called before
+     * setting the adapter with {@link #setAdapter(ListAdapter)}. Starting with
+     * {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE}, this method may be
+     * called at any time. If the ListView's adapter does not extend
+     * {@link HeaderViewListAdapter}, it will be wrapped with a supporting
+     * instance of {@link WrapperListAdapter}.
      *
      * @param v The view to add.
      * @param data Data to associate with this view
      * @param isSelectable whether the item is selectable
      */
     public void addHeaderView(View v, Object data, boolean isSelectable) {
-
-        if (mAdapter != null && ! (mAdapter instanceof HeaderViewListAdapter)) {
-            throw new IllegalStateException(
-                    "Cannot add header view to list -- setAdapter has already been called.");
-        }
-
-        FixedViewInfo info = new FixedViewInfo();
+        final FixedViewInfo info = new FixedViewInfo();
         info.view = v;
         info.data = data;
         info.isSelectable = isSelectable;
         mHeaderViewInfos.add(info);
 
-        // in the case of re-adding a header view, or adding one later on,
-        // we need to notify the observer
-        if (mAdapter != null && mDataSetObserver != null) {
-            mDataSetObserver.onChanged();
+        // Wrap the adapter if it wasn't already wrapped.
+        if (mAdapter != null) {
+            if (!(mAdapter instanceof HeaderViewListAdapter)) {
+                mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
+            }
+
+            // In the case of re-adding a header view, or adding one later on,
+            // we need to notify the observer.
+            if (mDataSetObserver != null) {
+                mDataSetObserver.onChanged();
+            }
         }
     }
 
@@ -277,9 +281,12 @@
      * called more than once, the views will appear in the order they were
      * added. Views added using this call can take focus if they want.
      * <p>
-     * NOTE: Call this before calling setAdapter. This is so ListView can wrap
-     * the supplied cursor with one that will also account for header and footer
-     * views.
+     * Note: When first introduced, this method could only be called before
+     * setting the adapter with {@link #setAdapter(ListAdapter)}. Starting with
+     * {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE}, this method may be
+     * called at any time. If the ListView's adapter does not extend
+     * {@link HeaderViewListAdapter}, it will be wrapped with a supporting
+     * instance of {@link WrapperListAdapter}.
      *
      * @param v The view to add.
      */
@@ -330,41 +337,49 @@
      * called more than once, the views will appear in the order they were
      * added. Views added using this call can take focus if they want.
      * <p>
-     * NOTE: Call this before calling setAdapter. This is so ListView can wrap
-     * the supplied cursor with one that will also account for header and footer
-     * views.
+     * Note: When first introduced, this method could only be called before
+     * setting the adapter with {@link #setAdapter(ListAdapter)}. Starting with
+     * {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE}, this method may be
+     * called at any time. If the ListView's adapter does not extend
+     * {@link HeaderViewListAdapter}, it will be wrapped with a supporting
+     * instance of {@link WrapperListAdapter}.
      *
      * @param v The view to add.
      * @param data Data to associate with this view
      * @param isSelectable true if the footer view can be selected
      */
     public void addFooterView(View v, Object data, boolean isSelectable) {
-
-        // NOTE: do not enforce the adapter being null here, since unlike in
-        // addHeaderView, it was never enforced here, and so existing apps are
-        // relying on being able to add a footer and then calling setAdapter to
-        // force creation of the HeaderViewListAdapter wrapper
-
-        FixedViewInfo info = new FixedViewInfo();
+        final FixedViewInfo info = new FixedViewInfo();
         info.view = v;
         info.data = data;
         info.isSelectable = isSelectable;
         mFooterViewInfos.add(info);
 
-        // in the case of re-adding a footer view, or adding one later on,
-        // we need to notify the observer
-        if (mAdapter != null && mDataSetObserver != null) {
-            mDataSetObserver.onChanged();
+        // Wrap the adapter if it wasn't already wrapped.
+        if (mAdapter != null) {
+            if (!(mAdapter instanceof HeaderViewListAdapter)) {
+                mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
+            }
+
+            // In the case of re-adding a footer view, or adding one later on,
+            // we need to notify the observer.
+            if (mDataSetObserver != null) {
+                mDataSetObserver.onChanged();
+            }
         }
     }
 
     /**
-     * Add a fixed view to appear at the bottom of the list. If addFooterView is called more
-     * than once, the views will appear in the order they were added. Views added using
-     * this call can take focus if they want.
-     * <p>NOTE: Call this before calling setAdapter. This is so ListView can wrap the supplied
-     * cursor with one that will also account for header and footer views.
-     *
+     * Add a fixed view to appear at the bottom of the list. If addFooterView is
+     * called more than once, the views will appear in the order they were
+     * added. Views added using this call can take focus if they want.
+     * <p>
+     * Note: When first introduced, this method could only be called before
+     * setting the adapter with {@link #setAdapter(ListAdapter)}. Starting with
+     * {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE}, this method may be
+     * called at any time. If the ListView's adapter does not extend
+     * {@link HeaderViewListAdapter}, it will be wrapped with a supporting
+     * instance of {@link WrapperListAdapter}.
      *
      * @param v The view to add.
      */
@@ -3433,6 +3448,7 @@
      * @param headerDividersEnabled True to draw the headers, false otherwise.
      *
      * @see #setFooterDividersEnabled(boolean)
+     * @see #areHeaderDividersEnabled()
      * @see #addHeaderView(android.view.View)
      */
     public void setHeaderDividersEnabled(boolean headerDividersEnabled) {
@@ -3441,17 +3457,36 @@
     }
 
     /**
+     * @return Whether the drawing of the divider for header views is enabled
+     *
+     * @see #setHeaderDividersEnabled(boolean)
+     */
+    public boolean areHeaderDividersEnabled() {
+        return mHeaderDividersEnabled;
+    }
+
+    /**
      * Enables or disables the drawing of the divider for footer views.
      *
      * @param footerDividersEnabled True to draw the footers, false otherwise.
      *
      * @see #setHeaderDividersEnabled(boolean)
+     * @see #areFooterDividersEnabled()
      * @see #addFooterView(android.view.View)
      */
     public void setFooterDividersEnabled(boolean footerDividersEnabled) {
         mFooterDividersEnabled = footerDividersEnabled;
         invalidate();
     }
+
+    /**
+     * @return Whether the drawing of the divider for footer views is enabled
+     *
+     * @see #setFooterDividersEnabled(boolean)
+     */
+    public boolean areFooterDividersEnabled() {
+        return mFooterDividersEnabled;
+    }
     
     /**
      * Sets the drawable that will be drawn above all other list content.
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index f10a2e8..52c2cdd 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -549,8 +549,9 @@
 
             final PointerState ps = mPointers.get(id);
             ps.mCurDown = true;
-            ps.mHasBoundingBox = (InputDevice.getDevice(event.getDeviceId()).
-                    getMotionRange(MotionEvent.AXIS_GENERIC_1) != null);
+            InputDevice device = InputDevice.getDevice(event.getDeviceId());
+            ps.mHasBoundingBox = device != null &&
+                    device.getMotionRange(MotionEvent.AXIS_GENERIC_1) != null;
         }
 
         final int NI = event.getPointerCount();
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index b203824..fd094b4 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -870,7 +870,7 @@
     <string name="factorytest_not_system" msgid="4435201656767276723">"Tendo la JARIBIO_LA KIWANDA  linahimiliwa tu kwa furushi zilizosakinishwa katika /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Hakuna furushi lililopatikana ambalo linatoa tendo la JARIBIO_LA KIWANDA."</string>
     <string name="factorytest_reboot" msgid="6320168203050791643">"Washa tena"</string>
-    <string name="js_dialog_title" msgid="1987483977834603872">"Ukurasa ulio \"<xliff:g id="TITLE">%s</xliff:g>\" unasema:"</string>
+    <string name="js_dialog_title" msgid="1987483977834603872">"Ukurasa wa \"<xliff:g id="TITLE">%s</xliff:g>\" unasema:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"HatiJava"</string>
     <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"Thibitisha jinsi ya kuelekea"</string>
     <string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"Toka kwenye Ukurasa huu"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 2c72c3f..d4a46ef 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -790,7 +790,7 @@
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Åžarj oluyor (<xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="321635745684060624">"Åžarj oldu"</string>
     <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="lockscreen_low_battery" msgid="1482873981919249740">"Şarj cihazınızı bağlayın."</string>
+    <string name="lockscreen_low_battery" msgid="1482873981919249740">"Şarj cihazınızı takın."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM kart yok"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tablette SIM kart yok."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonda SIM kart yok."</string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 637128a5..ccca2d8 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -50,8 +50,10 @@
     <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
     <dimen name="status_bar_edge_ignore">5dp</dimen>
 
-    <!-- Size of the fastscroll hint letter -->
+    <!-- Minimum size of the fastscroll overlay -->
     <dimen name="fastscroll_overlay_size">104dp</dimen>
+    <!-- Padding of the fastscroll overlay -->
+    <dimen name="fastscroll_overlay_padding">16dp</dimen>
     <!-- Width of the fastscroll thumb -->
     <dimen name="fastscroll_thumb_width">64dp</dimen>
     <!-- Height of the fastscroll thumb -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3718220..d33a6fa 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -309,9 +309,9 @@
   <java-symbol type="dimen" name="dropdownitem_icon_width" />
   <java-symbol type="dimen" name="dropdownitem_text_padding_left" />
   <java-symbol type="dimen" name="fastscroll_overlay_size" />
+  <java-symbol type="dimen" name="fastscroll_overlay_padding" />
   <java-symbol type="dimen" name="fastscroll_thumb_height" />
   <java-symbol type="dimen" name="fastscroll_thumb_width" />
-  <java-symbol type="dimen" name="fastscroll_thumb_width" />
   <java-symbol type="dimen" name="password_keyboard_spacebar_vertical_correction" />
   <java-symbol type="dimen" name="search_view_preferred_width" />
   <java-symbol type="dimen" name="textview_error_popup_default_width" />
diff --git a/packages/Keyguard/res/values-tr/strings.xml b/packages/Keyguard/res/values-tr/strings.xml
index 0f214ba..d58f9a0 100644
--- a/packages/Keyguard/res/values-tr/strings.xml
+++ b/packages/Keyguard/res/values-tr/strings.xml
@@ -32,7 +32,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Yüz Tanıma Kilidi için maksimum deneme sayısı aşıldı"</string>
     <string name="keyguard_charged" msgid="3272223906073492454">"Åžarj oldu"</string>
     <string name="keyguard_plugged_in" msgid="8117572000639998388">"Åžarj oluyor, <xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="keyguard_low_battery" msgid="8143808018719173859">"Şarj cihazınızı bağlayın."</string>
+    <string name="keyguard_low_battery" msgid="8143808018719173859">"Şarj cihazınızı takın."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"Kilidi açmak için Menü\'ye basın."</string>
     <string name="keyguard_network_locked_message" msgid="9169717779058037168">"AÄŸ kilitli"</string>
     <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"SIM kart yok"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/BeanBag.java b/packages/SystemUI/src/com/android/systemui/BeanBag.java
index f5a90ca..a396759 100644
--- a/packages/SystemUI/src/com/android/systemui/BeanBag.java
+++ b/packages/SystemUI/src/com/android/systemui/BeanBag.java
@@ -16,44 +16,25 @@
 
 package com.android.systemui;
 
-import android.animation.AnimatorSet;
-import android.animation.PropertyValuesHolder;
-import android.animation.ObjectAnimator;
 import android.animation.TimeAnimator;
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.graphics.drawable.AnimationDrawable;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Matrix;
 import android.graphics.Paint;
-import android.graphics.Point;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.provider.Settings;
+import android.graphics.drawable.BitmapDrawable;
 import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Pair;
-import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
-import android.view.animation.AnimationUtils;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
-import java.util.HashMap;
+
 import java.util.Random;
 
 public class BeanBag extends Activity {
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 0019c1b..fa1e3fe 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -29,9 +29,9 @@
 import android.view.ScaleGestureDetector;
 import android.view.ScaleGestureDetector.OnScaleGestureListener;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
-import android.view.View.OnClickListener;
 
 public class ExpandHelper implements Gefingerpoken, OnClickListener {
     public interface Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index cdd3d84..ca6a06f 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui;
 
+import static android.opengl.GLES20.*;
+import static javax.microedition.khronos.egl.EGL10.*;
+
 import android.app.ActivityManager;
 import android.app.WallpaperManager;
 import android.content.BroadcastReceiver;
@@ -35,18 +38,16 @@
 import android.view.SurfaceHolder;
 import android.view.WindowManager;
 
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.FloatBuffer;
 
-import static android.opengl.GLES20.*;
-import static javax.microedition.khronos.egl.EGL10.*;
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
 
 /**
  * Default built-in wallpaper that simply shows a static image.
diff --git a/packages/SystemUI/src/com/android/systemui/LoadAverageService.java b/packages/SystemUI/src/com/android/systemui/LoadAverageService.java
index 2b45ad1..37e974b 100644
--- a/packages/SystemUI/src/com/android/systemui/LoadAverageService.java
+++ b/packages/SystemUI/src/com/android/systemui/LoadAverageService.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui;
 
-import com.android.internal.os.ProcessStats;
-
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
@@ -31,6 +29,8 @@
 import android.view.View;
 import android.view.WindowManager;
 
+import com.android.internal.os.ProcessStats;
+
 public class LoadAverageService extends Service {
     private View mView;
     
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index ab11748..7eec8f2 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -43,9 +43,6 @@
 
 import com.android.internal.widget.multiwaveview.GlowPadView;
 import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
-
-import com.android.systemui.EventLogTags;
-import com.android.systemui.R;
 import com.android.systemui.recent.StatusBarTouchProxy;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.CommandQueue;
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index f824a8e..d38d828 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -19,18 +19,17 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
-import android.animation.Animator.AnimatorListener;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.graphics.RectF;
 import android.os.Handler;
 import android.util.Log;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.animation.LinearInterpolator;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.animation.LinearInterpolator;
 
 public class SwipeHelper implements Gefingerpoken {
     static final String TAG = "com.android.systemui.SwipeHelper";
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index 2110483c..6c38cea 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -16,12 +16,12 @@
 
 package com.android.systemui;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
 import android.content.Context;
 import android.content.res.Configuration;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 public abstract class SystemUI {
     public Context mContext;
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index ebd7fa8..447161d 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -16,9 +16,6 @@
 
 package com.android.systemui;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
 import android.app.Service;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -28,6 +25,9 @@
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 public class SystemUIService extends Service {
     static final String TAG = "SystemUIService";
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
index 8979fc2..f8b347c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
@@ -26,7 +26,6 @@
 import android.os.SystemClock;
 import android.util.Log;
 
-import java.lang.Thread;
 import java.util.LinkedList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 0d26c57..e084dac 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -16,10 +16,6 @@
 
 package com.android.systemui.power;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.Arrays;
-
 import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -27,13 +23,13 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.UserHandle;
-import android.media.AudioManager;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
 import android.provider.Settings;
 import android.util.Log;
 import android.view.View;
@@ -43,6 +39,10 @@
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+
 public class PowerUI extends SystemUI {
     static final String TAG = "PowerUI";
 
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index 403c643f..ee076d9 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -21,7 +21,6 @@
 import android.content.res.Configuration;
 import android.database.DataSetObserver;
 import android.graphics.Canvas;
-import android.graphics.Paint;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.FloatMath;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index aa80664..5617520 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -45,7 +45,6 @@
 import android.os.Process;
 import android.provider.MediaStore;
 import android.util.DisplayMetrics;
-import android.util.Log;
 import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 6a0fe47..456b5fa 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -23,7 +23,6 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
-import android.util.Log;
 
 public class TakeScreenshotService extends Service {
     private static final String TAG = "TakeScreenshotService";
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index f5471e5..327e715 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -18,7 +18,6 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -30,8 +29,6 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
-import android.view.IWindowManager;
-import android.widget.CompoundButton;
 import android.widget.ImageView;
 
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index 1b05084..ff79f04 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -16,19 +16,16 @@
 
 package com.android.systemui.settings;
 
-import com.android.systemui.R;
-
 import android.app.Dialog;
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.os.Handler;
-import android.util.Log;
 import android.view.Window;
 import android.view.WindowManager;
 import android.widget.ImageView;
 
-import java.lang.Runnable;
+import com.android.systemui.R;
 
 /** A dialog that provides controls for adjusting the screen brightness. */
 public class BrightnessDialog extends Dialog implements
diff --git a/packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java b/packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java
index 3ab2d9b..8bc72c9 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java
@@ -16,9 +16,6 @@
 
 package com.android.systemui.settings;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -30,6 +27,9 @@
 
 import com.android.systemui.SystemUI;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 public class SettingsUI extends SystemUI {
     private static final String TAG = "SettingsUI";
     private static final boolean DEBUG = false;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
index e0aefca..d584043 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
@@ -23,7 +23,6 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.CompoundButton;
-import android.widget.ProgressBar;
 import android.widget.RelativeLayout;
 import android.widget.SeekBar;
 import android.widget.TextView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index c96d9c9..089099f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -17,21 +17,6 @@
 
 package com.android.systemui.statusbar;
 
-import android.service.notification.StatusBarNotification;
-import android.content.res.Configuration;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.statusbar.StatusBarIconList;
-import com.android.internal.widget.SizeAdaptiveLayout;
-import com.android.systemui.R;
-import com.android.systemui.SearchPanelView;
-import com.android.systemui.SystemUI;
-import com.android.systemui.recent.RecentTasksLoader;
-import com.android.systemui.recent.RecentsActivity;
-import com.android.systemui.recent.TaskDescription;
-import com.android.systemui.statusbar.policy.NotificationRowLayout;
-import com.android.systemui.statusbar.tablet.StatusBarPanel;
-
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.ActivityOptions;
@@ -45,6 +30,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
@@ -59,6 +45,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -78,6 +65,19 @@
 import android.widget.RemoteViews;
 import android.widget.TextView;
 
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.statusbar.StatusBarIconList;
+import com.android.internal.widget.SizeAdaptiveLayout;
+import com.android.systemui.R;
+import com.android.systemui.SearchPanelView;
+import com.android.systemui.SystemUI;
+import com.android.systemui.recent.RecentTasksLoader;
+import com.android.systemui.recent.RecentsActivity;
+import com.android.systemui.recent.TaskDescription;
+import com.android.systemui.statusbar.policy.NotificationRowLayout;
+import com.android.systemui.statusbar.tablet.StatusBarPanel;
+
 import java.util.ArrayList;
 import java.util.Locale;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index cbbaab3..43992c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -19,8 +19,8 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
-
 import android.service.notification.StatusBarNotification;
+
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DoNotDisturb.java b/packages/SystemUI/src/com/android/systemui/statusbar/DoNotDisturb.java
index ce67abe..7520434 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DoNotDisturb.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DoNotDisturb.java
@@ -17,11 +17,8 @@
 package com.android.systemui.statusbar;
 
 import android.app.StatusBarManager;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 
 import com.android.systemui.statusbar.policy.Prefs;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
index 378061f..f2adaf0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
@@ -16,6 +16,12 @@
 
 package com.android.systemui.statusbar;
 
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.MotionEvent;
+
 import java.io.BufferedWriter;
 import java.io.FileDescriptor;
 import java.io.FileWriter;
@@ -24,12 +30,6 @@
 import java.util.HashSet;
 import java.util.LinkedList;
 
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.util.Log;
-import android.view.MotionEvent;
-
 /**
  * Convenience class for capturing gestures for later analysis.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 2c7a2a8..673ca6b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -16,15 +16,15 @@
 
 package com.android.systemui.statusbar;
 
-import android.service.notification.StatusBarNotification;
 import android.os.IBinder;
+import android.service.notification.StatusBarNotification;
 import android.view.View;
 import android.widget.ImageView;
 
 import com.android.systemui.R;
 
-import java.util.Comparator;
 import java.util.ArrayList;
+import java.util.Comparator;
 
 /**
  * The list of currently displaying notifications.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index de7f189..f17b143e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -25,9 +25,8 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
-import com.android.systemui.statusbar.policy.NetworkController;
-
 import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.NetworkController;
 
 // Intimately tied to the design of res/layout/signal_cluster_view.xml
 public class SignalClusterView
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 54c5e2a..8b50a38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -20,10 +20,10 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -32,12 +32,11 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.ImageView;
 
-import java.text.NumberFormat;
-
 import com.android.internal.statusbar.StatusBarIcon;
-
 import com.android.systemui.R;
 
+import java.text.NumberFormat;
+
 public class StatusBarIconView extends AnimatedImageView {
     private static final String TAG = "StatusBarIconView";
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java
index 5fa8126..5ea17e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java
@@ -23,17 +23,10 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.View;
 import android.widget.TextView;
 
 import com.android.internal.telephony.TelephonyIntents;
 
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.TimeZone;
-
-import com.android.internal.R;
-
 /**
  * This widget display an analogic clock with two hands for hours and
  * minutes.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
index eae4b7a..50ead3d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
@@ -17,15 +17,11 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
-import android.os.Handler;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.LinearLayout;
 
-import com.android.internal.statusbar.StatusBarIcon;
-
 import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusBarIconView;
 
 public class IconMerger extends LinearLayout {
     private static final String TAG = "IconMerger";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index f5867ab..9eaee30 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -30,25 +30,25 @@
 import android.os.ServiceManager;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.animation.AccelerateInterpolator;
 import android.view.Display;
 import android.view.MotionEvent;
-import android.view.View;
 import android.view.Surface;
+import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.animation.AccelerateInterpolator;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.DelegateViewHelper;
 import com.android.systemui.statusbar.policy.DeadZone;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 public class NavigationBarView extends LinearLayout {
     final static boolean DEBUG = false;
     final static String TAG = "PhoneStatusBar/NavigationBarView";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 91e1aa0..751d944 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import java.util.ArrayList;
-
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -25,6 +23,8 @@
 import android.view.View;
 import android.widget.FrameLayout;
 
+import java.util.ArrayList;
+
 public class PanelBar extends FrameLayout {
     public static final boolean DEBUG = false;
     public static final String TAG = PanelBar.class.getSimpleName();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 70cb94a..cf7f9c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -16,11 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayDeque;
-import java.util.Iterator;
-
 import android.animation.ObjectAnimator;
 import android.animation.TimeAnimator;
 import android.animation.TimeAnimator.TimeListener;
@@ -34,6 +29,11 @@
 
 import com.android.systemui.R;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayDeque;
+import java.util.Iterator;
+
 public class PanelView extends FrameLayout {
     public static final boolean DEBUG = PanelBar.DEBUG;
     public static final String TAG = PanelView.class.getSimpleName();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 97c7b98a..38f13b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -26,7 +26,6 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
-import android.service.notification.StatusBarNotification;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -52,6 +51,7 @@
 import android.provider.Settings;
 import android.service.dreams.DreamService;
 import android.service.dreams.IDreamManager;
+import android.service.notification.StatusBarNotification;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
@@ -87,7 +87,6 @@
 import com.android.systemui.statusbar.NotificationData.Entry;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
-import com.android.systemui.statusbar.policy.RotationLockController;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.DateView;
@@ -97,6 +96,7 @@
 import com.android.systemui.statusbar.policy.NotificationRowLayout;
 import com.android.systemui.statusbar.policy.OnSizeChangedListener;
 import com.android.systemui.statusbar.policy.Prefs;
+import com.android.systemui.statusbar.policy.RotationLockController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 80734ee..57ec0e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -22,28 +22,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.location.LocationManager;
 import android.media.AudioManager;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.wifi.WifiManager;
-import android.os.Binder;
 import android.os.Handler;
-import android.os.RemoteException;
 import android.os.storage.StorageManager;
-import android.provider.Settings;
-import android.telephony.PhoneStateListener;
-import android.telephony.ServiceState;
-import android.telephony.SignalStrength;
-import android.telephony.TelephonyManager;
 import android.util.Log;
 
-import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.cdma.EriInfo;
 import com.android.internal.telephony.cdma.TtyIntent;
-import com.android.server.am.BatteryStatsService;
 import com.android.systemui.R;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index b20a8bb..9ee6065 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -16,19 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import com.android.systemui.R;
-
-import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
-import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
-import com.android.systemui.statusbar.phone.QuickSettingsModel.State;
-import com.android.systemui.statusbar.phone.QuickSettingsModel.UserState;
-import com.android.systemui.statusbar.phone.QuickSettingsModel.WifiState;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.RotationLockController;
-
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -71,6 +58,18 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.State;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.UserState;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.WifiState;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RotationLockController;
+
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsBasicTile.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsBasicTile.java
index 94b2fc7..ef850d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsBasicTile.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsBasicTile.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import com.android.systemui.R;
-
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
@@ -26,6 +24,8 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.systemui.R;
+
 class QuickSettingsBasicTile extends QuickSettingsTileView {
     private final TextView mTextView;
     private final ImageView mImageView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index b0aca16..79495a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -40,13 +40,13 @@
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.systemui.R;
-import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.settings.BrightnessController.BrightnessStateChangeCallback;
-import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
+import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
 import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback;
 import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
+import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
 
 import java.util.List;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
index 1897589..c10a0d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
@@ -16,23 +16,18 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.animation.LayoutTransition;
 import android.content.Context;
-import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.EventLog;
-import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.systemui.EventLogTags;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 5620e1b..a600aae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -20,14 +20,12 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewRootImpl;
 import android.widget.FrameLayout;
 import android.widget.ScrollView;
-import android.widget.TextSwitcher;
 
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
index b1ccd00..a784f37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/Ticker.java
@@ -16,27 +16,26 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.service.notification.StatusBarNotification;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
-import android.text.StaticLayout;
+import android.service.notification.StatusBarNotification;
 import android.text.Layout.Alignment;
+import android.text.StaticLayout;
 import android.text.TextPaint;
 import android.view.View;
 import android.view.animation.AnimationUtils;
+import android.widget.ImageSwitcher;
 import android.widget.TextSwitcher;
 import android.widget.TextView;
-import android.widget.ImageSwitcher;
-
-import java.util.ArrayList;
 
 import com.android.internal.statusbar.StatusBarIcon;
-
 import com.android.systemui.R;
 import com.android.systemui.statusbar.StatusBarIconView;
 
+import java.util.ArrayList;
+
 public abstract class Ticker {
     private static final int TICKER_SEGMENT_DELAY = 3000;
     
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingPatternView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingPatternView.java
index f3cf65c..68807a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingPatternView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingPatternView.java
@@ -17,13 +17,12 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
-import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
 import android.util.AttributeSet;
 import android.view.View;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
-import android.graphics.Paint;
-import android.graphics.Canvas;
 
 public class TrackingPatternView extends View {
     private Bitmap mTexture;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
index 71a7aa8..8bbe957 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
@@ -22,8 +22,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.AsyncTask;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.widget.CompoundButton;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 0f56ba6..452ff489 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -16,9 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import java.util.ArrayList;
-
-import android.bluetooth.BluetoothAdapter.BluetoothStateChangeCallback;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -29,6 +26,8 @@
 
 import com.android.systemui.R;
 
+import java.util.ArrayList;
+
 public class BatteryController extends BroadcastReceiver {
     private static final String TAG = "StatusBar.BatteryController";
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 91a1a6d..e5816cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -20,21 +20,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
 import android.text.format.DateFormat;
 import android.text.style.CharacterStyle;
-import android.text.style.ForegroundColorSpan;
 import android.text.style.RelativeSizeSpan;
-import android.text.style.RelativeSizeSpan;
-import android.text.style.StyleSpan;
 import android.util.AttributeSet;
-import android.view.View;
 import android.widget.TextView;
 
 import java.text.SimpleDateFormat;
@@ -44,8 +35,6 @@
 
 import libcore.icu.LocaleData;
 
-import com.android.internal.R;
-
 /**
  * Digital clock for the status bar.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
index 3083e8b..7939752 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
@@ -18,15 +18,11 @@
 
 import android.app.ActivityManager;
 import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.RemoteException;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
 import android.widget.ImageView;
 
-import com.android.systemui.R;
-
 public class CompatModeButton extends ImageView {
     private static final boolean DEBUG = false;
     private static final String TAG = "StatusBar.CompatModeButton";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DoNotDisturbController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DoNotDisturbController.java
index d45a94f..8612c8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DoNotDisturbController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DoNotDisturbController.java
@@ -16,14 +16,8 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.IWindowManager;
 import android.widget.CompoundButton;
 
 public class DoNotDisturbController implements CompoundButton.OnCheckedChangeListener,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java
index 4de4241..aca88fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java
@@ -17,26 +17,10 @@
 package com.android.systemui.statusbar.policy;
 
 import android.content.Context;
-import android.content.res.TypedArray;
 import android.graphics.Region;
-import android.graphics.drawable.AnimationDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.ServiceManager;
 import android.util.AttributeSet;
-import android.view.HapticFeedbackConstants;
-import android.view.IWindowManager;
-import android.view.InputDevice;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver;
-import android.widget.RemoteViews.RemoteView;
-
-import com.android.systemui.R;
 
 public class EventHole extends View implements ViewTreeObserver.OnComputeInternalInsetsListener {
     private static final String TAG = "StatusBar.EventHole";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FixedSizeDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FixedSizeDrawable.java
index 3751399..af20411 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FixedSizeDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FixedSizeDrawable.java
@@ -16,10 +16,10 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.graphics.drawable.Drawable;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 
 public class FixedSizeDrawable extends Drawable {
     Drawable mDrawable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IntruderAlertView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IntruderAlertView.java
index 9b96384..dbd36af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IntruderAlertView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IntruderAlertView.java
@@ -16,21 +16,14 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.LayoutTransition;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.widget.LinearLayout;
@@ -40,8 +33,6 @@
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.statusbar.BaseStatusBar;
 
-import java.util.HashMap;
-
 public class IntruderAlertView extends LinearLayout implements SwipeHelper.Callback {
     private static final String TAG = "IntruderAlertView";
     private static final boolean DEBUG = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index db0e4c3..fc77be1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -20,17 +20,13 @@
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
 import android.graphics.Canvas;
 import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
 import android.hardware.input.InputManager;
-import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.ServiceManager;
 import android.util.AttributeSet;
-import android.view.accessibility.AccessibilityEvent;
 import android.view.HapticFeedbackConstants;
-import android.view.IWindowManager;
 import android.view.InputDevice;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
@@ -38,6 +34,7 @@
 import android.view.SoundEffectConstants;
 import android.view.View;
 import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.ImageView;
 
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index 68d048d..63f1254 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -16,8 +16,7 @@
 
 package com.android.systemui.statusbar.policy;
 
-import java.util.ArrayList;
-
+import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -29,11 +28,10 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 
-// private NM API
-import android.app.INotificationManager;
-
 import com.android.systemui.R;
 
+import java.util.ArrayList;
+
 public class LocationController extends BroadcastReceiver {
     private static final String TAG = "StatusBar.LocationController";
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index 9bf1c1b..cd8445c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -16,14 +16,10 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.LayoutTransition;
-import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -31,7 +27,6 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
 import android.widget.LinearLayout;
 
 import com.android.systemui.ExpandHelper;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java
index 3e138d5..d3707f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java
@@ -16,15 +16,9 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.content.ContentResolver;
 import android.content.Context;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.Vibrator;
 import android.media.AudioManager;
-import android.provider.Settings;
-import android.view.IWindowManager;
-import android.widget.CompoundButton;
+import android.os.Vibrator;
 
 import com.android.systemui.settings.ToggleSlider;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java
index d3d4338..4877828 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java
@@ -1,28 +1,27 @@
-/*

- * Copyright (C) 2011 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.statusbar.policy;

-

-import com.android.systemui.statusbar.policy.TelephonyIcons;

-import com.android.systemui.R;

-

-class WimaxIcons {

-    static final int[][] WIMAX_SIGNAL_STRENGTH = TelephonyIcons.DATA_SIGNAL_STRENGTH;

-

-    static final int WIMAX_DISCONNECTED = WIMAX_SIGNAL_STRENGTH[0][0];

-

-    static final int WIMAX_IDLE = WIMAX_DISCONNECTED; // XXX: unclear if we need a different icon

-}

+/*
+ * Copyright (C) 2011 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.statusbar.policy;
+
+import com.android.systemui.statusbar.policy.TelephonyIcons;
+
+class WimaxIcons {
+    static final int[][] WIMAX_SIGNAL_STRENGTH = TelephonyIcons.DATA_SIGNAL_STRENGTH;
+
+    static final int WIMAX_DISCONNECTED = WIMAX_SIGNAL_STRENGTH[0][0];
+
+    static final int WIMAX_IDLE = WIMAX_DISCONNECTED; // XXX: unclear if we need a different icon
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
index 080cbd5..10bbf56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/CompatModePanel.java
@@ -18,15 +18,11 @@
 
 import android.app.ActivityManager;
 import android.content.Context;
-import android.content.res.TypedArray;
-import android.os.RemoteException;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.FrameLayout;
-import android.widget.ImageView;
 import android.widget.RadioButton;
-import android.widget.RadioGroup;
 
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
index fa8aa6d..aead242 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
@@ -20,10 +20,10 @@
 import android.os.IBinder;
 import android.provider.Settings;
 import android.util.AttributeSet;
+import android.view.View;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
-import android.view.View;
 import android.widget.ImageView;
 
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
index 8924087..6699379 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.tablet;
 
-import com.android.systemui.R;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -41,6 +39,8 @@
 import android.widget.Switch;
 import android.widget.TextView;
 
+import com.android.systemui.R;
+
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
index 4f3c4d5..6e93cee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
@@ -17,14 +17,10 @@
 package com.android.systemui.statusbar.tablet;
 
 import android.content.Context;
-import android.content.res.Resources;
-import android.os.Handler;
 import android.util.AttributeSet;
-import android.view.View;
+import android.view.MotionEvent;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
-import android.widget.ImageView;
-import android.view.MotionEvent;
 
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java
index 51980dd..6d15e87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java
@@ -16,9 +16,6 @@
 
 package com.android.systemui.statusbar.tablet;
 
-import android.animation.Animator;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -26,14 +23,8 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
 import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java
index d180ab9..8eeeb14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanelTitle.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.tablet;
 
-import java.util.ArrayList;
-
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
@@ -28,6 +26,8 @@
 
 import com.android.systemui.R;
 
+import java.util.ArrayList;
+
 
 public class NotificationPanelTitle extends RelativeLayout implements View.OnClickListener {
     private NotificationPanel mPanel;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
index 48486b2..7ac4fd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -20,25 +20,17 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.ClipData;
-import android.content.ClipDescription;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
-import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.DragEvent;
-import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
 import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.systemui.R;
 
 public class ShirtPocket extends ImageView {
     private static final boolean DEBUG = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index c2054d0..b938716 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -23,7 +23,6 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
-import android.service.notification.StatusBarNotification;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -39,6 +38,7 @@
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
+import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.Display;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
index cd1c942..5c901c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
@@ -16,18 +16,18 @@
 
 package com.android.systemui.statusbar.tablet;
 
-import com.android.systemui.R;
-import com.android.systemui.statusbar.BaseStatusBar;
-import com.android.systemui.statusbar.DelegateViewHelper;
-
 import android.content.Context;
 import android.os.Handler;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.View;
 import android.view.MotionEvent;
+import android.view.View;
 import android.widget.FrameLayout;
 
+import com.android.systemui.R;
+import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.DelegateViewHelper;
+
 public class TabletStatusBarView extends FrameLayout {
     private Handler mHandler;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index 04e0e56..167f03c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -16,12 +16,9 @@
 
 package com.android.systemui.statusbar.tablet;
 
-import java.util.Arrays;
-
 import android.animation.LayoutTransition;
 import android.app.Notification;
 import android.app.PendingIntent;
-import android.service.notification.StatusBarNotification;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
@@ -29,6 +26,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.service.notification.StatusBarNotification;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -40,10 +38,11 @@
 import android.widget.TextView;
 
 import com.android.internal.statusbar.StatusBarIcon;
-
 import com.android.systemui.R;
 import com.android.systemui.statusbar.StatusBarIconView;
 
+import java.util.Arrays;
+
 public class TabletTicker
         extends Handler
         implements LayoutTransition.TransitionListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index dc5de02..18b9e26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -16,15 +16,15 @@
 
 package com.android.systemui.statusbar.tv;
 
-import android.service.notification.StatusBarNotification;
-import com.android.internal.statusbar.StatusBarIcon;
-import com.android.systemui.statusbar.BaseStatusBar;
-
 import android.os.IBinder;
+import android.service.notification.StatusBarNotification;
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
 
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.statusbar.BaseStatusBar;
+
 /*
  * Status bar implementation for "large screen" products that mostly present no on-screen nav
  */
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
index ff06630..b5f98ad 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbAccessoryUriActivity.java
@@ -16,22 +16,19 @@
 
 package com.android.systemui.usb;
 
-import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.ActivityNotFoundException;
-import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.net.Uri;
 import android.hardware.usb.UsbAccessory;
 import android.hardware.usb.UsbManager;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
-
 import com.android.systemui.R;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index 2c25236..7abfc88 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -23,9 +23,7 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.graphics.Typeface;
 import android.hardware.usb.IUsbManager;
-import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbManager;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -35,12 +33,9 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.CheckBox;
-import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
-
 import com.android.systemui.R;
 
 public class UsbDebuggingActivity extends AlertActivity
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index 6e88d0d..1e69fc5 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.usb;
 
-import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -25,8 +24,8 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.hardware.usb.IUsbManager;
-import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbManager;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -42,7 +41,6 @@
 
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
-
 import com.android.systemui.R;
 
 public class UsbPermissionActivity extends AlertActivity
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
index e61ef8a..65315f3 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.usb;
 
-import com.android.internal.R;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.AlertDialog;
@@ -24,31 +23,30 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.DialogInterface.OnCancelListener;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.hardware.usb.UsbManager;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
-import android.os.storage.IMountService;
-import android.os.storage.StorageManager;
-import android.os.storage.StorageEventListener;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.widget.ImageView;
+import android.os.storage.IMountService;
+import android.os.storage.StorageEventListener;
+import android.os.storage.StorageManager;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
 import android.widget.Button;
+import android.widget.ImageView;
 import android.widget.ProgressBar;
 import android.widget.TextView;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.util.Log;
+
+import com.android.internal.R;
 
 import java.util.List;
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 0da3b56..4930d59 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -296,35 +296,18 @@
     WindowState mFocusedWindow;
     IApplicationToken mFocusedApp;
 
-    private static final class PointerLocationInputEventReceiver extends InputEventReceiver {
-        private final PointerLocationView mView;
-
-        public PointerLocationInputEventReceiver(InputChannel inputChannel, Looper looper,
-                PointerLocationView view) {
-            super(inputChannel, looper);
-            mView = view;
-        }
-
+    private final class PointerLocationPointerEventListener implements PointerEventListener {
         @Override
-        public void onInputEvent(InputEvent event) {
-            boolean handled = false;
-            try {
-                if (event instanceof MotionEvent
-                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
-                    final MotionEvent motionEvent = (MotionEvent)event;
-                    mView.addPointerEvent(motionEvent);
-                    handled = true;
-                }
-            } finally {
-                finishInputEvent(event, handled);
+        public void onPointerEvent(MotionEvent motionEvent) {
+            if (mPointerLocationView != null) {
+                mPointerLocationView.addPointerEvent(motionEvent);
             }
         }
     }
 
     // Pointer location view state, only modified on the mHandler Looper.
-    PointerLocationInputEventReceiver mPointerLocationInputEventReceiver;
+    PointerLocationPointerEventListener mPointerLocationPointerEventListener;
     PointerLocationView mPointerLocationView;
-    InputChannel mPointerLocationInputChannel;
 
     // The current size of the screen; really; extends into the overscan area of
     // the screen and doesn't account for any system elements like the status bar.
@@ -568,8 +551,7 @@
     private int mStatusHideybar;
     private int mNavigationHideybar;
 
-    private InputChannel mSystemGestureInputChannel;
-    private SystemGestures mSystemGestures;
+    private SystemGesturesPointerEventListener mSystemGestures;
 
     IStatusBarService getStatusBarService() {
         synchronized (mServiceAquireLock) {
@@ -925,10 +907,8 @@
         context.registerReceiver(mMultiuserReceiver, filter);
 
         // monitor for system gestures
-        mSystemGestureInputChannel = mWindowManagerFuncs.monitorInput("SystemGestures");
-        mSystemGestures = new SystemGestures(mSystemGestureInputChannel,
-                mHandler.getLooper(), context,
-                new SystemGestures.Callbacks() {
+        mSystemGestures = new SystemGesturesPointerEventListener(context,
+                new SystemGesturesPointerEventListener.Callbacks() {
                     @Override
                     public void onSwipeFromTop() {
                         if (mStatusBar != null) {
@@ -954,6 +934,7 @@
                         }
                     }
                 });
+        mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
 
         mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
         mLongPressVibePattern = getLongIntArray(mContext.getResources(),
@@ -1212,23 +1193,16 @@
             lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
             wm.addView(mPointerLocationView, lp);
 
-            mPointerLocationInputChannel =
-                    mWindowManagerFuncs.monitorInput("PointerLocationView");
-            mPointerLocationInputEventReceiver =
-                    new PointerLocationInputEventReceiver(mPointerLocationInputChannel,
-                            Looper.myLooper(), mPointerLocationView);
+            mPointerLocationPointerEventListener = new PointerLocationPointerEventListener();
+            mWindowManagerFuncs.registerPointerEventListener(mPointerLocationPointerEventListener);
         }
     }
 
     private void disablePointerLocation() {
-        if (mPointerLocationInputEventReceiver != null) {
-            mPointerLocationInputEventReceiver.dispose();
-            mPointerLocationInputEventReceiver = null;
-        }
-
-        if (mPointerLocationInputChannel != null) {
-            mPointerLocationInputChannel.dispose();
-            mPointerLocationInputChannel = null;
+        if (mPointerLocationPointerEventListener != null) {
+            mWindowManagerFuncs.unregisterPointerEventListener(
+                    mPointerLocationPointerEventListener);
+            mPointerLocationPointerEventListener = null;
         }
 
         if (mPointerLocationView != null) {
diff --git a/policy/src/com/android/internal/policy/impl/SystemGestures.java b/policy/src/com/android/internal/policy/impl/SystemGesturesPointerEventListener.java
similarity index 90%
rename from policy/src/com/android/internal/policy/impl/SystemGestures.java
rename to policy/src/com/android/internal/policy/impl/SystemGesturesPointerEventListener.java
index c9731a5..6e8c841 100644
--- a/policy/src/com/android/internal/policy/impl/SystemGestures.java
+++ b/policy/src/com/android/internal/policy/impl/SystemGesturesPointerEventListener.java
@@ -17,19 +17,15 @@
 package com.android.internal.policy.impl;
 
 import android.content.Context;
-import android.os.Looper;
 import android.util.Slog;
-import android.view.InputChannel;
-import android.view.InputDevice;
-import android.view.InputEvent;
-import android.view.InputEventReceiver;
 import android.view.MotionEvent;
+import android.view.WindowManagerPolicy.PointerEventListener;
 
 /*
  * Listens for system-wide input gestures, firing callbacks when detected.
  * @hide
  */
-public class SystemGestures extends InputEventReceiver {
+public class SystemGesturesPointerEventListener implements PointerEventListener {
     private static final String TAG = "SystemGestures";
     private static final boolean DEBUG = false;
     private static final long SWIPE_TIMEOUT_MS = 500;
@@ -55,9 +51,7 @@
     private boolean mSwipeFireable;
     private boolean mDebugFireable;
 
-    public SystemGestures(InputChannel inputChannel, Looper looper,
-            Context context, Callbacks callbacks) {
-        super(inputChannel, looper);
+    public SystemGesturesPointerEventListener(Context context, Callbacks callbacks) {
         mCallbacks = checkNull("callbacks", callbacks);
         mSwipeStartThreshold = checkNull("context", context).getResources()
                 .getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
@@ -72,14 +66,7 @@
     }
 
     @Override
-    public void onInputEvent(InputEvent event) {
-        if (event instanceof MotionEvent && event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
-            onPointerMotionEvent((MotionEvent) event);
-        }
-        finishInputEvent(event, false /*handled*/);
-    }
-
-    private void onPointerMotionEvent(MotionEvent event) {
+    public void onPointerEvent(MotionEvent event) {
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
                 mSwipeFireable = true;
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index a5d64b2..912c465 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -1015,7 +1015,7 @@
                 Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
             if (app != null && app.thread != null) {
                 try {
-                    app.addPackage(r.appInfo.packageName);
+                    app.addPackage(r.appInfo.packageName, mAm.mProcessTracker);
                     realStartServiceLocked(r, app);
                     return null;
                 } catch (RemoteException e) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 38fe5e6..2124095 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -817,10 +817,10 @@
     int mNumNonCachedProcs = 0;
 
     /**
-     * Keep track of the number of cached procs, to balance oom adj
+     * Keep track of the number of cached hidden procs, to balance oom adj
      * distribution between those and empty procs.
      */
-    int mNumCachedProcs = 0;
+    int mNumCachedHiddenProcs = 0;
 
     /**
      * Keep track of the number of service processes we last found, to
@@ -2151,7 +2151,7 @@
                 // come up (we have a pid but not yet its thread), so keep it.
                 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
                 // If this is a new package in the process, add the package to the list
-                app.addPackage(info.packageName);
+                app.addPackage(info.packageName, mProcessTracker);
                 return app;
             }
 
@@ -2206,7 +2206,7 @@
             }
         } else {
             // If this is a new package in the process, add the package to the list
-            app.addPackage(info.packageName);
+            app.addPackage(info.packageName, mProcessTracker);
         }
 
         // If the system is not ready yet, then hold off on starting this
@@ -3039,10 +3039,8 @@
                         proc = p;
                         break;
                     }
-                    for (String str : p.pkgList) {
-                        if (str.equals(packageName)) {
-                            proc = p;
-                        }
+                    if (p.pkgList.containsKey(packageName)) {
+                        proc = p;
                     }
                 }
             }
@@ -4014,7 +4012,7 @@
                     if (userId != UserHandle.USER_ALL && app.userId != userId) {
                         continue;
                     }
-                    if (!app.pkgList.contains(packageName)) {
+                    if (!app.pkgList.containsKey(packageName)) {
                         continue;
                     }
                 }
@@ -6220,7 +6218,7 @@
                     if (proc.userId != tr.userId) {
                         continue;
                     }
-                    if (!proc.pkgList.contains(pkg)) {
+                    if (!proc.pkgList.containsKey(pkg)) {
                         continue;
                     }
                     procs.add(proc);
@@ -6577,7 +6575,7 @@
                 if (DEBUG_MU)
                     Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid);
                 app.pubProviders.put(cpi.name, cpr);
-                app.addPackage(cpi.applicationInfo.packageName);
+                app.addPackage(cpi.applicationInfo.packageName, mProcessTracker);
                 ensurePackageDexOpt(cpi.applicationInfo.packageName);
             }
         }
@@ -7316,7 +7314,7 @@
             ps = stats.getProcessStatsLocked(info.uid, proc);
         }
         return new ProcessRecord(ps, thread, info, proc, uid,
-                mProcessTracker.getStateLocked(info.processName, info.uid));
+                mProcessTracker.getProcessStateLocked(info.packageName, uid, proc));
     }
 
     final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) {
@@ -8895,7 +8893,8 @@
             int flags = process.info.flags;
             IPackageManager pm = AppGlobals.getPackageManager();
             sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
-            for (String pkg : process.pkgList) {
+            for (int ip=0; ip<process.pkgList.size(); ip++) {
+                String pkg = process.pkgList.keyAt(ip);
                 sb.append("Package: ").append(pkg);
                 try {
                     PackageInfo pi = pm.getPackageInfo(pkg, 0, UserHandle.getCallingUserId());
@@ -9630,7 +9629,7 @@
                 final int NA = procs.size();
                 for (int ia=0; ia<NA; ia++) {
                     ProcessRecord r = procs.valueAt(ia);
-                    if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
+                    if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
                         continue;
                     }
                     if (!needSep) {
@@ -9653,7 +9652,7 @@
             boolean printed = false;
             for (int i=0; i<mIsolatedProcesses.size(); i++) {
                 ProcessRecord r = mIsolatedProcesses.valueAt(i);
-                if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
+                if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
                     continue;
                 }
                 if (!printed) {
@@ -9685,7 +9684,7 @@
                 boolean printed = false;
                 for (int i=0; i<mPidsSelfLocked.size(); i++) {
                     ProcessRecord r = mPidsSelfLocked.valueAt(i);
-                    if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
+                    if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
                         continue;
                     }
                     if (!printed) {
@@ -9708,7 +9707,7 @@
                     ProcessRecord r = mPidsSelfLocked.get( 
                             mForegroundProcesses.valueAt(i).pid);
                     if (dumpPackage != null && (r == null
-                            || !r.pkgList.contains(dumpPackage))) {
+                            || !r.pkgList.containsKey(dumpPackage))) {
                         continue;
                     }
                     if (!printed) {
@@ -9766,7 +9765,7 @@
                     int puid = uids.keyAt(i);
                     ProcessRecord r = mProcessNames.get(pname, puid);
                     if (dumpPackage != null && (r == null
-                            || !r.pkgList.contains(dumpPackage))) {
+                            || !r.pkgList.containsKey(dumpPackage))) {
                         continue;
                     }
                     if (!printed) {
@@ -9797,7 +9796,7 @@
                     int puid = uids.keyAt(i);
                     ProcessRecord r = mProcessNames.get(pname, puid);
                     if (dumpPackage != null && (r == null
-                            || !r.pkgList.contains(dumpPackage))) {
+                            || !r.pkgList.containsKey(dumpPackage))) {
                         continue;
                     }
                     if (!printed) {
@@ -9840,7 +9839,7 @@
             }
         }
         if (mHomeProcess != null && (dumpPackage == null
-                || mHomeProcess.pkgList.contains(dumpPackage))) {
+                || mHomeProcess.pkgList.containsKey(dumpPackage))) {
             if (needSep) {
                 pw.println();
                 needSep = false;
@@ -9848,7 +9847,7 @@
             pw.println("  mHomeProcess: " + mHomeProcess);
         }
         if (mPreviousProcess != null && (dumpPackage == null
-                || mPreviousProcess.pkgList.contains(dumpPackage))) {
+                || mPreviousProcess.pkgList.containsKey(dumpPackage))) {
             if (needSep) {
                 pw.println();
                 needSep = false;
@@ -9862,7 +9861,7 @@
             pw.println(sb);
         }
         if (mHeavyWeightProcess != null && (dumpPackage == null
-                || mHeavyWeightProcess.pkgList.contains(dumpPackage))) {
+                || mHeavyWeightProcess.pkgList.containsKey(dumpPackage))) {
             if (needSep) {
                 pw.println();
                 needSep = false;
@@ -9959,7 +9958,8 @@
                 pw.println("  mLaunchingActivity=" + getFocusedStack().mLaunchingActivity);
                 pw.println("  mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
                 pw.println("  mNumNonCachedProcs=" + mNumNonCachedProcs
-                        + " mNumCachedProcs=" + mNumCachedProcs
+                        + " (" + mLruProcesses.size() + " total)"
+                        + " mNumCachedHiddenProcs=" + mNumCachedHiddenProcs
                         + " mNumServiceProcs=" + mNumServiceProcs
                         + " mNewNumServiceProcs=" + mNewNumServiceProcs);
             }
@@ -10463,7 +10463,7 @@
                 = new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
         for (int i=0; i<origList.size(); i++) {
             ProcessRecord r = origList.get(i);
-            if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
+            if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
                 continue;
             }
             list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
@@ -11079,7 +11079,6 @@
 
     final void dumpProcessTracker(FileDescriptor fd, PrintWriter pw, String[] args) {
         synchronized (this) {
-            pw.println("Process Stats:");
             mProcessTracker.dumpLocked(fd, pw, args);
         }
     }
@@ -11787,7 +11786,7 @@
                             + ") when registering receiver " + receiver);
                 }
                 if (callerApp.info.uid != Process.SYSTEM_UID &&
-                        !callerApp.pkgList.contains(callerPackage)) {
+                        !callerApp.pkgList.containsKey(callerPackage)) {
                     throw new SecurityException("Given caller package " + callerPackage
                             + " is not running in process " + callerApp);
                 }
@@ -13899,7 +13898,7 @@
     }
 
     private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
-            int clientCachedAdj, int emptyAdj, ProcessRecord TOP_APP, boolean doingAll) {
+            int clientCachedAdj, int emptyAdj, ProcessRecord TOP_APP, boolean doingAll, long now) {
         app.cachedAdj = cachedAdj;
         app.clientCachedAdj = clientCachedAdj;
         app.emptyAdj = emptyAdj;
@@ -13936,9 +13935,10 @@
                     TAG, "Set " + app.pid + " " + app.processName +
                     " adj " + app.curAdj + ": " + app.adjType);
                 app.setAdj = app.curAdj;
-                if (app.setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
-                    app.tracker.setState(mProcessList.adjToTrackedState(app.setAdj),
-                            SystemClock.uptimeMillis());
+                app.setAdjChanged = true;
+                if (!doingAll) {
+                    app.setProcessTrackerState(TOP_APP, mProcessTracker.getMemFactor(),
+                            now, mProcessList);
                 }
             } else {
                 success = false;
@@ -13997,7 +13997,7 @@
         mAdjSeq++;
 
         boolean success = updateOomAdjLocked(app, app.cachedAdj, app.clientCachedAdj,
-                app.emptyAdj, TOP_APP, false);
+                app.emptyAdj, TOP_APP, false, SystemClock.uptimeMillis());
         final boolean nowCached = app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ
             && app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ;
         if (nowCached != wasCached) {
@@ -14011,7 +14011,8 @@
     final void updateOomAdjLocked() {
         final ActivityRecord TOP_ACT = resumedAppLocked();
         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
-        final long oldTime = SystemClock.uptimeMillis() - ProcessList.MAX_EMPTY_TIME;
+        final long now = SystemClock.uptimeMillis();
+        final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
 
         if (false) {
             RuntimeException e = new RuntimeException();
@@ -14040,7 +14041,7 @@
         // them.
         int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
                 - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
-        int numEmptyProcs = mLruProcesses.size()- mNumNonCachedProcs - mNumCachedProcs;
+        int numEmptyProcs = mLruProcesses.size()- mNumNonCachedProcs - mNumCachedHiddenProcs;
         if (numEmptyProcs > cachedProcessLimit) {
             // If there are more empty processes than our limit on cached
             // processes, then use the cached process limit for the factor.
@@ -14052,7 +14053,7 @@
         }
         int emptyFactor = numEmptyProcs/numSlots;
         if (emptyFactor < 1) emptyFactor = 1;
-        int cachedFactor = (mNumCachedProcs > 0 ? mNumCachedProcs : 1)/numSlots;
+        int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;
         if (cachedFactor < 1) cachedFactor = 1;
         int stepCached = 0;
         int stepEmpty = 0;
@@ -14061,7 +14062,7 @@
         int numTrimming = 0;
 
         mNumNonCachedProcs = 0;
-        mNumCachedProcs = 0;
+        mNumCachedHiddenProcs = 0;
 
         // First update the OOM adjustment for each of the
         // application processes based on their current state.
@@ -14071,16 +14072,20 @@
         int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
         int nextEmptyAdj = curEmptyAdj+2;
         int curClientCachedAdj = curEmptyAdj;
+        boolean changed = false;
         while (i > 0) {
             i--;
             ProcessRecord app = mLruProcesses.get(i);
             //Slog.i(TAG, "OOM " + app + ": cur cached=" + curCachedAdj);
-            updateOomAdjLocked(app, curCachedAdj, curClientCachedAdj, curEmptyAdj, TOP_APP, true);
+            app.setAdjChanged = false;
+            updateOomAdjLocked(app, curCachedAdj, curClientCachedAdj, curEmptyAdj, TOP_APP,
+                    true, now);
+            changed |= app.setAdjChanged;
             if (!app.killedBackground) {
                 if (app.curRawAdj == curCachedAdj && app.hasActivities) {
                     // This process was assigned as a cached process...  step the
                     // cached level.
-                    mNumCachedProcs++;
+                    mNumCachedHiddenProcs++;
                     if (curCachedAdj != nextCachedAdj) {
                         stepCached++;
                         if (stepCached >= cachedFactor) {
@@ -14188,6 +14193,7 @@
         // are managing to keep around is less than half the maximum we desire;
         // if we are keeping a good number around, we'll let them use whatever
         // memory they want.
+        int memFactor = ProcessTracker.STATE_MEM_FACTOR_NORMAL_ADJ;
         if (numCached <= ProcessList.TRIM_CACHED_APPS
                 && numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
             final int numCachedAndEmpty = numCached + numEmpty;
@@ -14201,10 +14207,13 @@
             int fgTrimLevel;
             if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
+                memFactor = ProcessTracker.STATE_MEM_FACTOR_CRITIAL_ADJ;
             } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
+                memFactor = ProcessTracker.STATE_MEM_FACTOR_LOW_ADJ;
             } else {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
+                memFactor = ProcessTracker.STATE_MEM_FACTOR_MODERATE_ADJ;
             }
             int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
             for (i=0; i<N; i++) {
@@ -14303,6 +14312,21 @@
             // be in a consistent state at this point.
             mStackSupervisor.scheduleDestroyAllActivities(null, "always-finish");
         }
+
+        boolean allChanged = mProcessTracker.setMemFactor(memFactor, !mSleeping, now);
+        if (changed || allChanged) {
+            memFactor = mProcessTracker.getMemFactor();
+            for (i=mLruProcesses.size()-1; i>=0; i--) {
+                ProcessRecord app = mLruProcesses.get(i);
+                if (allChanged || app.setAdjChanged) {
+                    app.setProcessTrackerState(TOP_APP, memFactor, now, mProcessList);
+                }
+            }
+        }
+
+        if (DEBUG_OOM_ADJ) {
+            Slog.d(TAG, "Did OOM ADJ in " + (SystemClock.uptimeMillis()-now) + "ms");
+        }
     }
 
     final void trimApplications() {
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 6fe28f4..ba8de39 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -987,7 +987,7 @@
 
         if (app != null && app.thread != null) {
             try {
-                app.addPackage(r.info.packageName);
+                app.addPackage(r.info.packageName, mService.mProcessTracker);
                 realStartActivityLocked(r, app, andResume, checkConfig);
                 return;
             } catch (RemoteException e) {
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index c7e6010..0e7513c 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -795,7 +795,7 @@
                     info.activityInfo.applicationInfo.uid);
             if (app != null && app.thread != null) {
                 try {
-                    app.addPackage(info.activityInfo.packageName);
+                    app.addPackage(info.activityInfo.packageName, mService.mProcessTracker);
                     processCurBroadcastLocked(r, app);
                     return;
                 } catch (RemoteException e) {
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
index f56371c..59e6787 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -300,7 +300,7 @@
             // Tell all processes that loaded this package about the change.
             for (int i=mService.mLruProcesses.size()-1; i>=0; i--) {
                 ProcessRecord app = mService.mLruProcesses.get(i);
-                if (!app.pkgList.contains(packageName)) {
+                if (!app.pkgList.containsKey(packageName)) {
                     continue;
                 }
                 try {
diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java
index e937d35..b5d783d 100644
--- a/services/java/com/android/server/am/ProcessList.java
+++ b/services/java/com/android/server/am/ProcessList.java
@@ -244,7 +244,7 @@
     }
 
     int adjToTrackedState(int adj) {
-        return mAdjToTrackedState[adj];
+        return adj >= FOREGROUND_APP_ADJ ? mAdjToTrackedState[adj] : ProcessTracker.STATE_NOTHING;
     }
 
     private void writeFile(String path, String data) {
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 6cae67c..cc0a5a3 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -51,9 +51,10 @@
     final int uid;              // uid of process; may be different from 'info' if isolated
     final int userId;           // user of process.
     final String processName;   // name of the process
-    final ProcessTracker.ProcessState tracker; // tracking execution of process
+    final ProcessTracker.ProcessState baseProcessTracker;
     // List of packages running in the process
-    final HashSet<String> pkgList = new HashSet<String>();
+    final ArrayMap<String, ProcessTracker.ProcessState> pkgList
+            = new ArrayMap<String, ProcessTracker.ProcessState>();
     IApplicationThread thread;  // the actual proc...  may be null only if
                                 // 'persistent' is true (in which case we
                                 // are in the process of launching the app)
@@ -87,6 +88,7 @@
     boolean hasAboveClient;     // Bound using BIND_ABOVE_CLIENT, so want to be lower
     boolean bad;                // True if disabled in the bad process list
     boolean killedBackground;   // True when proc has been killed due to too many bg
+    boolean setAdjChanged;      // Keep track of whether we changed 'setAdj'.
     String waitingToKill;       // Process is waiting to be killed when in the bg; reason
     IBinder forcingToForeground;// Token that is forcing this process to be foreground
     int adjSeq;                 // Sequence id for identifying oom_adj assignment cycles
@@ -327,15 +329,15 @@
     
     ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
             ApplicationInfo _info, String _processName, int _uid,
-            ProcessTracker.ProcessState _tracker) {
+            ProcessTracker.ProcessState tracker) {
         batteryStats = _batteryStats;
         info = _info;
         isolated = _info.uid != _uid;
         uid = _uid;
         userId = UserHandle.getUserId(_uid);
         processName = _processName;
-        tracker = _tracker;
-        pkgList.add(_info.packageName);
+        baseProcessTracker = tracker;
+        pkgList.put(_info.packageName, tracker);
         thread = _thread;
         maxAdj = ProcessList.CACHED_APP_MAX_ADJ;
         cachedAdj = clientCachedAdj = emptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
@@ -437,20 +439,33 @@
     /*
      *  Return true if package has been added false if not
      */
-    public boolean addPackage(String pkg) {
-        if (!pkgList.contains(pkg)) {
-            pkgList.add(pkg);
+    public boolean addPackage(String pkg, ProcessTracker tracker) {
+        if (!pkgList.containsKey(pkg)) {
+            pkgList.put(pkg, tracker.getProcessStateLocked(pkg, info.uid, processName));
             return true;
         }
         return false;
     }
-    
+
+    public void setProcessTrackerState(ProcessRecord TOP_APP, int memFactor, long now,
+            ProcessList plist) {
+        int state = this == TOP_APP ? ProcessTracker.STATE_TOP
+                : plist.adjToTrackedState(setAdj);
+        for (int ip=pkgList.size()-1; ip>=0; ip--) {
+            pkgList.valueAt(ip).setState(state, memFactor, now);
+        }
+    }
+
     /*
      *  Delete all packages from list except the package indicated in info
      */
     public void resetPackageList() {
+        long now = SystemClock.uptimeMillis();
+        for (int i=0; i<pkgList.size(); i++) {
+            pkgList.valueAt(i).setState(ProcessTracker.STATE_NOTHING, 0, now);
+        }
         pkgList.clear();
-        pkgList.add(info.packageName);
+        pkgList.put(info.packageName, baseProcessTracker);
     }
     
     public String[] getPackageList() {
@@ -459,7 +474,9 @@
             return null;
         }
         String list[] = new String[size];
-        pkgList.toArray(list);
+        for (int i=0; i<pkgList.size(); i++) {
+            list[i] = pkgList.keyAt(i);
+        }
         return list;
     }
 }
diff --git a/services/java/com/android/server/am/ProcessTracker.java b/services/java/com/android/server/am/ProcessTracker.java
index 4eb71c7..fb8d09c 100644
--- a/services/java/com/android/server/am/ProcessTracker.java
+++ b/services/java/com/android/server/am/ProcessTracker.java
@@ -36,7 +36,15 @@
     public static final int STATE_HOME = 6;
     public static final int STATE_PREVIOUS = 7;
     public static final int STATE_CACHED = 8;
-    public static final int STATE_SCREEN_ON_MOD = STATE_CACHED+1;
+    public static final int STATE_MEM_FACTOR_MOD = STATE_CACHED+1;
+    public static final int STATE_MEM_FACTOR_NORMAL_ADJ = 0;
+    public static final int STATE_MEM_FACTOR_MODERATE_ADJ = STATE_MEM_FACTOR_MOD;
+    public static final int STATE_MEM_FACTOR_LOW_ADJ = STATE_MEM_FACTOR_MOD*2;
+    public static final int STATE_MEM_FACTOR_CRITIAL_ADJ = STATE_MEM_FACTOR_MOD*3;
+    public static final int STATE_MEM_FACTOR_COUNT = STATE_MEM_FACTOR_MOD*4;
+    public static final int STATE_SCREEN_ON_MOD = STATE_MEM_FACTOR_COUNT;
+    public static final int STATE_SCREEN_OFF_ADJ = 0;
+    public static final int STATE_SCREEN_ON_ADJ = STATE_SCREEN_ON_MOD;
     public static final int STATE_COUNT = STATE_SCREEN_ON_MOD*2;
 
     static String[] STATE_NAMES = new String[] {
@@ -45,21 +53,44 @@
     };
 
     public static final class ProcessState {
-        final long[] mTimes = new long[STATE_COUNT];
+        final long[] mDurations = new long[STATE_COUNT];
         int mCurState = STATE_NOTHING;
         long mStartTime;
 
-        public void setState(int state, long now) {
-            if (mCurState != STATE_NOTHING) {
-                mTimes[mCurState] += now - mStartTime;
+        public void setState(int state, int memFactor, long now) {
+            if (state != STATE_NOTHING) {
+                state += memFactor;
             }
-            mCurState = state;
-            mStartTime = now;
+            if (mCurState != state) {
+                if (mCurState != STATE_NOTHING) {
+                    mDurations[mCurState] += now - mStartTime;
+                }
+                mCurState = state;
+                mStartTime = now;
+            }
+        }
+    }
+
+    public static final class ServiceState {
+        long mStartedDuration;
+        long mStartedTime;
+    }
+
+    public static final class PackageState {
+        final ArrayMap<String, ProcessState> mProcesses = new ArrayMap<String, ProcessState>();
+        final ArrayMap<String, ServiceState> mServices = new ArrayMap<String, ServiceState>();
+        final int mUid;
+
+        public PackageState(int uid) {
+            mUid = uid;
         }
     }
 
     static final class State {
-        final ProcessMap<ProcessState> mProcesses = new ProcessMap<ProcessState>();
+        final ProcessMap<PackageState> mPackages = new ProcessMap<PackageState>();
+        final long[] mMemFactorDurations = new long[STATE_COUNT/STATE_MEM_FACTOR_MOD];
+        int mMemFactor = STATE_NOTHING;
+        long mStartTime;
     }
 
     final State mState = new State();
@@ -67,44 +98,198 @@
     public ProcessTracker() {
     }
 
-    public ProcessState getStateLocked(String name, int uid) {
-        ProcessState ps = mState.mProcesses.get(name, uid);
+    private PackageState getPackageStateLocked(String packageName, int uid) {
+        PackageState as = mState.mPackages.get(packageName, uid);
+        if (as != null) {
+            return as;
+        }
+        as = new PackageState(uid);
+        mState.mPackages.put(packageName, uid, as);
+        return as;
+    }
+
+    public ProcessState getProcessStateLocked(String packageName, int uid, String processName) {
+        final PackageState as = getPackageStateLocked(packageName, uid);
+        ProcessState ps = as.mProcesses.get(processName);
         if (ps != null) {
             return ps;
         }
         ps = new ProcessState();
-        mState.mProcesses.put(name, uid, ps);
+        as.mProcesses.put(processName, ps);
         return ps;
     }
 
+    public ServiceState getServiceStateLocked(String packageName, int uid, String className) {
+        final PackageState as = getPackageStateLocked(packageName, uid);
+        ServiceState ss = as.mServices.get(className);
+        if (ss != null) {
+            return ss;
+        }
+        ss = new ServiceState();
+        as.mServices.put(className, ss);
+        return ss;
+    }
+
+    public boolean setMemFactor(int memFactor, boolean screenOn, long now) {
+        if (screenOn) {
+            memFactor += STATE_SCREEN_ON_MOD;
+        }
+        if (memFactor != mState.mMemFactor) {
+            if (mState.mMemFactor != STATE_NOTHING) {
+                mState.mMemFactorDurations[mState.mMemFactor/STATE_MEM_FACTOR_MOD]
+                        += now - mState.mStartTime;
+            }
+            mState.mMemFactor = memFactor;
+            mState.mStartTime = now;
+            return true;
+        }
+        return false;
+    }
+
+    public int getMemFactor() {
+        return mState.mMemFactor != STATE_NOTHING ? mState.mMemFactor : 0;
+    }
+
+    private void printScreenLabel(PrintWriter pw, int offset) {
+        switch (offset) {
+            case STATE_NOTHING:
+                pw.print("             ");
+                break;
+            case STATE_SCREEN_OFF_ADJ:
+                pw.print("Screen Off / ");
+                break;
+            case STATE_SCREEN_ON_ADJ:
+                pw.print("Screen On  / ");
+                break;
+            default:
+                pw.print("?????????? / ");
+                break;
+        }
+    }
+
+    private void printMemLabel(PrintWriter pw, int offset) {
+        switch (offset) {
+            case STATE_NOTHING:
+                pw.print("       ");
+                break;
+            case STATE_MEM_FACTOR_NORMAL_ADJ:
+                pw.print("Norm / ");
+                break;
+            case STATE_MEM_FACTOR_MODERATE_ADJ:
+                pw.print("Mod  / ");
+                break;
+            case STATE_MEM_FACTOR_LOW_ADJ:
+                pw.print("Low  / ");
+                break;
+            case STATE_MEM_FACTOR_CRITIAL_ADJ:
+                pw.print("Crit / ");
+                break;
+            default:
+                pw.print("???? / ");
+                break;
+        }
+    }
+
     public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
         final long now = SystemClock.uptimeMillis();
-        ArrayMap<String, SparseArray<ProcessState>> pmap = mState.mProcesses.getMap();
+        ArrayMap<String, SparseArray<PackageState>> pmap = mState.mPackages.getMap();
+        pw.println("Process Stats:");
         for (int ip=0; ip<pmap.size(); ip++) {
             String procName = pmap.keyAt(ip);
-            SparseArray<ProcessState> procs = pmap.valueAt(ip);
+            SparseArray<PackageState> procs = pmap.valueAt(ip);
             for (int iu=0; iu<procs.size(); iu++) {
                 int uid = procs.keyAt(iu);
-                ProcessState state = procs.valueAt(iu);
+                PackageState state = procs.valueAt(iu);
                 pw.print("  "); pw.print(procName); pw.print(" / "); pw.print(uid); pw.println(":");
-                long totalTime = 0;
-                for (int is=0; is<STATE_NAMES.length; is++) {
-                    long time = state.mTimes[is];
-                    if (state.mCurState == is) {
-                        time += now - state.mStartTime;
+                for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {
+                    pw.print("    Process ");
+                    pw.print(state.mProcesses.keyAt(iproc));
+                    pw.println(":");
+                    long totalTime = 0;
+                    ProcessState proc = state.mProcesses.valueAt(iproc);
+                    int printedScreen = -1;
+                    for (int iscreen=0; iscreen<STATE_COUNT; iscreen+=STATE_SCREEN_ON_MOD) {
+                        int printedMem = -1;
+                        for (int imem=0; imem<STATE_MEM_FACTOR_COUNT; imem+=STATE_MEM_FACTOR_MOD) {
+                            for (int is=0; is<STATE_NAMES.length; is++) {
+                                int bucket = is+imem+iscreen;
+                                long time = proc.mDurations[bucket];
+                                String running = "";
+                                if (proc.mCurState == bucket) {
+                                    time += now - proc.mStartTime;
+                                    running = " (running)";
+                                }
+                                if (time != 0) {
+                                    pw.print("      ");
+                                    printScreenLabel(pw, printedScreen != iscreen
+                                            ? iscreen : STATE_NOTHING);
+                                    printedScreen = iscreen;
+                                    printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+                                    printedMem = imem;
+                                    pw.print(STATE_NAMES[is]); pw.print(": ");
+                                    TimeUtils.formatDuration(time, pw); pw.println(running);
+                                    totalTime += time;
+                                }
+                            }
+                        }
+                    }
+                    if (totalTime != 0) {
+                        pw.print("      ");
+                        printScreenLabel(pw, STATE_NOTHING);
+                        printMemLabel(pw, STATE_NOTHING);
+                        pw.print("TOTAL      : ");
+                        TimeUtils.formatDuration(totalTime, pw);
+                        pw.println();
+                    }
+                }
+                for (int isvc=0; isvc<state.mServices.size(); isvc++) {
+                    pw.print("    Service ");
+                    pw.print(state.mServices.keyAt(isvc));
+                    pw.println(":");
+                    ServiceState svc = state.mServices.valueAt(isvc);
+                    long time = svc.mStartedDuration;
+                    if (svc.mStartedTime >= 0) {
+                        time += now - svc.mStartedTime;
                     }
                     if (time != 0) {
-                        pw.print("    "); pw.print(STATE_NAMES[is]); pw.print(": ");
+                        pw.print("    Started: ");
                         TimeUtils.formatDuration(time, pw); pw.println();
-                        totalTime += time;
                     }
                 }
-                if (totalTime != 0) {
-                    pw.print("    TOTAL      : ");
-                    TimeUtils.formatDuration(totalTime, pw);
-                    pw.println();
+            }
+        }
+        pw.println();
+        pw.println("Run time Stats:");
+        long totalTime = 0;
+        int printedScreen = -1;
+        for (int iscreen=0; iscreen<STATE_COUNT; iscreen+=STATE_SCREEN_ON_MOD) {
+            int printedMem = -1;
+            for (int imem=0; imem<STATE_MEM_FACTOR_COUNT; imem+=STATE_MEM_FACTOR_MOD) {
+                int bucket = imem+iscreen;
+                long time = mState.mMemFactorDurations[bucket/STATE_MEM_FACTOR_MOD];
+                String running = "";
+                if (mState.mMemFactor == bucket) {
+                    time += now - mState.mStartTime;
+                    running = " (running)";
+                }
+                if (time != 0) {
+                    pw.print("  ");
+                    printScreenLabel(pw, printedScreen != iscreen
+                            ? iscreen : STATE_NOTHING);
+                    printedScreen = iscreen;
+                    printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+                    printedMem = imem;
+                    TimeUtils.formatDuration(time, pw); pw.println(running);
+                    totalTime += time;
                 }
             }
         }
+        if (totalTime != 0) {
+            pw.print("  ");
+            printScreenLabel(pw, STATE_NOTHING);
+            pw.print("TOTAL: ");
+            TimeUtils.formatDuration(totalTime, pw);
+            pw.println();
+        }
     }
 }
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 4a3699c..82e8c7f 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -28,7 +28,6 @@
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayInfo;
-import android.view.InputChannel;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -101,11 +100,8 @@
     /** Sorted most recent at top, oldest at [0]. */
     ArrayList<TaskStack> mStackHistory = new ArrayList<TaskStack>();
 
-    /** Forward motion events to mTapDetector. */
-    InputChannel mTapInputChannel;
-
     /** Detect user tapping outside of current focused stack bounds .*/
-    StackTapDetector mTapDetector;
+    StackTapPointerEventListener mTapDetector;
 
     /** Detect user tapping outside of current focused stack bounds .*/
     Region mTouchExcludeRegion = new Region();
diff --git a/services/java/com/android/server/wm/PointerEventDispatcher.java b/services/java/com/android/server/wm/PointerEventDispatcher.java
new file mode 100644
index 0000000..6b0e4c9
--- /dev/null
+++ b/services/java/com/android/server/wm/PointerEventDispatcher.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2013 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.server.wm;
+
+import android.view.InputChannel;
+import android.view.InputDevice;
+import android.view.InputEvent;
+import android.view.InputEventReceiver;
+import android.view.MotionEvent;
+import android.view.WindowManagerPolicy.PointerEventListener;
+
+import com.android.server.UiThread;
+
+import java.util.ArrayList;
+
+public class PointerEventDispatcher extends InputEventReceiver {
+    ArrayList<PointerEventListener> mListeners = new ArrayList<PointerEventListener>();
+    PointerEventListener[] mListenersArray = new PointerEventListener[0];
+
+    public PointerEventDispatcher(InputChannel inputChannel) {
+        super(inputChannel, UiThread.getHandler().getLooper());
+    }
+
+    @Override
+    public void onInputEvent(InputEvent event) {
+        try {
+            if (event instanceof MotionEvent
+                    && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+                final MotionEvent motionEvent = (MotionEvent)event;
+                PointerEventListener[] listeners;
+                synchronized (mListeners) {
+                    if (mListenersArray == null) {
+                        mListenersArray = new PointerEventListener[mListeners.size()];
+                        mListeners.toArray(mListenersArray);
+                    }
+                    listeners = mListenersArray;
+                }
+                for (int i = 0; i < listeners.length; ++i) {
+                    listeners[i].onPointerEvent(motionEvent);
+                }
+            }
+        } finally {
+            finishInputEvent(event, false);
+        }
+    }
+
+    /**
+     * Add the specified listener to the list.
+     * @param listener The listener to add.
+     */
+    public void registerInputEventListener(PointerEventListener listener) {
+        synchronized (mListeners) {
+            if (mListeners.contains(listener)) {
+                throw new IllegalStateException("registerInputEventListener: trying to register" +
+                        listener + " twice.");
+            }
+            mListeners.add(listener);
+            mListenersArray = null;
+        }
+    }
+
+    /**
+     * Remove the specified listener from the list.
+     * @param listener The listener to remove.
+     */
+    public void unregisterInputEventListener(PointerEventListener listener) {
+        synchronized (mListeners) {
+            if (!mListeners.contains(listener)) {
+                throw new IllegalStateException("registerInputEventListener: " + listener +
+                        " not registered.");
+            }
+            mListeners.remove(listener);
+            mListenersArray = null;
+        }
+    }
+}
diff --git a/services/java/com/android/server/wm/StackTapDetector.java b/services/java/com/android/server/wm/StackTapDetector.java
deleted file mode 100644
index 7127fd2..0000000
--- a/services/java/com/android/server/wm/StackTapDetector.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2013 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.server.wm;
-
-import android.graphics.Region;
-import android.os.Looper;
-import android.view.DisplayInfo;
-import android.view.InputChannel;
-import android.view.InputDevice;
-import android.view.InputEvent;
-import android.view.InputEventReceiver;
-import android.view.MotionEvent;
-
-import com.android.server.wm.WindowManagerService.H;
-
-public class StackTapDetector extends InputEventReceiver {
-    private static final int TAP_TIMEOUT_MSEC = 300;
-    private static final float TAP_MOTION_SLOP_INCHES = 0.125f;
-
-    private final int mMotionSlop;
-    private float mDownX;
-    private float mDownY;
-    private int mPointerId;
-    final private Region mTouchExcludeRegion;
-    private final WindowManagerService mService;
-    private final DisplayContent mDisplayContent;
-
-    public StackTapDetector(WindowManagerService service, DisplayContent displayContent,
-            InputChannel inputChannel, Looper looper) {
-        super(inputChannel, looper);
-        mService = service;
-        mDisplayContent = displayContent;
-        mTouchExcludeRegion = displayContent.mTouchExcludeRegion;
-        DisplayInfo info = displayContent.getDisplayInfo();
-        mMotionSlop = (int)(info.logicalDensityDpi * TAP_MOTION_SLOP_INCHES);
-    }
-
-    @Override
-    public void onInputEvent(InputEvent event) {
-        try {
-            if (!(event instanceof MotionEvent)
-                    || !event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
-                return;
-            }
-            final MotionEvent motionEvent = (MotionEvent)event;
-            final int action = motionEvent.getAction();
-            switch (action & MotionEvent.ACTION_MASK) {
-                case MotionEvent.ACTION_DOWN:
-                    mPointerId = motionEvent.getPointerId(0);
-                    mDownX = motionEvent.getX();
-                    mDownY = motionEvent.getY();
-                    break;
-                case MotionEvent.ACTION_MOVE:
-                    if (mPointerId >= 0) {
-                        int index = motionEvent.findPointerIndex(mPointerId);
-                        if ((motionEvent.getEventTime() - motionEvent.getDownTime())
-                                > TAP_TIMEOUT_MSEC
-                                || (motionEvent.getX(index) - mDownX) > mMotionSlop
-                                || (motionEvent.getY(index) - mDownY) > mMotionSlop) {
-                            mPointerId = -1;
-                        }
-                    }
-                    break;
-                case MotionEvent.ACTION_UP:
-                case MotionEvent.ACTION_POINTER_UP: {
-                    int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
-                            >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
-                    // Extract the index of the pointer that left the touch sensor
-                    if (mPointerId == motionEvent.getPointerId(index)) {
-                        final int x = (int)motionEvent.getX(index);
-                        final int y = (int)motionEvent.getY(index);
-                        synchronized (this) {
-                            if ((motionEvent.getEventTime() - motionEvent.getDownTime())
-                                    < TAP_TIMEOUT_MSEC
-                                    && (x - mDownX) < mMotionSlop && (y - mDownY) < mMotionSlop
-                                    && !mTouchExcludeRegion.contains(x, y)) {
-                                mService.mH.obtainMessage(H.TAP_OUTSIDE_STACK, x, y,
-                                        mDisplayContent).sendToTarget();
-                            }
-                        }
-                        mPointerId = -1;
-                    }
-                    break;
-                }
-            }
-        } finally {
-            finishInputEvent(event, false /*ignored for monitors*/);
-        }
-    }
-}
diff --git a/services/java/com/android/server/wm/StackTapPointerEventListener.java b/services/java/com/android/server/wm/StackTapPointerEventListener.java
new file mode 100644
index 0000000..19d8ab3
--- /dev/null
+++ b/services/java/com/android/server/wm/StackTapPointerEventListener.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2013 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.server.wm;
+
+import android.graphics.Region;
+import android.view.DisplayInfo;
+import android.view.MotionEvent;
+import android.view.WindowManagerPolicy.PointerEventListener;
+
+import com.android.server.wm.WindowManagerService.H;
+
+public class StackTapPointerEventListener implements PointerEventListener {
+    private static final int TAP_TIMEOUT_MSEC = 300;
+    private static final float TAP_MOTION_SLOP_INCHES = 0.125f;
+
+    private final int mMotionSlop;
+    private float mDownX;
+    private float mDownY;
+    private int mPointerId;
+    final private Region mTouchExcludeRegion;
+    private final WindowManagerService mService;
+    private final DisplayContent mDisplayContent;
+
+    public StackTapPointerEventListener(WindowManagerService service,
+            DisplayContent displayContent) {
+        mService = service;
+        mDisplayContent = displayContent;
+        mTouchExcludeRegion = displayContent.mTouchExcludeRegion;
+        DisplayInfo info = displayContent.getDisplayInfo();
+        mMotionSlop = (int)(info.logicalDensityDpi * TAP_MOTION_SLOP_INCHES);
+    }
+
+    @Override
+    public void onPointerEvent(MotionEvent motionEvent) {
+        final int action = motionEvent.getAction();
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                mPointerId = motionEvent.getPointerId(0);
+                mDownX = motionEvent.getX();
+                mDownY = motionEvent.getY();
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mPointerId >= 0) {
+                    int index = motionEvent.findPointerIndex(mPointerId);
+                    if ((motionEvent.getEventTime() - motionEvent.getDownTime()) > TAP_TIMEOUT_MSEC
+                            || (motionEvent.getX(index) - mDownX) > mMotionSlop
+                            || (motionEvent.getY(index) - mDownY) > mMotionSlop) {
+                        mPointerId = -1;
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_POINTER_UP: {
+                int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
+                        >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+                // Extract the index of the pointer that left the touch sensor
+                if (mPointerId == motionEvent.getPointerId(index)) {
+                    final int x = (int)motionEvent.getX(index);
+                    final int y = (int)motionEvent.getY(index);
+                    if ((motionEvent.getEventTime() - motionEvent.getDownTime())
+                            < TAP_TIMEOUT_MSEC
+                            && (x - mDownX) < mMotionSlop && (y - mDownY) < mMotionSlop
+                            && !mTouchExcludeRegion.contains(x, y)) {
+                        mService.mH.obtainMessage(H.TAP_OUTSIDE_STACK, x, y,
+                                mDisplayContent).sendToTarget();
+                    }
+                    mPointerId = -1;
+                }
+                break;
+            }
+        }
+    }
+}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index f166c31..079134b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -124,6 +124,7 @@
 import android.view.WindowManagerPolicy;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManagerPolicy.FakeWindow;
+import android.view.WindowManagerPolicy.PointerEventListener;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Transformation;
@@ -281,8 +282,6 @@
     private static final String SYSTEM_SECURE = "ro.secure";
     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
 
-    private static final String TAP_INPUT_CHANNEL_NAME = "StackTapDetector";
-
     private static final int MAX_SCREENSHOT_RETRIES = 3;
 
     final private KeyguardDisableHandler mKeyguardDisableHandler;
@@ -594,6 +593,8 @@
     SparseArray<Task> mTaskIdToTask = new SparseArray<Task>();
     SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>();
 
+    private final PointerEventDispatcher mPointerEventDispatcher;
+
     final class DragInputEventReceiver extends InputEventReceiver {
         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
             super(inputChannel, looper);
@@ -728,6 +729,8 @@
         mDisplaySettings = new DisplaySettings(context);
         mDisplaySettings.readSettingsLocked();
 
+        mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG));
+
         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
         mDisplayManager.registerDisplayListener(this, null);
         Display[] displays = mDisplayManager.getDisplays();
@@ -5098,6 +5101,16 @@
                 mAnimatorDurationScale };
     }
 
+    @Override
+    public void registerPointerEventListener(PointerEventListener listener) {
+        mPointerEventDispatcher.registerInputEventListener(listener);
+    }
+
+    @Override
+    public void unregisterPointerEventListener(PointerEventListener listener) {
+        mPointerEventDispatcher.unregisterInputEventListener(listener);
+    }
+
     // Called by window manager policy. Not exposed externally.
     @Override
     public int getLidState() {
@@ -5117,12 +5130,6 @@
 
     // Called by window manager policy.  Not exposed externally.
     @Override
-    public InputChannel monitorInput(String inputChannelName) {
-        return mInputManager.monitorInput(inputChannelName);
-    }
-
-    // Called by window manager policy.  Not exposed externally.
-    @Override
     public void switchKeyboardLayout(int deviceId, int direction) {
         mInputManager.switchKeyboardLayout(deviceId, direction);
     }
@@ -10652,10 +10659,8 @@
 
         // TODO: Create an input channel for each display with touch capability.
         if (displayId == Display.DEFAULT_DISPLAY) {
-            InputChannel inputChannel = monitorInput(TAP_INPUT_CHANNEL_NAME);
-            displayContent.mTapInputChannel = inputChannel;
-            displayContent.mTapDetector =
-                    new StackTapDetector(this, displayContent, inputChannel, Looper.myLooper());
+            displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
+            registerPointerEventListener(displayContent.mTapDetector);
         }
 
         return displayContent;
@@ -10838,10 +10843,9 @@
         if (displayContent != null) {
             mDisplayContents.delete(displayId);
 
-            if (displayContent.mTapInputChannel != null) {
-                displayContent.mTapInputChannel.dispose();
+            if (displayId == Display.DEFAULT_DISPLAY) {
+                unregisterPointerEventListener(displayContent.mTapDetector);
             }
-
             WindowList windows = displayContent.getWindowList();
             while (!windows.isEmpty()) {
                 final WindowState win = windows.get(windows.size() - 1);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index b78f589..584411b 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -174,6 +174,11 @@
     boolean setRadio(boolean turnOn);
 
     /**
+     * Set the radio to on or off unconditionally
+     */
+    boolean setRadioPower(boolean turnOn);
+
+    /**
      * Request to update location information in service state
      */
     void updateServiceLocation();
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ArrayMapTests.java b/tests/ActivityTests/src/com/google/android/test/activity/ArrayMapTests.java
index 7d82cd3..9b54927 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ArrayMapTests.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ArrayMapTests.java
@@ -17,10 +17,12 @@
 package com.google.android.test.activity;
 
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
@@ -137,41 +139,35 @@
             }
         }
 
+        return true;
+    }
+
+    private static boolean compareSets(HashSet set, ArraySet array) {
+        if (set.size() != array.size()) {
+            Log.e("test", "Bad size: expected " + set.size() + ", got " + array.size());
+            return false;
+        }
+
+        for (Object entry : set) {
+            if (!array.contains(entry)) {
+                Log.e("test", "Bad value: expected " + entry + " not found in ArraySet");
+                return false;
+            }
+        }
+
+        for (int i=0; i<array.size(); i++) {
+            Object entry = array.valueAt(i);
+            if (!set.contains(entry)) {
+                Log.e("test", "Bad value: unexpected " + entry + " in ArraySet");
+                return false;
+            }
+        }
+
         int index = 0;
-        for (Object entry : array.entrySet()) {
-            Object key = ((Map.Entry)entry).getKey();
-            Object value = ((Map.Entry)entry).getValue();
-            Object realKey = array.keyAt(index);
-            Object realValue = array.valueAt(index);
-            if (!compare(key, realKey)) {
-                Log.e("test", "Bad entry iterator: expected key " + realKey + ", got " + key
-                        + " at index " + index);
-                return false;
-            }
-            if (!compare(value, realValue)) {
-                Log.e("test", "Bad entry iterator: expected value " + realValue + ", got " + value
-                        + " at index " + index);
-                return false;
-            }
-            index++;
-        }
-
-        index = 0;
-        for (Object key : array.keySet()) {
-            Object realKey = array.keyAt(index);
-            if (!compare(key, realKey)) {
-                Log.e("test", "Bad key iterator: expected key " + realKey + ", got " + key
-                        + " at index " + index);
-                return false;
-            }
-            index++;
-        }
-
-        index = 0;
-        for (Object value : array.values()) {
-            Object realValue = array.valueAt(index);
-            if (!compare(value, realValue)) {
-                Log.e("test", "Bad value iterator: expected value " + realValue + ", got " + value
+        for (Object entry : array) {
+            Object realEntry = array.valueAt(index);
+            if (!compare(entry, realEntry)) {
+                Log.e("test", "Bad iterator: expected value " + realEntry + ", got " + entry
                         + " at index " + index);
                 return false;
             }
@@ -190,14 +186,14 @@
             Object value = entry.getKey();
             Object realValue = array.keyAt(index);
             if (!compare(realValue, value)) {
-                Log.e("test", "Bad hash array entry set: expected key " + realValue
+                Log.e("test", "Bad array map entry set: expected key " + realValue
                         + ", got " + value + " at index " + index);
                 return false;
             }
             value = entry.getValue();
             realValue = array.valueAt(index);
             if (!compare(realValue, value)) {
-                Log.e("test", "Bad hash array entry set: expected value " + realValue
+                Log.e("test", "Bad array map entry set: expected value " + realValue
                         + ", got " + value + " at index " + index);
                 return false;
             }
@@ -211,7 +207,7 @@
             Object value = keyIt.next();
             Object realValue = array.keyAt(index);
             if (!compare(realValue, value)) {
-                Log.e("test", "Bad hash array key set: expected key " + realValue
+                Log.e("test", "Bad array map key set: expected key " + realValue
                         + ", got " + value + " at index " + index);
                 return false;
             }
@@ -225,7 +221,7 @@
             Object value = valueIt.next();
             Object realValue = array.valueAt(index);
             if (!compare(realValue, value)) {
-                Log.e("test", "Bad hash array value col: expected value " + realValue
+                Log.e("test", "Bad array map value col: expected value " + realValue
                         + ", got " + value + " at index " + index);
                 return false;
             }
@@ -235,7 +231,7 @@
         return true;
     }
 
-    private static void dump(HashMap map, ArrayMap array) {
+    private static void dump(Map map, ArrayMap array) {
         Log.e("test", "HashMap of " + map.size() + " entries:");
         Set<Map.Entry> mapSet = map.entrySet();
         for (Map.Entry entry : mapSet) {
@@ -247,6 +243,17 @@
         }
     }
 
+    private static void dump(Set set, ArraySet array) {
+        Log.e("test", "HashSet of " + set.size() + " entries:");
+        for (Object entry : set) {
+            Log.e("test", "    " + entry);
+        }
+        Log.e("test", "ArraySet of " + array.size() + " entries:");
+        for (int i=0; i<array.size(); i++) {
+            Log.e("test", "    " + array.valueAt(i));
+        }
+    }
+
     private static void dump(ArrayMap map1, ArrayMap map2) {
         Log.e("test", "ArrayMap of " + map1.size() + " entries:");
         Set<Map.Entry> mapSet = map1.entrySet();
@@ -260,60 +267,93 @@
     }
 
     public static void run() {
-        HashMap<ControlledHash, Integer> mHashMap = new HashMap<ControlledHash, Integer>();
-        ArrayMap<ControlledHash, Integer> mArrayMap = new ArrayMap<ControlledHash, Integer>();
+        HashMap<ControlledHash, Integer> hashMap = new HashMap<ControlledHash, Integer>();
+        ArrayMap<ControlledHash, Integer> arrayMap = new ArrayMap<ControlledHash, Integer>();
+        HashSet<ControlledHash> hashSet = new HashSet<ControlledHash>();
+        ArraySet<ControlledHash> arraySet = new ArraySet<ControlledHash>();
 
         for (int i=0; i<OPS.length; i++) {
-            Integer oldMap;
+            Integer oldHash;
             Integer oldArray;
+            boolean hashChanged;
+            boolean arrayChanged;
             switch (OPS[i]) {
                 case OP_ADD:
                     Log.i("test", "Adding key: " + KEYS[i]);
-                    oldMap = mHashMap.put(new ControlledHash(KEYS[i]), i);
-                    oldArray = mArrayMap.put(new ControlledHash(KEYS[i]), i);
+                    oldHash = hashMap.put(new ControlledHash(KEYS[i]), i);
+                    oldArray = arrayMap.put(new ControlledHash(KEYS[i]), i);
+                    hashChanged = hashSet.add(new ControlledHash(KEYS[i]));
+                    arrayChanged = arraySet.add(new ControlledHash(KEYS[i]));
                     break;
                 case OP_REM:
                     Log.i("test", "Removing key: " + KEYS[i]);
-                    oldMap = mHashMap.remove(new ControlledHash(KEYS[i]));
-                    oldArray = mArrayMap.remove(new ControlledHash(KEYS[i]));
+                    oldHash = hashMap.remove(new ControlledHash(KEYS[i]));
+                    oldArray = arrayMap.remove(new ControlledHash(KEYS[i]));
+                    hashChanged = hashSet.remove(new ControlledHash(KEYS[i]));
+                    arrayChanged = arraySet.remove(new ControlledHash(KEYS[i]));
                     break;
                 default:
                     Log.e("test", "Bad operation " + OPS[i] + " @ " + i);
                     return;
             }
-            if (!compare(oldMap, oldArray)) {
-                Log.e("test", "Bad result: expected " + oldMap + ", got " + oldArray);
-                dump(mHashMap, mArrayMap);
+            if (!compare(oldHash, oldArray)) {
+                Log.e("test", "Bad result: expected " + oldHash + ", got " + oldArray);
+                dump(hashMap, arrayMap);
                 return;
             }
-            if (!validateArrayMap(mArrayMap)) {
-                dump(mHashMap, mArrayMap);
+            if (hashChanged != arrayChanged) {
+                Log.e("test", "Bad change: expected " + hashChanged + ", got " + arrayChanged);
+                dump(hashSet, arraySet);
                 return;
             }
-            if (!compareMaps(mHashMap, mArrayMap)) {
-                dump(mHashMap, mArrayMap);
+            if (!validateArrayMap(arrayMap)) {
+                dump(hashMap, arrayMap);
+                return;
+            }
+            if (!compareMaps(hashMap, arrayMap)) {
+                dump(hashMap, arrayMap);
+                return;
+            }
+            if (!compareSets(hashSet, arraySet)) {
+                dump(hashSet, arraySet);
                 return;
             }
         }
 
-        mArrayMap.put(new ControlledHash(50000), 100);
+        arrayMap.put(new ControlledHash(50000), 100);
         ControlledHash lookup = new ControlledHash(50000);
-        Iterator<ControlledHash> it = mArrayMap.keySet().iterator();
+        Iterator<ControlledHash> it = arrayMap.keySet().iterator();
         while (it.hasNext()) {
             if (it.next().equals(lookup)) {
                 it.remove();
             }
         }
-        if (mArrayMap.containsKey(lookup)) {
-            Log.e("test", "Bad iterator: didn't remove test key");
-            dump(mHashMap, mArrayMap);
+        if (arrayMap.containsKey(lookup)) {
+            Log.e("test", "Bad map iterator: didn't remove test key");
+            dump(hashMap, arrayMap);
         }
 
-        if (!equalsTest()) {
+        arraySet.add(new ControlledHash(50000));
+        it = arraySet.iterator();
+        while (it.hasNext()) {
+            if (it.next().equals(lookup)) {
+                it.remove();
+            }
+        }
+        if (arraySet.contains(lookup)) {
+            Log.e("test", "Bad set iterator: didn't remove test key");
+            dump(hashSet, arraySet);
+        }
+
+        if (!equalsMapTest()) {
             return;
         }
 
-        // copy constructor test
+        if (!equalsSetTest()) {
+            return;
+        }
+
+        // map copy constructor test
         ArrayMap newMap = new ArrayMap<Integer, String>();
         for (int i = 0; i < 10; ++i) {
             newMap.put(i, String.valueOf(i));
@@ -322,15 +362,31 @@
         if (!compare(mapCopy, newMap)) {
             Log.e("test", "ArrayMap copy constructor failure: expected " +
                     newMap + ", got " + mapCopy);
-            dump(mHashMap, mArrayMap);
+            dump(newMap, mapCopy);
+            return;
+        }
+
+        // set copy constructor test
+        ArraySet newSet = new ArraySet<Integer>();
+        for (int i = 0; i < 10; ++i) {
+            newSet.add(i);
+        }
+        ArraySet setCopy = new ArraySet(newSet);
+        if (!compare(setCopy, newSet)) {
+            Log.e("test", "ArraySet copy constructor failure: expected " +
+                    newSet + ", got " + setCopy);
+            dump(newSet, setCopy);
             return;
         }
 
         Log.e("test", "Test successful; printing final map.");
-        dump(mHashMap, mArrayMap);
+        dump(hashMap, arrayMap);
+
+        Log.e("test", "Test successful; printing final set.");
+        dump(hashSet, arraySet);
     }
 
-    private static boolean equalsTest() {
+    private static boolean equalsMapTest() {
         ArrayMap<Integer, String> map1 = new ArrayMap<Integer, String>();
         ArrayMap<Integer, String> map2 = new ArrayMap<Integer, String>();
         HashMap<Integer, String> map3 = new HashMap<Integer, String>();
@@ -368,4 +424,42 @@
 
         return true;
     }
+
+    private static boolean equalsSetTest() {
+        ArraySet<Integer> set1 = new ArraySet<Integer>();
+        ArraySet<Integer> set2 = new ArraySet<Integer>();
+        HashSet<Integer> set3 = new HashSet<Integer>();
+        if (!compare(set1, set2) || !compare(set1, set3) || !compare(set3, set2)) {
+            Log.e("test", "ArraySet equals failure for empty sets " + set1 + ", " +
+                    set2 + ", " + set3);
+            return false;
+        }
+
+        for (int i = 0; i < 10; ++i) {
+            set1.add(i);
+            set2.add(i);
+            set3.add(i);
+        }
+        if (!compare(set1, set2) || !compare(set1, set3) || !compare(set3, set2)) {
+            Log.e("test", "ArraySet equals failure for populated sets " + set1 + ", " +
+                    set2 + ", " + set3);
+            return false;
+        }
+
+        set1.remove(0);
+        if (compare(set1, set2) || compare(set1, set3) || compare(set3, set1)) {
+            Log.e("test", "ArraSet equals failure for set size " + set1 + ", " +
+                    set2 + ", " + set3);
+            return false;
+        }
+
+        set1.add(-1);
+        if (compare(set1, set2) || compare(set1, set3) || compare(set3, set1)) {
+            Log.e("test", "ArraySet equals failure for set contents " + set1 + ", " +
+                    set2 + ", " + set3);
+            return false;
+        }
+
+        return true;
+    }
 }