Merge "Add timer to SIP session creation process." into gingerbread
diff --git a/Android.mk b/Android.mk
index 84376ce..566b36f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -352,6 +352,7 @@
 # The since flag (-since N.xml API_LEVEL) is used to add API Level information
 # to the reference documentation. Must be in order of oldest to newest.
 framework_docs_LOCAL_DROIDDOC_OPTIONS := \
+    -knowntags ./frameworks/base/docs/knowntags.txt \
     -since ./frameworks/base/api/1.xml 1 \
     -since ./frameworks/base/api/2.xml 2 \
     -since ./frameworks/base/api/3.xml 3 \
@@ -360,10 +361,13 @@
     -since ./frameworks/base/api/6.xml 6 \
     -since ./frameworks/base/api/7.xml 7 \
     -since ./frameworks/base/api/8.xml 8 \
-		-error 1 -error 2 -warning 3 -error 4 -error 6 -error 8 -error 14 \
-		-overview $(LOCAL_PATH)/core/java/overview.html
+    -werror -hide 13 \
+    -overview $(LOCAL_PATH)/core/java/overview.html
 
-framework_docs_LOCAL_ADDITIONAL_JAVA_DIR:=$(call intermediates-dir-for,JAVA_LIBRARIES,framework)
+framework_docs_LOCAL_ADDITIONAL_JAVA_DIR:= $(call intermediates-dir-for,JAVA_LIBRARIES,framework)
+
+framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES := \
+    frameworks/base/docs/knowntags.txt
 
 sample_dir := development/samples
 
@@ -423,25 +427,12 @@
 framework_docs_SDK_VERSION:=2.2
   # release version (ie "Release x")  (full releases only)
 framework_docs_SDK_REL_ID:=1
-  # name of current SDK directory (full releases only)
-framework_docs_SDK_CURRENT_DIR:=$(framework_docs_SDK_VERSION)_r$(framework_docs_SDK_REL_ID)
   # flag to build offline docs for a preview release
 framework_docs_SDK_PREVIEW:=0
 
-## Latest ADT version identifiers, for reference from published docs
-framework_docs_ADT_VERSION:=0.9.8
-framework_docs_ADT_DOWNLOAD:=ADT-0.9.8.zip
-framework_docs_ADT_BYTES:=8301417
-framework_docs_ADT_CHECKSUM:=27e0de800512f13feae46fb554e6ee2f
-
 framework_docs_LOCAL_DROIDDOC_OPTIONS += \
 		-hdf sdk.version $(framework_docs_SDK_VERSION) \
-		-hdf sdk.rel.id $(framework_docs_SDK_REL_ID) \
-		-hdf sdk.current $(framework_docs_SDK_CURRENT_DIR) \
-		-hdf adt.zip.version $(framework_docs_ADT_VERSION) \
-		-hdf adt.zip.download $(framework_docs_ADT_DOWNLOAD) \
-		-hdf adt.zip.bytes $(framework_docs_ADT_BYTES) \
-		-hdf adt.zip.checksum $(framework_docs_ADT_CHECKSUM) 
+		-hdf sdk.rel.id $(framework_docs_SDK_REL_ID)
 
 # ====  the api stubs and current.xml ===========================
 include $(CLEAR_VARS)
@@ -453,6 +444,7 @@
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
 LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
 LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
+LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
 
 LOCAL_MODULE := api-stubs
 
@@ -481,6 +473,7 @@
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
 LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
 LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
+LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
 
 LOCAL_MODULE := doc-comment-check
 
@@ -508,6 +501,7 @@
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
 LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
 LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
+LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
 
 LOCAL_MODULE := offline-sdk
 
@@ -522,7 +516,7 @@
 		-hdf android.whichdoc offline 
 
 ifeq ($(framework_docs_SDK_PREVIEW),true)
-  LOCAL_DROIDDOC_OPTIONS += -hdf sdk.current preview 
+  LOCAL_DROIDDOC_OPTIONS += -hdf sdk.preview true
 endif
 
 LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
@@ -551,6 +545,7 @@
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
 LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
 LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
+LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
 
 LOCAL_MODULE := online-sdk
 
@@ -579,6 +574,7 @@
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
 LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
 LOCAL_ADDITIONAL_JAVA_DIR:=$(call intermediates-dir-for,JAVA_LIBRARIES,framework)
+LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
 
 LOCAL_MODULE := hidden
 LOCAL_DROIDDOC_OPTIONS:=\
@@ -608,7 +604,7 @@
 
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_JAVA_LIBRARIES := core
-
+LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := ext
 
 LOCAL_NO_EMMA_INSTRUMENT := true
diff --git a/api/current.xml b/api/current.xml
index 81090a4..aff615c 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -33609,7 +33609,7 @@
  value="2743"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -177751,17 +177751,6 @@
  visibility="public"
 >
 </field>
-<field name="SOURCE_CLASS_JOYSTICK"
- type="int"
- transient="false"
- volatile="false"
- value="16"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="SOURCE_CLASS_MASK"
  type="int"
  transient="false"
@@ -177817,39 +177806,6 @@
  visibility="public"
 >
 </field>
-<field name="SOURCE_GAMEPAD"
- type="int"
- transient="false"
- volatile="false"
- value="1025"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="SOURCE_JOYSTICK_LEFT"
- type="int"
- transient="false"
- volatile="false"
- value="16777232"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="SOURCE_JOYSTICK_RIGHT"
- type="int"
- transient="false"
- volatile="false"
- value="33554448"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="SOURCE_KEYBOARD"
  type="int"
  transient="false"
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 4a1d27b..8ab94ad 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -60,7 +60,7 @@
     return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
 }
 
-static void playSource(OMXClient *client, const sp<MediaSource> &source) {
+static void playSource(OMXClient *client, sp<MediaSource> &source) {
     sp<MetaData> meta = source->getFormat();
 
     const char *mime;
@@ -81,6 +81,8 @@
         }
     }
 
+    source.clear();
+
     status_t err = rawSource->start();
 
     if (err != OK) {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 16a8c57..33fd395 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -465,11 +465,11 @@
     }
 
     /**
-     * Set the friendly Bluetooth name of the local Bluetoth adapter.
+     * Set the friendly Bluetooth name of the local Bluetooth adapter.
      * <p>This name is visible to remote Bluetooth devices.
-     * <p>Valid Bluetooth names are a maximum of 248 UTF-8 characters, however
-     * many remote devices can only display the first 40 characters, and some
-     * may be limited to just 20.
+     * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
+     * encoding, although many remote devices can only display the first
+     * 40 characters, and some may be limited to just 20.
      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
      * will return false. After turning on Bluetooth,
      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
@@ -488,7 +488,7 @@
     }
 
     /**
-     * Get the current Bluetooth scan mode of the local Bluetooth adaper.
+     * Get the current Bluetooth scan mode of the local Bluetooth adapter.
      * <p>The Bluetooth scan mode determines if the local adapter is
      * connectable and/or discoverable from remote Bluetooth devices.
      * <p>Possible values are:
@@ -611,7 +611,7 @@
     /**
      * Cancel the current device discovery process.
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
-     * <p>Because discovery is a heavyweight precedure for the Bluetooth
+     * <p>Because discovery is a heavyweight procedure for the Bluetooth
      * adapter, this method should always be called before attempting to connect
      * to a remote device with {@link
      * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index 9dd7b9f..c0a268f 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -37,8 +37,9 @@
 public abstract class AbstractThreadedSyncAdapter {
     /**
      * Kernel event log tag.  Also listed in data/etc/event-log-tags.
-     * @Deprecated
+     * @deprecated Private constant.  May go away in the next release.
      */
+    @Deprecated
     public static final int LOG_SYNC_DETAILS = 2743;
 
     private final Context mContext;
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 7945f3f..12e9bab 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -272,13 +272,14 @@
      * The ContentValues back references are represented as a ContentValues object where the
      * key refers to a column and the value is an index of the back reference whose
      * valued should be associated with the column.
+     * <p>
+     * This is intended to be a private method but it is exposed for
+     * unit testing purposes
      * @param backRefs an array of previous results
      * @param numBackRefs the number of valid previous results in backRefs
      * @return the ContentValues that should be used in this operation application after
      * expansion of back references. This can be called if either mValues or mValuesBackReferences
      * is null
-     * @VisibleForTesting this is intended to be a private method but it is exposed for
-     * unit testing purposes
      */
     public ContentValues resolveValueBackReferences(
             ContentProviderResult[] backRefs, int numBackRefs) {
@@ -308,13 +309,14 @@
      * the key is an index into the selection argument array (see {@link Builder#withSelection})
      * and the value is the index of the previous result that should be used for that selection
      * argument array slot.
+     * <p>
+     * This is intended to be a private method but it is exposed for
+     * unit testing purposes
      * @param backRefs an array of previous results
      * @param numBackRefs the number of valid previous results in backRefs
      * @return the ContentValues that should be used in this operation application after
      * expansion of back references. This can be called if either mValues or mValuesBackReferences
      * is null
-     * @VisibleForTesting this is intended to be a private method but it is exposed for
-     * unit testing purposes
      */
     public String[] resolveSelectionArgsBackReferences(
             ContentProviderResult[] backRefs, int numBackRefs) {
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 0068724..a271075 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -24,6 +24,7 @@
 import android.os.ServiceManager;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.view.IRotationWatcher;
 import android.view.IWindowManager;
 import android.view.Surface;
@@ -446,12 +447,12 @@
                     int accuracy = status[0];
                     synchronized (sListeners) {
                         if (sensor == -1 || sListeners.isEmpty()) {
-                            if (sensor == -1) {
-                                // we lost the connection to the event stream. this happens
-                                // when the last listener is removed.
-                                Log.d(TAG, "_sensors_data_poll() failed, we bail out.");
+                            // we lost the connection to the event stream. this happens
+                            // when the last listener is removed or if there is an error
+                            if (sensor == -1 && !sListeners.isEmpty()) {
+                                // log a warning in case of abnormal termination
+                                Log.e(TAG, "_sensors_data_poll() failed, we bail out: sensors=" + sensor);
                             }
-
                             // we have no more listeners or polling failed, terminate the thread
                             sensors_destroy_queue(sQueue);
                             sQueue = 0;
@@ -487,7 +488,7 @@
         private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
         private final Handler mHandler;
         private SensorEvent mValuesPool;
-        public int mSensors;
+        public SparseBooleanArray mSensors = new SparseBooleanArray();
 
         ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
             mSensorEventListener = listener;
@@ -541,18 +542,17 @@
             return mSensorEventListener;
         }
 
-        int addSensor(Sensor sensor) {
-            mSensors |= 1<<sensor.getHandle();
+        void addSensor(Sensor sensor) {
+            mSensors.put(sensor.getHandle(), true);
             mSensorList.add(sensor);
-            return mSensors;
         }
         int removeSensor(Sensor sensor) {
-            mSensors &= ~(1<<sensor.getHandle());
+            mSensors.delete(sensor.getHandle());
             mSensorList.remove(sensor);
-            return mSensors;
+            return mSensors.size();
         }
         boolean hasSensor(Sensor sensor) {
-            return ((mSensors & (1<<sensor.getHandle())) != 0);
+            return mSensors.get(sensor.getHandle());
         }
         List<Sensor> getSensors() {
             return mSensorList;
@@ -971,6 +971,31 @@
         return registerListener(listener, sensor, rate, null);
     }
 
+    private boolean enableSensorLocked(Sensor sensor, int delay) {
+        boolean result = false;
+        for (ListenerDelegate i : sListeners) {
+            if (i.hasSensor(sensor)) {
+                String name = sensor.getName();
+                int handle = sensor.getHandle();
+                result = sensors_enable_sensor(sQueue, name, handle, delay);
+                break;
+            }
+        }
+        return result;
+    }
+
+    private boolean disableSensorLocked(Sensor sensor) {
+        for (ListenerDelegate i : sListeners) {
+            if (i.hasSensor(sensor)) {
+                // not an error, it's just that this sensor is still in use
+                return true;
+            }
+        }
+        String name = sensor.getName();
+        int handle = sensor.getHandle();
+        return sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
+    }
+
     /**
      * Registers a {@link android.hardware.SensorEventListener
      * SensorEventListener} for the given sensor.
@@ -1008,7 +1033,7 @@
         if (listener == null || sensor == null) {
             return false;
         }
-        boolean result;
+        boolean result = true;
         int delay = -1;
         switch (rate) {
             case SENSOR_DELAY_FASTEST:
@@ -1029,6 +1054,7 @@
         }
 
         synchronized (sListeners) {
+            // look for this listener in our list
             ListenerDelegate l = null;
             for (ListenerDelegate i : sListeners) {
                 if (i.getListener() == listener) {
@@ -1037,29 +1063,37 @@
                 }
             }
 
-            String name = sensor.getName();
-            int handle = sensor.getHandle();
+            // if we don't find it, add it to the list
             if (l == null) {
-                result = false;
                 l = new ListenerDelegate(listener, sensor, handler);
                 sListeners.add(l);
+                // if the list is not empty, start our main thread
                 if (!sListeners.isEmpty()) {
-                    result = sSensorThread.startLocked();
-                    if (result) {
-                        result = sensors_enable_sensor(sQueue, name, handle, delay);
-                        if (!result) {
-                            // there was an error, remove the listeners
+                    if (sSensorThread.startLocked()) {
+                        if (!enableSensorLocked(sensor, delay)) {
+                            // oops. there was an error
                             sListeners.remove(l);
+                            result = false;
                         }
+                    } else {
+                        // there was an error, remove the listener
+                        sListeners.remove(l);
+                        result = false;
                     }
+                } else {
+                    // weird, we couldn't add the listener
+                    result = false;
                 }
             } else {
-                result = sensors_enable_sensor(sQueue, name, handle, delay);
-                if (result) {
-                    l.addSensor(sensor);
+                l.addSensor(sensor);
+                if (!enableSensorLocked(sensor, delay)) {
+                    // oops. there was an error
+                    l.removeSensor(sensor);
+                    result = false;
                 }
             }
         }
+
         return result;
     }
 
@@ -1067,23 +1101,21 @@
         if (listener == null || sensor == null) {
             return;
         }
+
         synchronized (sListeners) {
             final int size = sListeners.size();
             for (int i=0 ; i<size ; i++) {
                 ListenerDelegate l = sListeners.get(i);
                 if (l.getListener() == listener) {
-                    // disable these sensors
-                    String name = sensor.getName();
-                    int handle = sensor.getHandle();
-                    sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
-                    // if we have no more sensors enabled on this listener,
-                    // take it off the list.
                     if (l.removeSensor(sensor) == 0) {
+                        // if we have no more sensors enabled on this listener,
+                        // take it off the list.
                         sListeners.remove(i);
                     }
                     break;
                 }
             }
+            disableSensorLocked(sensor);
         }
     }
 
@@ -1091,18 +1123,17 @@
         if (listener == null) {
             return;
         }
+
         synchronized (sListeners) {
             final int size = sListeners.size();
             for (int i=0 ; i<size ; i++) {
                 ListenerDelegate l = sListeners.get(i);
                 if (l.getListener() == listener) {
+                    sListeners.remove(i);
                     // disable all sensors for this listener
                     for (Sensor sensor : l.getSensors()) {
-                        String name = sensor.getName();
-                        int handle = sensor.getHandle();
-                        sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
+                        disableSensorLocked(sensor);
                     }
-                    sListeners.remove(i);
                     break;
                 }
             }
diff --git a/core/java/android/net/DownloadManager.java b/core/java/android/net/DownloadManager.java
index e8237c9..5320da3 100644
--- a/core/java/android/net/DownloadManager.java
+++ b/core/java/android/net/DownloadManager.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.content.ContentResolver;
+import android.content.ContentUris;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.database.CursorWrapper;
@@ -536,12 +537,12 @@
          * @param projection the projection to pass to ContentResolver.query()
          * @return the Cursor returned by ContentResolver.query()
          */
-        Cursor runQuery(ContentResolver resolver, String[] projection) {
-            Uri uri = Downloads.CONTENT_URI;
+        Cursor runQuery(ContentResolver resolver, String[] projection, Uri baseUri) {
+            Uri uri = baseUri;
             List<String> selectionParts = new ArrayList<String>();
 
             if (mId != null) {
-                uri = Uri.withAppendedPath(uri, mId.toString());
+                uri = ContentUris.withAppendedId(uri, mId);
             }
 
             if (mStatusFlags != null) {
@@ -597,6 +598,7 @@
 
     private ContentResolver mResolver;
     private String mPackageName;
+    private Uri mBaseUri = Downloads.Impl.CONTENT_URI;
 
     /**
      * @hide
@@ -607,6 +609,19 @@
     }
 
     /**
+     * Makes this object access the download provider through /all_downloads URIs rather than
+     * /my_downloads URIs, for clients that have permission to do so.
+     * @hide
+     */
+    public void setAccessAllDownloads(boolean accessAllDownloads) {
+        if (accessAllDownloads) {
+            mBaseUri = Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI;
+        } else {
+            mBaseUri = Downloads.Impl.CONTENT_URI;
+        }
+    }
+
+    /**
      * Enqueue a new download.  The download will start automatically once the download manager is
      * ready to execute it and connectivity is available.
      *
@@ -642,11 +657,11 @@
      * COLUMN_* constants.
      */
     public Cursor query(Query query) {
-        Cursor underlyingCursor = query.runQuery(mResolver, UNDERLYING_COLUMNS);
+        Cursor underlyingCursor = query.runQuery(mResolver, UNDERLYING_COLUMNS, mBaseUri);
         if (underlyingCursor == null) {
             return null;
         }
-        return new CursorTranslator(underlyingCursor);
+        return new CursorTranslator(underlyingCursor, mBaseUri);
     }
 
     /**
@@ -690,9 +705,8 @@
     /**
      * Get the DownloadProvider URI for the download with the given ID.
      */
-    private Uri getDownloadUri(long id) {
-        Uri downloadUri = Uri.withAppendedPath(Downloads.CONTENT_URI, Long.toString(id));
-        return downloadUri;
+    Uri getDownloadUri(long id) {
+        return ContentUris.withAppendedId(mBaseUri, id);
     }
 
     /**
@@ -702,8 +716,11 @@
      * underlying data.
      */
     private static class CursorTranslator extends CursorWrapper {
-        public CursorTranslator(Cursor cursor) {
+        private Uri mBaseUri;
+
+        public CursorTranslator(Cursor cursor, Uri baseUri) {
             super(cursor);
+            mBaseUri = baseUri;
         }
 
         @Override
@@ -799,11 +816,24 @@
             }
 
             assert column.equals(COLUMN_LOCAL_URI);
-            String localUri = getUnderlyingString(Downloads._DATA);
+            return getLocalUri();
+        }
+
+        private String getLocalUri() {
+            String localUri = getUnderlyingString(Downloads.Impl._DATA);
             if (localUri == null) {
                 return null;
             }
-            return Uri.fromFile(new File(localUri)).toString();
+
+            long destinationType = getUnderlyingLong(Downloads.Impl.COLUMN_DESTINATION);
+            if (destinationType == Downloads.Impl.DESTINATION_FILE_URI) {
+                // return file URI for external download
+                return Uri.fromFile(new File(localUri)).toString();
+            }
+
+            // return content URI for cache download
+            long downloadId = getUnderlyingLong(Downloads.Impl._ID);
+            return ContentUris.withAppendedId(mBaseUri, downloadId).toString();
         }
 
         private long translateLong(String column) {
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 603e598..74c7372 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -60,7 +60,7 @@
      * @hide
      */
     public static final Uri CONTENT_URI =
-        Uri.parse("content://downloads/download");
+        Uri.parse("content://downloads/my_downloads");
 
     /**
      * Broadcast Action: this is sent by the download manager to the app
@@ -637,10 +637,17 @@
                 "android.permission.DOWNLOAD_WITHOUT_NOTIFICATION";
 
         /**
-         * The content:// URI for the data table in the provider
+         * The content:// URI to access downloads owned by the caller's UID.
          */
         public static final Uri CONTENT_URI =
-            Uri.parse("content://downloads/download");
+                Uri.parse("content://downloads/my_downloads");
+
+        /**
+         * The content URI for accessing all downloads across all UIDs (requires the
+         * ACCESS_ALL_DOWNLOADS permission).
+         */
+        public static final Uri ALL_DOWNLOADS_CONTENT_URI =
+                Uri.parse("content://downloads/all_downloads");
 
         /**
          * Broadcast Action: this is sent by the download manager to the app
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 7468579..dd04975 100755
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -28,8 +28,7 @@
  * keyboard may compose the capabilities of a standard keyboard together with a track pad mouse
  * or other pointing device.
  * </p><p>
- * Some input devices present multiple distinguishable sources of input.  For example, a
- * game pad may have two analog joysticks, a directional pad and a full complement of buttons.
+ * Some input devices present multiple distinguishable sources of input.
  * Applications can query the framework about the characteristics of each distinct source.
  * </p><p>
  * As a further wrinkle, different kinds of input sources uses different coordinate systems
@@ -55,7 +54,7 @@
     
     /**
      * The input source has buttons or keys.
-     * Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_GAMEPAD}, {@link #SOURCE_DPAD}.
+     * Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_DPAD}.
      * 
      * A {@link KeyEvent} should be interpreted as a button or key press.
      * 
@@ -101,18 +100,6 @@
     public static final int SOURCE_CLASS_POSITION = 0x00000008;
     
     /**
-     * The input source is a joystick.
-     * 
-     * A {@link KeyEvent} should be interpreted as a joystick button press.
-     * 
-     * A {@link MotionEvent} should be interpreted in absolute coordinates as a joystick
-     * position in normalized device-specific units nominally between -1.0 and 1.0.
-     * 
-     * Use {@link #getMotionRange} to query the range and precision of motion.
-     */
-    public static final int SOURCE_CLASS_JOYSTICK = 0x00000010;
-    
-    /**
      * The input source is unknown.
      */
     public static final int SOURCE_UNKNOWN = 0x00000000;
@@ -132,13 +119,6 @@
     public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON;
     
     /**
-     * The input source is a gamepad.
-     * 
-     * @see #SOURCE_CLASS_BUTTON
-     */
-    public static final int SOURCE_GAMEPAD = 0x00000400 | SOURCE_CLASS_BUTTON;
-    
-    /**
      * The input source is a touch screen pointing device.
      * 
      * @see #SOURCE_CLASS_POINTER
@@ -168,20 +148,6 @@
      * @see #SOURCE_CLASS_POSITION
      */
     public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION;
-
-    /**
-     * The input source is a joystick mounted on the left or is a standalone joystick.
-     * 
-     * @see #SOURCE_CLASS_JOYSTICK
-     */
-    public static final int SOURCE_JOYSTICK_LEFT = 0x01000000 | SOURCE_CLASS_JOYSTICK;
-    
-    /**
-     * The input source is a joystick mounted on the right.
-     * 
-     * @see #SOURCE_CLASS_JOYSTICK
-     */
-    public static final int SOURCE_JOYSTICK_RIGHT = 0x02000000 | SOURCE_CLASS_JOYSTICK;
     
     /**
      * A special input source constant that is used when filtering input devices
@@ -411,7 +377,7 @@
         /**
          * Gets the extent of the center flat position with respect to this coordinate.
          * For example, a flat value of 8 means that the center position is between -8 and +8.
-         * This value is mainly useful for calibrating joysticks.
+         * This value is mainly useful for calibrating self-centering devices.
          * @return The extent of the center flat position.
          */
         public float getFlat() {
@@ -506,13 +472,10 @@
         description.append("  Sources:");
         appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
         appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
-        appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
         appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen");
         appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
         appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
         appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
-        appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK_LEFT, "joystick_left");
-        appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK_RIGHT, "joystick_right");
         description.append("\n");
         
         appendRangeDescriptionIfApplicable(description, MOTION_RANGE_X, "x");
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index ed10e41..9e7eedf 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -24,120 +24,305 @@
 import android.view.KeyCharacterMap.KeyData;
 
 /**
- * Contains constants for key events.
+ * Object used to report key and button events.
+ * <p>
+ * Each key press is described by a sequence of key events.  A key press
+ * starts with a key event with {@link #ACTION_DOWN}.  If the key is held
+ * sufficiently long that it repeats, then the initial down is followed
+ * additional key events with {@link #ACTION_DOWN} and a non-zero value for
+ * {@link #getRepeatCount()}.  The last key event is a {@link #ACTION_UP}
+ * for the key up.  If the key press is canceled, the key up event will have the
+ * {@link #FLAG_CANCELED} flag set.
+ * </p><p>
+ * Key events are generally accompanied by a key code ({@link #getKeyCode()}),
+ * scan code ({@link #getScanCode()}) and meta state ({@link #getMetaState()}).
+ * Key code constants are defined in this class.  Scan code constants are raw
+ * device-specific codes obtained from the OS and so are not generally meaningful
+ * to applications unless interpreted using the {@link KeyCharacterMap}.
+ * Meta states describe the pressed state of key modifiers
+ * such as {@link #META_SHIFT_ON} or {@link #META_ALT_ON}.
+ * </p><p>
+ * When interacting with an IME, the framework may deliver key events
+ * with the special action {@link #ACTION_MULTIPLE} that either specifies
+ * that single repeated key code or a sequence of characters to insert.
+ * </p><p>
+ * In general, the framework makes no guarantees that the key events delivered
+ * to a view constitute a complete key press.  In particular, there is no
+ * guarantee that a view will always receive a key event with {@link #ACTION_UP}
+ * for each {@link #ACTION_DOWN} that was delivered.
+ * </p><p>
+ * Refer to {@link InputDevice} for more information about how different kinds of
+ * input devices and sources represent keys and buttons.
+ * </p>
  */
 public class KeyEvent extends InputEvent implements Parcelable {
-    // key codes
+    /** Key code constant: Unknown key code. */
     public static final int KEYCODE_UNKNOWN         = 0;
+    /** Key code constant: Soft Left key.
+     * Usually situated below the display on phones and used as a multi-function
+     * feature key for selecting a software defined function shown on the bottom left
+     * of the display. */
     public static final int KEYCODE_SOFT_LEFT       = 1;
+    /** Key code constant: Soft Right key.
+     * Usually situated below the display on phones and used as a multi-function
+     * feature key for selecting a software defined function shown on the bottom right
+     * of the display. */
     public static final int KEYCODE_SOFT_RIGHT      = 2;
+    /** Key code constant: Home key.
+     * This key is handled by the framework and is never delivered to applications. */
     public static final int KEYCODE_HOME            = 3;
+    /** Key code constant: Back key. */
     public static final int KEYCODE_BACK            = 4;
+    /** Key code constant: Call key. */
     public static final int KEYCODE_CALL            = 5;
+    /** Key code constant: End Call key. */
     public static final int KEYCODE_ENDCALL         = 6;
+    /** Key code constant: '0' key. */
     public static final int KEYCODE_0               = 7;
+    /** Key code constant: '1' key. */
     public static final int KEYCODE_1               = 8;
+    /** Key code constant: '2' key. */
     public static final int KEYCODE_2               = 9;
+    /** Key code constant: '3' key. */
     public static final int KEYCODE_3               = 10;
+    /** Key code constant: '4' key. */
     public static final int KEYCODE_4               = 11;
+    /** Key code constant: '5' key. */
     public static final int KEYCODE_5               = 12;
+    /** Key code constant: '6' key. */
     public static final int KEYCODE_6               = 13;
+    /** Key code constant: '7' key. */
     public static final int KEYCODE_7               = 14;
+    /** Key code constant: '8' key. */
     public static final int KEYCODE_8               = 15;
+    /** Key code constant: '9' key. */
     public static final int KEYCODE_9               = 16;
+    /** Key code constant: '*' key. */
     public static final int KEYCODE_STAR            = 17;
+    /** Key code constant: '#' key. */
     public static final int KEYCODE_POUND           = 18;
+    /** Key code constant: Directional Pad Up key.
+     * May also be synthesized from trackball motions. */
     public static final int KEYCODE_DPAD_UP         = 19;
+    /** Key code constant: Directional Pad Down key.
+     * May also be synthesized from trackball motions. */
     public static final int KEYCODE_DPAD_DOWN       = 20;
+    /** Key code constant: Directional Pad Left key.
+     * May also be synthesized from trackball motions. */
     public static final int KEYCODE_DPAD_LEFT       = 21;
+    /** Key code constant: Directional Pad Right key.
+     * May also be synthesized from trackball motions. */
     public static final int KEYCODE_DPAD_RIGHT      = 22;
+    /** Key code constant: Directional Pad Center key.
+     * May also be synthesized from trackball motions. */
     public static final int KEYCODE_DPAD_CENTER     = 23;
+    /** Key code constant: Volume Up key. */
     public static final int KEYCODE_VOLUME_UP       = 24;
+    /** Key code constant: Volume Down key. */
     public static final int KEYCODE_VOLUME_DOWN     = 25;
+    /** Key code constant: Power key. */
     public static final int KEYCODE_POWER           = 26;
+    /** Key code constant: Camera key.
+     * Used to launch a camera application or take pictures. */
     public static final int KEYCODE_CAMERA          = 27;
+    /** Key code constant: Clear key. */
     public static final int KEYCODE_CLEAR           = 28;
+    /** Key code constant: 'A' key. */
     public static final int KEYCODE_A               = 29;
+    /** Key code constant: 'B' key. */
     public static final int KEYCODE_B               = 30;
+    /** Key code constant: 'C' key. */
     public static final int KEYCODE_C               = 31;
+    /** Key code constant: 'D' key. */
     public static final int KEYCODE_D               = 32;
+    /** Key code constant: 'E' key. */
     public static final int KEYCODE_E               = 33;
+    /** Key code constant: 'F' key. */
     public static final int KEYCODE_F               = 34;
+    /** Key code constant: 'G' key. */
     public static final int KEYCODE_G               = 35;
+    /** Key code constant: 'H' key. */
     public static final int KEYCODE_H               = 36;
+    /** Key code constant: 'I' key. */
     public static final int KEYCODE_I               = 37;
+    /** Key code constant: 'J' key. */
     public static final int KEYCODE_J               = 38;
+    /** Key code constant: 'K' key. */
     public static final int KEYCODE_K               = 39;
+    /** Key code constant: 'L' key. */
     public static final int KEYCODE_L               = 40;
+    /** Key code constant: 'M' key. */
     public static final int KEYCODE_M               = 41;
+    /** Key code constant: 'N' key. */
     public static final int KEYCODE_N               = 42;
+    /** Key code constant: 'O' key. */
     public static final int KEYCODE_O               = 43;
+    /** Key code constant: 'P' key. */
     public static final int KEYCODE_P               = 44;
+    /** Key code constant: 'Q' key. */
     public static final int KEYCODE_Q               = 45;
+    /** Key code constant: 'R' key. */
     public static final int KEYCODE_R               = 46;
+    /** Key code constant: 'S' key. */
     public static final int KEYCODE_S               = 47;
+    /** Key code constant: 'T' key. */
     public static final int KEYCODE_T               = 48;
+    /** Key code constant: 'U' key. */
     public static final int KEYCODE_U               = 49;
+    /** Key code constant: 'V' key. */
     public static final int KEYCODE_V               = 50;
+    /** Key code constant: 'W' key. */
     public static final int KEYCODE_W               = 51;
+    /** Key code constant: 'X' key. */
     public static final int KEYCODE_X               = 52;
+    /** Key code constant: 'Y' key. */
     public static final int KEYCODE_Y               = 53;
+    /** Key code constant: 'Z' key. */
     public static final int KEYCODE_Z               = 54;
+    /** Key code constant: ',' key. */
     public static final int KEYCODE_COMMA           = 55;
+    /** Key code constant: '.' key. */
     public static final int KEYCODE_PERIOD          = 56;
+    /** Key code constant: Left Alt modifier key. */
     public static final int KEYCODE_ALT_LEFT        = 57;
+    /** Key code constant: Right Alt modifier key. */
     public static final int KEYCODE_ALT_RIGHT       = 58;
+    /** Key code constant: Left Shift modifier key. */
     public static final int KEYCODE_SHIFT_LEFT      = 59;
+    /** Key code constant: Right Shift modifier key. */
     public static final int KEYCODE_SHIFT_RIGHT     = 60;
+    /** Key code constant: Tab key. */
     public static final int KEYCODE_TAB             = 61;
+    /** Key code constant: Space key. */
     public static final int KEYCODE_SPACE           = 62;
+    /** Key code constant: Symbol modifier key. */
     public static final int KEYCODE_SYM             = 63;
+    /** Key code constant: Explorer special function key.
+     * Used to launch a browser application. */
     public static final int KEYCODE_EXPLORER        = 64;
+    /** Key code constant: Envelope special function key.
+     * Used to launch a mail application. */
     public static final int KEYCODE_ENVELOPE        = 65;
+    /** Key code constant: Enter key. */
     public static final int KEYCODE_ENTER           = 66;
+    /** Key code constant: Delete key. */
     public static final int KEYCODE_DEL             = 67;
+    /** Key code constant: '`' (backtick) key. */
     public static final int KEYCODE_GRAVE           = 68;
+    /** Key code constant: '-'. */
     public static final int KEYCODE_MINUS           = 69;
+    /** Key code constant: '=' key. */
     public static final int KEYCODE_EQUALS          = 70;
+    /** Key code constant: '[' key. */
     public static final int KEYCODE_LEFT_BRACKET    = 71;
+    /** Key code constant: ']' key. */
     public static final int KEYCODE_RIGHT_BRACKET   = 72;
+    /** Key code constant: '\' key. */
     public static final int KEYCODE_BACKSLASH       = 73;
+    /** Key code constant: ';' key. */
     public static final int KEYCODE_SEMICOLON       = 74;
+    /** Key code constant: ''' (apostrophe) key. */
     public static final int KEYCODE_APOSTROPHE      = 75;
+    /** Key code constant: '/' key. */
     public static final int KEYCODE_SLASH           = 76;
+    /** Key code constant: '@' key. */
     public static final int KEYCODE_AT              = 77;
+    /** Key code constant: Number Lock modifier key. */
     public static final int KEYCODE_NUM             = 78;
+    /** Key code constant: Headset Hook key.
+     * Used to hang up calls and stop media. */
     public static final int KEYCODE_HEADSETHOOK     = 79;
+    /** Key code constant: Camera Focus key.
+     * Used to focus the camera. */
     public static final int KEYCODE_FOCUS           = 80;   // *Camera* focus
+    /** Key code constant: '+' key. */
     public static final int KEYCODE_PLUS            = 81;
+    /** Key code constant: Menu key. */
     public static final int KEYCODE_MENU            = 82;
+    /** Key code constant: Notification key. */
     public static final int KEYCODE_NOTIFICATION    = 83;
+    /** Key code constant: Search key. */
     public static final int KEYCODE_SEARCH          = 84;
+    /** Key code constant: Play/Pause media key. */
     public static final int KEYCODE_MEDIA_PLAY_PAUSE= 85;
+    /** Key code constant: Stop media key. */
     public static final int KEYCODE_MEDIA_STOP      = 86;
+    /** Key code constant: Play Next media key. */
     public static final int KEYCODE_MEDIA_NEXT      = 87;
+    /** Key code constant: Play Previous media key. */
     public static final int KEYCODE_MEDIA_PREVIOUS  = 88;
+    /** Key code constant: Rewind media key. */
     public static final int KEYCODE_MEDIA_REWIND    = 89;
+    /** Key code constant: Fast Forward media key. */
     public static final int KEYCODE_MEDIA_FAST_FORWARD = 90;
+    /** Key code constant: Mute key. */
     public static final int KEYCODE_MUTE            = 91;
+    /** Key code constant: Page Up key. */
     public static final int KEYCODE_PAGE_UP         = 92;
+    /** Key code constant: Page Down key. */
     public static final int KEYCODE_PAGE_DOWN       = 93;
+    /** Key code constant: Picture Symbols modifier key.
+     * Used to switch symbol sets (Emoji, Kao-moji). */
     public static final int KEYCODE_PICTSYMBOLS     = 94;   // switch symbol-sets (Emoji,Kao-moji)
+    /** Key code constant: Switch Charset modifier key.
+     * Used to switch character sets (Kanji, Katakana). */
     public static final int KEYCODE_SWITCH_CHARSET  = 95;   // switch char-sets (Kanji,Katakana)
+    /** Key code constant: A Button key.
+     * On a game controller, the A button should be either the button labeled A
+     * or the first button on the upper row of controller buttons. */
     public static final int KEYCODE_BUTTON_A        = 96;
+    /** Key code constant: B Button key.
+     * On a game controller, the B button should be either the button labeled B
+     * or the second button on the upper row of controller buttons. */
     public static final int KEYCODE_BUTTON_B        = 97;
+    /** Key code constant: C Button key.
+     * On a game controller, the C button should be either the button labeled C
+     * or the third button on the upper row of controller buttons. */
     public static final int KEYCODE_BUTTON_C        = 98;
+    /** Key code constant: X Button key.
+     * On a game controller, the X button should be either the button labeled X
+     * or the first button on the lower row of controller buttons. */
     public static final int KEYCODE_BUTTON_X        = 99;
+    /** Key code constant: Y Button key.
+     * On a game controller, the Y button should be either the button labeled Y
+     * or the second button on the lower row of controller buttons. */
     public static final int KEYCODE_BUTTON_Y        = 100;
+    /** Key code constant: Z Button key.
+     * On a game controller, the Z button should be either the button labeled Z
+     * or the third button on the lower row of controller buttons. */
     public static final int KEYCODE_BUTTON_Z        = 101;
+    /** Key code constant: L1 Button key.
+     * On a game controller, the L1 button should be either the button labeled L1 (or L)
+     * or the top left trigger button. */
     public static final int KEYCODE_BUTTON_L1       = 102;
+    /** Key code constant: R1 Button key.
+     * On a game controller, the R1 button should be either the button labeled R1 (or R)
+     * or the top right trigger button. */
     public static final int KEYCODE_BUTTON_R1       = 103;
+    /** Key code constant: L2 Button key.
+     * On a game controller, the L2 button should be either the button labeled L2
+     * or the bottom left trigger button. */
     public static final int KEYCODE_BUTTON_L2       = 104;
+    /** Key code constant: R2 Button key.
+     * On a game controller, the R2 button should be either the button labeled R2
+     * or the bottom right trigger button. */
     public static final int KEYCODE_BUTTON_R2       = 105;
+    /** Key code constant: Left Thumb Button key.
+     * On a game controller, the left thumb button indicates that the left (or only)
+     * joystick is pressed. */
     public static final int KEYCODE_BUTTON_THUMBL   = 106;
+    /** Key code constant: Right Thumb Button key.
+     * On a game controller, the right thumb button indicates that the right
+     * joystick is pressed. */
     public static final int KEYCODE_BUTTON_THUMBR   = 107;
+    /** Key code constant: Start Button key.
+     * On a game controller, the button labeled Start. */
     public static final int KEYCODE_BUTTON_START    = 108;
+    /** Key code constant: Select Button key.
+     * On a game controller, the button labeled Select. */
     public static final int KEYCODE_BUTTON_SELECT   = 109;
+    /** Key code constant: Mode Button key.
+     * On a game controller, the button labeled Mode. */
     public static final int KEYCODE_BUTTON_MODE     = 110;
 
     // NOTE: If you add a new keycode here you must also add it to:
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 78b9b5d..6705596 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -24,9 +24,71 @@
  * Object used to report movement (mouse, pen, finger, trackball) events.  This
  * class may hold either absolute or relative movements, depending on what
  * it is being used for.
- * 
- * Refer to {@link InputDevice} for information about how different kinds of
+ * <p>
+ * On pointing devices such as touch screens, pointer coordinates specify absolute
+ * positions such as view X/Y coordinates.  Each complete gesture is represented
+ * by a sequence of motion events with actions that describe pointer state transitions
+ * and movements.  A gesture starts with a motion event with {@link #ACTION_DOWN}
+ * that provides the location of the first pointer down.  As each additional
+ * pointer that goes down or up, the framework will generate a motion event with
+ * {@link #ACTION_POINTER_DOWN} or {@link #ACTION_POINTER_UP} accordingly.
+ * Pointer movements are described by motion events with {@link #ACTION_MOVE}.
+ * Finally, a gesture end either when the final pointer goes up as represented
+ * by a motion event with {@link #ACTION_UP} or when gesture is canceled
+ * with {@link #ACTION_CANCEL}.
+ * </p><p>
+ * On trackballs, the pointer coordinates specify relative movements as X/Y deltas.
+ * A trackball gesture consists of a sequence of movements described by motion
+ * events with {@link #ACTION_MOVE} interspersed with occasional {@link #ACTION_DOWN}
+ * or {@link #ACTION_UP} motion events when the trackball button is pressed or released.
+ * </p><p>
+ * Motion events always report movements for all pointers at once.  The number
+ * of pointers only ever changes by one as individual pointers go up and down,
+ * except when the gesture is canceled.
+ * </p><p>
+ * The order in which individual pointers appear within a motion event can change
+ * from one event to the next. Use the {@link #getPointerId(int)} method to obtain a
+ * pointer id to track pointers across motion events in a gesture.  Then for
+ * successive motion events, use the {@link #findPointerIndex(int)} method to obtain
+ * the pointer index for a given pointer id in that motion event.
+ * </p><p>
+ * For efficiency, motion events with {@link #ACTION_MOVE} may batch together
+ * multiple movement samples within a single object.  The most current
+ * pointer coordinates are available using {@link #getX(int)} and {@link #getY(int)}.
+ * Earlier coordinates within the batch are accessed using {@link #getHistoricalX(int, int)}
+ * and {@link #getHistoricalY(int, int)}.  The coordinates are "historical" only
+ * insofar as they are older than the current coordinates in the batch; however,
+ * they are still distinct from any other coordinates reported in prior motion events.
+ * To process all coordinates in the batch in time order, first consume the historical
+ * coordinates then consume the current coordinates.
+ * </p><p>
+ * Example: Consuming all samples for all pointers in a motion event in time order.
+ * </p><p><pre><code>
+ * void printSamples(MotionEvent ev) {
+ *     final int historySize = ev.getHistorySize();
+ *     final int pointerCount = ev.getPointerCount();
+ *     for (int h = 0; h &lt; historySize; h++) {
+ *         System.out.printf("At time %d:", ev.getHistoricalEventTime(h));
+ *         for (int p = 0; p &lt; pointerCount; p++) {
+ *             System.out.printf("  pointer %d: (%f,%f)",
+ *                 ev.getPointerId(p), ev.getHistoricalX(p, h), ev.getHistoricalY(p, h));
+ *         }
+ *     }
+ *     System.out.printf("At time %d:", ev.getEventTime());
+ *     for (int p = 0; p &lt; pointerCount; p++) {
+ *         System.out.printf("  pointer %d: (%f,%f)",
+ *             ev.getPointerId(p), ev.getX(p), ev.getY(p));
+ *     }
+ * }
+ * </code></pre></p><p>
+ * In general, the framework makes no guarantees that the motion events delivered
+ * to a view constitute a complete gesture.  In particular, there is no
+ * guarantee that a view will always receive a motion event with {@link #ACTION_UP}
+ * for each {@link #ACTION_DOWN} that was delivered.
+ * </p><p>
+ * Refer to {@link InputDevice} for more information about how different kinds of
  * input devices and sources represent pointer coordinates.
+ * </p>
  */
 public final class MotionEvent extends InputEvent implements Parcelable {
     private static final long MS_PER_NS = 1000000;
diff --git a/core/java/com/android/internal/util/HierarchicalStateMachine.java b/core/java/com/android/internal/util/HierarchicalStateMachine.java
index c599d68..f789301 100644
--- a/core/java/com/android/internal/util/HierarchicalStateMachine.java
+++ b/core/java/com/android/internal/util/HierarchicalStateMachine.java
@@ -137,7 +137,7 @@
     }
 
     class State1 extends HierarchicalState {
-        @Override public boolean processMessage(Message message) {
+        &#64;Override public boolean processMessage(Message message) {
             Log.d(TAG, "Hello World");
             return HANDLED;
         }
@@ -257,10 +257,10 @@
     }
 
     class P1 extends HierarchicalState {
-        @Override public void enter() {
+        &#64;Override public void enter() {
             Log.d(TAG, "mP1.enter");
         }
-        @Override public boolean processMessage(Message message) {
+        &#64;Override public boolean processMessage(Message message) {
             boolean retVal;
             Log.d(TAG, "mP1.processMessage what=" + message.what);
             switch(message.what) {
@@ -278,16 +278,16 @@
             }
             return retVal;
         }
-        @Override public void exit() {
+        &#64;Override public void exit() {
             Log.d(TAG, "mP1.exit");
         }
     }
 
     class S1 extends HierarchicalState {
-        @Override public void enter() {
+        &#64;Override public void enter() {
             Log.d(TAG, "mS1.enter");
         }
-        @Override public boolean processMessage(Message message) {
+        &#64;Override public boolean processMessage(Message message) {
             Log.d(TAG, "S1.processMessage what=" + message.what);
             if (message.what == CMD_1) {
                 // Transition to ourself to show that enter/exit is called
@@ -298,16 +298,16 @@
                 return NOT_HANDLED;
             }
         }
-        @Override public void exit() {
+        &#64;Override public void exit() {
             Log.d(TAG, "mS1.exit");
         }
     }
 
     class S2 extends HierarchicalState {
-        @Override public void enter() {
+        &#64;Override public void enter() {
             Log.d(TAG, "mS2.enter");
         }
-        @Override public boolean processMessage(Message message) {
+        &#64;Override public boolean processMessage(Message message) {
             boolean retVal;
             Log.d(TAG, "mS2.processMessage what=" + message.what);
             switch(message.what) {
@@ -326,17 +326,17 @@
             }
             return retVal;
         }
-        @Override public void exit() {
+        &#64;Override public void exit() {
             Log.d(TAG, "mS2.exit");
         }
     }
 
     class P2 extends HierarchicalState {
-        @Override public void enter() {
+        &#64;Override public void enter() {
             Log.d(TAG, "mP2.enter");
             sendMessage(obtainMessage(CMD_5));
         }
-        @Override public boolean processMessage(Message message) {
+        &#64;Override public boolean processMessage(Message message) {
             Log.d(TAG, "P2.processMessage what=" + message.what);
             switch(message.what) {
             case(CMD_3):
@@ -349,12 +349,12 @@
             }
             return HANDLED;
         }
-        @Override public void exit() {
+        &#64;Override public void exit() {
             Log.d(TAG, "mP2.exit");
         }
     }
 
-    @Override
+    &#64;Override
     void halting() {
         Log.d(TAG, "halting");
         synchronized (this) {
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 2751a82..17ab46c 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -703,42 +703,6 @@
         }
     }
 
-    /* enable poisoning of memory of freed objects */
-    property_get("dalvik.vm.gc.overwritefree", propBuf, "false");
-    if (strcmp(propBuf, "true") == 0) {
-        opt.optionString = "-Xgc:overwritefree";
-        mOptions.add(opt);
-    } else if (strcmp(propBuf, "false") != 0) {
-        LOGW("dalvik.vm.gc.overwritefree should be 'true' or 'false'");
-    }
-
-    /* enable heap verification before each gc */
-    property_get("dalvik.vm.gc.preverify", propBuf, "false");
-    if (strcmp(propBuf, "true") == 0) {
-        opt.optionString = "-Xgc:preverify";
-        mOptions.add(opt);
-    } else if (strcmp(propBuf, "false") != 0) {
-        LOGW("dalvik.vm.gc.preverify should be 'true' or 'false'");
-    }
-
-    /* enable heap verification after each gc */
-    property_get("dalvik.vm.gc.postverify", propBuf, "false");
-    if (strcmp(propBuf, "true") == 0) {
-        opt.optionString = "-Xgc:postverify";
-        mOptions.add(opt);
-    } else if (strcmp(propBuf, "false") != 0) {
-        LOGW("dalvik.vm.gc.postverify should be 'true' or 'false'");
-    }
-
-    /* enable card table verification for partial gc */
-    property_get("dalvik.vm.gc.verifycardtable", propBuf, "false");
-    if (strcmp(propBuf, "true") == 0) {
-        opt.optionString = "-Xgc:verifycardtable";
-        mOptions.add(opt);
-    } else if (strcmp(propBuf, "false") != 0) {
-        LOGW("dalvik.vm.gc.verifycardtable should be 'true' or 'false'");
-    }
-
     /* enable debugging; set suspend=y to pause during VM init */
 #ifdef HAVE_ANDROID_OS
     /* use android ADB transport */
diff --git a/docs/html/guide/topics/resources/localization.jd b/docs/html/guide/topics/resources/localization.jd
index 3d630c9..36e12f6 100755
--- a/docs/html/guide/topics/resources/localization.jd
+++ b/docs/html/guide/topics/resources/localization.jd
@@ -433,12 +433,12 @@
 href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a>.</p>

 <h4>Creating and using a custom locale</h4>

 

-<p>A &quot;custom&quot; locale is a language/region combination that the

-Android system image does not explicitly support. (For a list of supported 

-locales, see the <a href="{@docRoot}sdk/android-{@sdkCurrentVersion}.html">Android

-Version Notes</a>.) You can test how your application will run in a custom

-locale by creating a custom locale in the emulator. There are two ways to do

-this:</p>

+<p>A &quot;custom&quot; locale is a language/region combination that the Android

+system image does not explicitly support. (For a list of supported locales in

+Android platforms see the Version Notes in the <a

+href="{@docRoot}sdk/index.html">SDK</a> tab). You can test

+how your application will run in a custom locale by creating a custom locale in

+the emulator. There are two ways to do this:</p>

 

 <ul>

   <li>Use the Custom Locale application, which is accessible from the

diff --git a/docs/html/sdk/adt_download.jd b/docs/html/sdk/adt_download.jd
index 126c052..5e642d7 100644
--- a/docs/html/sdk/adt_download.jd
+++ b/docs/html/sdk/adt_download.jd
@@ -24,8 +24,8 @@
   <tr>
      <td>0.9.8</td>
      <td><a href="http://dl-ssl.google.com/android/ADT-0.9.8.zip">ADT-0.9.8.zip</a></td>
-     <td><nobr>{@adtZipBytes} bytes</nobr></td>
-     <td>{@adtZipChecksum}</td>
+     <td><nobr>8703591 bytes</nobr></td>
+     <td>22070f8e52924605a3b3abf87c1ba39f</td>
      <td>Requires SDK Tools, Revision 7 <em><nobr>September 2010</nobr></em></td>
   </tr>
   <tr>
diff --git a/docs/html/sdk/android-1.5.jd b/docs/html/sdk/android-1.5.jd
index 0c16b60..9ed798c 100644
--- a/docs/html/sdk/android-1.5.jd
+++ b/docs/html/sdk/android-1.5.jd
@@ -2,8 +2,6 @@
 sdk.platform.version=1.5
 sdk.platform.apiLevel=3
 sdk.platform.majorMinor=major
-sdk.platform.releaseDate=April 2009
-sdk.platform.deployableDate=May 2009
 
 @jd:body
 
@@ -43,7 +41,7 @@
 <em>API Level:</em>&nbsp;<strong>{@sdkPlatformApiLevel}</strong></p>
 
 <p>Android {@sdkPlatformVersion} is a {@sdkPlatformMajorMinor} platform release
-deployable to Android-powered handsets starting in {@sdkPlatformDeployableDate}.
+deployable to Android-powered handsets starting in May 2009.
 The release includes new features for users and developers, as well as changes
 in the Android framework API. </p>
 
diff --git a/docs/html/sdk/android-1.6.jd b/docs/html/sdk/android-1.6.jd
index c4e08ff..a01a5f6 100644
--- a/docs/html/sdk/android-1.6.jd
+++ b/docs/html/sdk/android-1.6.jd
@@ -2,8 +2,6 @@
 sdk.platform.version=1.6
 sdk.platform.apiLevel=4
 sdk.platform.majorMinor=minor
-sdk.platform.releaseDate=December 2009
-sdk.platform.deployableDate=October 2009
 
 @jd:body
 
@@ -43,7 +41,7 @@
 <em>API Level:</em>&nbsp;<strong>{@sdkPlatformApiLevel}</strong></p>
 
 <p>Android {@sdkPlatformVersion} is a {@sdkPlatformMajorMinor} platform release
-deployable to Android-powered handsets since {@sdkPlatformDeployableDate}.
+deployable to Android-powered handsets since October 2009.
 The platform includes new features for users and developers, as well as changes
 in the Android framework API. </p>
 
diff --git a/docs/html/sdk/android-2.0.1.jd b/docs/html/sdk/android-2.0.1.jd
index cacb6bf..0c8afb6 100644
--- a/docs/html/sdk/android-2.0.1.jd
+++ b/docs/html/sdk/android-2.0.1.jd
@@ -2,8 +2,6 @@
 sdk.platform.version=2.0.1
 sdk.platform.apiLevel=6
 sdk.platform.majorMinor=minor
-sdk.platform.releaseDate=December 2009
-sdk.platform.deployableDate=December 2009
 
 @jd:body
 
@@ -44,7 +42,7 @@
 <em>API Level:</em>&nbsp;<strong>{@sdkPlatformApiLevel}</strong></p>
 
 <p>Android {@sdkPlatformVersion} is a {@sdkPlatformMajorMinor} platform release
-deployable to Android-powered handsets starting in {@sdkPlatformDeployableDate}.
+deployable to Android-powered handsets starting in December 2009.
 This release includes minor API
 changes, bug fixes and framework behavioral changes. For information on changes
 and fixes, see the <a href="#api">Framework API</a> section.</p>
diff --git a/docs/html/sdk/android-2.0.jd b/docs/html/sdk/android-2.0.jd
index a430f34..2c31923 100644
--- a/docs/html/sdk/android-2.0.jd
+++ b/docs/html/sdk/android-2.0.jd
@@ -2,8 +2,6 @@
 sdk.platform.version=2.0
 sdk.platform.apiLevel=5
 sdk.platform.majorMinor=major
-sdk.platform.releaseDate=October 2009
-sdk.platform.deployableDate=November 2009
 
 @jd:body
 
@@ -38,7 +36,7 @@
 <em>API Level:</em>&nbsp;<strong>{@sdkPlatformApiLevel}</strong></p>
 
 <p>Android {@sdkPlatformVersion} is a {@sdkPlatformMajorMinor} platform release
-deployable to Android-powered handsets starting in {@sdkPlatformDeployableDate}.
+deployable to Android-powered handsets starting in November 2009.
 The release includes new features for users and developers, as well as changes
 in the Android framework API. </p>
 
diff --git a/docs/html/sdk/android-2.1.jd b/docs/html/sdk/android-2.1.jd
index cd48a72..6eba6f09 100644
--- a/docs/html/sdk/android-2.1.jd
+++ b/docs/html/sdk/android-2.1.jd
@@ -2,7 +2,6 @@
 sdk.platform.version=2.1
 sdk.platform.apiLevel=7
 sdk.platform.majorMinor=minor
-sdk.platform.deployableDate=January 2010
 
 @jd:body
 
@@ -42,7 +41,7 @@
 <em>API Level:</em>&nbsp;<strong>{@sdkPlatformApiLevel}</strong></p>
 
 <p>Android {@sdkPlatformVersion} is a {@sdkPlatformMajorMinor} platform release
-deployable to Android-powered handsets starting in {@sdkPlatformDeployableDate}.
+deployable to Android-powered handsets starting in January 2010.
 This release includes new API
 changes and bug fixes. For information on changes, see the <a href="#api">Framework API</a>
 section.</p>
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index 3d4b6a1..a984d56 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -1,5 +1,9 @@
 page.title=ADT Plugin for Eclipse
 sdk.preview=0
+adt.zip.version=0.9.8
+adt.zip.download=ADT-0.9.8.zip
+adt.zip.bytes=8703591
+adt.zip.checksum=22070f8e52924605a3b3abf87c1ba39f
 
 @jd:body
 
diff --git a/docs/knowntags.txt b/docs/knowntags.txt
new file mode 100644
index 0000000..5bebabb
--- /dev/null
+++ b/docs/knowntags.txt
@@ -0,0 +1,38 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# The grandfathered list.  We should get rid of these if possible.
+#
+@ToBeFixed
+@stable
+@com.intel.drl.spec_ref
+@ar.org.fitc.spec_ref
+
+# Something about CTS?
+@cts
+
+# Auto-generated info about the SDK
+@sdkCurrent
+@sdkCurrentVersion
+@sdkCurrentRelId
+@sdkPlatformVersion
+@sdkPlatformApiLevel
+@sdkPlatformMajorMinor
+@sdkPlatformReleaseDate
+@sdkPlatformDeployableDate
+@adtZipVersion
+@adtZipDownload
+@adtZipBytes
+@adtZipChecksum
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index 25d5afb..d6b09dc 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -111,10 +111,10 @@
     /* The input device is a multi-touch touchscreen. */
     INPUT_DEVICE_CLASS_TOUCHSCREEN_MT= 0x00000010,
 
-    /* The input device is a directional pad. */
+    /* The input device is a directional pad (implies keyboard, has DPAD keys). */
     INPUT_DEVICE_CLASS_DPAD          = 0x00000020,
 
-    /* The input device is a gamepad (implies keyboard). */
+    /* The input device is a gamepad (implies keyboard, has BUTTON keys). */
     INPUT_DEVICE_CLASS_GAMEPAD       = 0x00000040,
 
     /* The input device has switches. */
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index e466ddd..96b4fae 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -851,8 +851,8 @@
 
     // Inbound event processing.
     void drainInboundQueueLocked();
-    void releasePendingEventLocked(bool wasDropped);
-    void releaseInboundEventLocked(EventEntry* entry, bool wasDropped);
+    void releasePendingEventLocked();
+    void releaseInboundEventLocked(EventEntry* entry);
     bool isEventFromReliableSourceLocked(EventEntry* entry);
 
     // Dispatch state.
@@ -886,10 +886,10 @@
             nsecs_t currentTime, ConfigurationChangedEntry* entry);
     bool dispatchKeyLocked(
             nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
-            nsecs_t* nextWakeupTime);
+            bool dropEvent, nsecs_t* nextWakeupTime);
     bool dispatchMotionLocked(
             nsecs_t currentTime, MotionEntry* entry,
-            nsecs_t* nextWakeupTime);
+            bool dropEvent, nsecs_t* nextWakeupTime);
     void dispatchEventToCurrentInputTargetsLocked(
             nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
 
@@ -914,8 +914,8 @@
     bool mInputTargetWaitTimeoutExpired;
 
     // Finding targets for input events.
-    void startFindingTargetsLocked();
-    void finishFindingTargetsLocked(const InputWindow* window);
+    void resetTargetsLocked();
+    void commitTargetsLocked(const InputWindow* window);
     int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
             const InputApplication* application, const InputWindow* window,
             nsecs_t* nextWakeupTime);
diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp
index c3a9f22..f935524 100644
--- a/libs/gui/SensorEventQueue.cpp
+++ b/libs/gui/SensorEventQueue.cpp
@@ -70,9 +70,13 @@
 ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents)
 {
     ssize_t size = mSensorChannel->read(events, numEvents*sizeof(events[0]));
+    LOGE_IF(size<0 && size!=-EAGAIN,
+            "SensorChannel::read error (%s)", strerror(-size));
     if (size >= 0) {
         if (size % sizeof(events[0])) {
             // partial read!!! should never happen.
+            LOGE("SensorEventQueue partial read (event-size=%u, read=%d)",
+                    sizeof(events[0]), int(size));
             return -EINVAL;
         }
         // returns number of events read
@@ -95,8 +99,18 @@
 {
     const int fd = getFd();
     sp<Looper> looper(getLooper());
-    int32_t result = looper->pollOnce(-1);
-    return (result == fd) ? status_t(NO_ERROR) : status_t(-1);
+
+    int32_t result;
+    do {
+        result = looper->pollOnce(-1);
+        if (result == ALOOPER_EVENT_ERROR) {
+            LOGE("SensorChannel::waitForEvent error (errno=%d)", errno);
+            result = -EPIPE; // unknown error, so we make up one
+            break;
+        }
+    } while (result != fd);
+
+    return  (result == fd) ? status_t(NO_ERROR) : result;
 }
 
 status_t SensorEventQueue::wake() const
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 3b3c483..1cf7592 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -122,7 +122,7 @@
         AutoMutex _l(mLock);
 
         resetKeyRepeatLocked();
-        releasePendingEventLocked(true);
+        releasePendingEventLocked();
         drainInboundQueueLocked();
     }
 
@@ -174,7 +174,7 @@
     if (! mDispatchEnabled) {
         if (mPendingEvent || ! mInboundQueue.isEmpty()) {
             LOGI("Dropping pending events because input dispatch is disabled.");
-            releasePendingEventLocked(true);
+            releasePendingEventLocked();
             drainInboundQueueLocked();
         }
         return;
@@ -281,51 +281,50 @@
 
     // Now we have an event to dispatch.
     assert(mPendingEvent != NULL);
-    bool wasDispatched = false;
-    bool wasDropped = false;
+    bool done = false;
     switch (mPendingEvent->type) {
     case EventEntry::TYPE_CONFIGURATION_CHANGED: {
         ConfigurationChangedEntry* typedEntry =
                 static_cast<ConfigurationChangedEntry*>(mPendingEvent);
-        wasDispatched = dispatchConfigurationChangedLocked(currentTime, typedEntry);
+        done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
         break;
     }
 
     case EventEntry::TYPE_KEY: {
         KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
-        if (isAppSwitchPendingLocked()) {
-            if (isAppSwitchKey(typedEntry->keyCode)) {
+        bool appSwitchKey = isAppSwitchKey(typedEntry->keyCode);
+        bool dropEvent = isAppSwitchDue && ! appSwitchKey;
+        done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout, dropEvent,
+                nextWakeupTime);
+        if (done) {
+            if (dropEvent) {
+                LOGI("Dropped key because of pending overdue app switch.");
+            } else if (appSwitchKey) {
                 resetPendingAppSwitchLocked(true);
-            } else if (isAppSwitchDue) {
-                LOGI("Dropping key because of pending overdue app switch.");
-                wasDropped = true;
-                break;
             }
         }
-        wasDispatched = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
-                nextWakeupTime);
         break;
     }
 
     case EventEntry::TYPE_MOTION: {
         MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
-        if (isAppSwitchDue) {
-            LOGI("Dropping motion because of pending overdue app switch.");
-            wasDropped = true;
-            break;
+        bool dropEvent = isAppSwitchDue;
+        done = dispatchMotionLocked(currentTime, typedEntry, dropEvent, nextWakeupTime);
+        if (done) {
+            if (dropEvent) {
+                LOGI("Dropped motion because of pending overdue app switch.");
+            }
         }
-        wasDispatched = dispatchMotionLocked(currentTime, typedEntry, nextWakeupTime);
         break;
     }
 
     default:
         assert(false);
-        wasDropped = true;
         break;
     }
 
-    if (wasDispatched || wasDropped) {
-        releasePendingEventLocked(wasDropped);
+    if (done) {
+        releasePendingEventLocked();
         *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
     }
 }
@@ -403,21 +402,21 @@
 void InputDispatcher::drainInboundQueueLocked() {
     while (! mInboundQueue.isEmpty()) {
         EventEntry* entry = mInboundQueue.dequeueAtHead();
-        releaseInboundEventLocked(entry, true /*wasDropped*/);
+        releaseInboundEventLocked(entry);
     }
 }
 
-void InputDispatcher::releasePendingEventLocked(bool wasDropped) {
+void InputDispatcher::releasePendingEventLocked() {
     if (mPendingEvent) {
-        releaseInboundEventLocked(mPendingEvent, wasDropped);
+        releaseInboundEventLocked(mPendingEvent);
         mPendingEvent = NULL;
     }
 }
 
-void InputDispatcher::releaseInboundEventLocked(EventEntry* entry, bool wasDropped) {
-    if (wasDropped) {
+void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
+    if (entry->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
 #if DEBUG_DISPATCH_CYCLE
-        LOGD("Pending event was dropped.");
+        LOGD("Inbound event was dropped.  Setting injection result to failed.");
 #endif
         setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
     }
@@ -492,7 +491,41 @@
 
 bool InputDispatcher::dispatchKeyLocked(
         nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
-        nsecs_t* nextWakeupTime) {
+        bool dropEvent, nsecs_t* nextWakeupTime) {
+    // Give the policy a chance to intercept the key.
+    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
+        bool trusted;
+        if (! dropEvent && mFocusedWindow) {
+            trusted = checkInjectionPermission(mFocusedWindow,
+                    entry->injectorPid, entry->injectorUid);
+        } else {
+            trusted = isEventFromReliableSourceLocked(entry);
+        }
+        if (trusted) {
+            CommandEntry* commandEntry = postCommandLocked(
+                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
+            if (! dropEvent && mFocusedWindow) {
+                commandEntry->inputChannel = mFocusedWindow->inputChannel;
+            }
+            commandEntry->keyEntry = entry;
+            entry->refCount += 1;
+            return false; // wait for the command to run
+        } else {
+            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
+        }
+    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
+        resetTargetsLocked();
+        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED);
+        return true;
+    }
+
+    // Clean up if dropping the event.
+    if (dropEvent) {
+        resetTargetsLocked();
+        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
+        return true;
+    }
+
     // Preprocessing.
     if (! entry->dispatchInProgress) {
         logOutboundKeyDetailsLocked("dispatchKey - ", entry);
@@ -521,7 +554,7 @@
         }
 
         entry->dispatchInProgress = true;
-        startFindingTargetsLocked(); // resets mCurrentInputTargetsValid
+        resetTargetsLocked();
     }
 
     // Identify targets.
@@ -539,20 +572,7 @@
         }
 
         addMonitoringTargetsLocked();
-        finishFindingTargetsLocked(window);
-    }
-
-    // Give the policy a chance to intercept the key.
-    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
-        CommandEntry* commandEntry = postCommandLocked(
-                & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
-        commandEntry->inputChannel = mCurrentInputChannel;
-        commandEntry->keyEntry = entry;
-        entry->refCount += 1;
-        return false; // wait for the command to run
-    }
-    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
-        return true;
+        commitTargetsLocked(window);
     }
 
     // Dispatch the key.
@@ -576,13 +596,20 @@
 }
 
 bool InputDispatcher::dispatchMotionLocked(
-        nsecs_t currentTime, MotionEntry* entry, nsecs_t* nextWakeupTime) {
+        nsecs_t currentTime, MotionEntry* entry, bool dropEvent, nsecs_t* nextWakeupTime) {
+    // Clean up if dropping the event.
+    if (dropEvent) {
+        resetTargetsLocked();
+        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
+        return true;
+    }
+
     // Preprocessing.
     if (! entry->dispatchInProgress) {
         logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
 
         entry->dispatchInProgress = true;
-        startFindingTargetsLocked(); // resets mCurrentInputTargetsValid
+        resetTargetsLocked();
     }
 
     bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
@@ -610,7 +637,7 @@
         }
 
         addMonitoringTargetsLocked();
-        finishFindingTargetsLocked(window);
+        commitTargetsLocked(window);
     }
 
     // Dispatch the motion.
@@ -705,14 +732,14 @@
     }
 }
 
-void InputDispatcher::startFindingTargetsLocked() {
+void InputDispatcher::resetTargetsLocked() {
     mCurrentInputTargetsValid = false;
     mCurrentInputTargets.clear();
     mCurrentInputChannel.clear();
     mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
 }
 
-void InputDispatcher::finishFindingTargetsLocked(const InputWindow* window) {
+void InputDispatcher::commitTargetsLocked(const InputWindow* window) {
     mCurrentInputWindowType = window->layoutParamsType;
     mCurrentInputChannel = window->inputChannel;
     mCurrentInputTargetsValid = true;
@@ -776,11 +803,16 @@
         // Give up.
         mInputTargetWaitTimeoutExpired = true;
 
+        // Release the touch target.
+        releaseTouchedWindowLocked();
+
         // Input state will not be realistic.  Mark it out of sync.
-        ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
-        if (connectionIndex >= 0) {
-            sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-            connection->inputState.setOutOfSync();
+        if (inputChannel.get()) {
+            ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
+            if (connectionIndex >= 0) {
+                sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
+                connection->inputState.setOutOfSync();
+            }
         }
     }
 }
@@ -2157,9 +2189,8 @@
     { // acquire lock
         AutoMutex _l(mLock);
 
-        sp<InputChannel> oldFocusedWindowChannel = mFocusedWindow
-                ? mFocusedWindow->inputChannel : NULL;
-        int32_t oldFocusedWindowLayer = mFocusedWindow ? mFocusedWindow->layer : -1;
+        // Clear old window pointers but remember their associated channels.
+        mFocusedWindow = NULL;
 
         sp<InputChannel> touchedWindowChannel;
         if (mTouchedWindow) {
@@ -2173,11 +2204,11 @@
             }
             mTouchedWallpaperWindows.clear();
         }
-
-        mFocusedWindow = NULL;
         mWallpaperWindows.clear();
-
         mWindows.clear();
+
+        // Loop over new windows and rebuild the necessary window pointers for
+        // tracking focus and touch.
         mWindows.appendVector(inputWindows);
 
         size_t numWindows = mWindows.size();
@@ -2201,41 +2232,8 @@
                 mTouchedWindow = window;
             }
         }
-
         mTempTouchedWallpaperChannels.clear();
 
-        bool preempt = false;
-        if (mFocusedWindow
-                && mFocusedWindow->inputChannel != oldFocusedWindowChannel
-                && mFocusedWindow->canReceiveKeys) {
-            // If the new input focus is an error window or appears above the current
-            // input focus, drop the current touched window so that we can start
-            // delivering events to the new input focus as soon as possible.
-            if (mFocusedWindow->layoutParamsFlags & InputWindow::FLAG_SYSTEM_ERROR) {
-#if DEBUG_FOCUS
-                LOGD("Preempting: New SYSTEM_ERROR window; resetting state");
-#endif
-                preempt = true;
-            } else if (oldFocusedWindowChannel.get() != NULL
-                    && mFocusedWindow->layer > oldFocusedWindowLayer) {
-#if DEBUG_FOCUS
-                LOGD("Preempting: Transferring focus to new window at higher layer: "
-                        "old win layer=%d, new win layer=%d",
-                        oldFocusedWindowLayer, mFocusedWindow->layer);
-#endif
-                preempt = true;
-            }
-        }
-        if (mTouchedWindow && ! mTouchedWindow->visible) {
-#if DEBUG_FOCUS
-            LOGD("Preempting: Touched window became invisible.");
-#endif
-            preempt = true;
-        }
-        if (preempt) {
-            releaseTouchedWindowLocked();
-        }
-
 #if DEBUG_FOCUS
         logDispatchStateLocked();
 #endif
@@ -2310,7 +2308,17 @@
 void InputDispatcher::logDispatchStateLocked() {
     String8 dump;
     dumpDispatchStateLocked(dump);
-    LOGD("%s", dump.string());
+
+    char* text = dump.lockBuffer(dump.size());
+    char* start = text;
+    while (*start != '\0') {
+        char* end = strchr(start, '\n');
+        if (*end == '\n') {
+            *(end++) = '\0';
+        }
+        LOGD("%s", start);
+        start = end;
+    }
 }
 
 void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
@@ -2324,28 +2332,30 @@
     } else {
         dump.append("  focusedApplication: <null>\n");
     }
-    dump.appendFormat("  focusedWindow: '%s'\n",
-            mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : "<null>");
-    dump.appendFormat("  touchedWindow: '%s', touchDown=%d\n",
-            mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "<null>",
+    dump.appendFormat("  focusedWindow: name='%s'\n",
+            mFocusedWindow != NULL ? mFocusedWindow->name.string() : "<null>");
+    dump.appendFormat("  touchedWindow: name='%s', touchDown=%d\n",
+            mTouchedWindow != NULL ? mTouchedWindow->name.string() : "<null>",
             mTouchDown);
     for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) {
-        dump.appendFormat("  touchedWallpaperWindows[%d]: '%s'\n",
-                i, mTouchedWallpaperWindows[i]->inputChannel->getName().string());
+        dump.appendFormat("  touchedWallpaperWindows[%d]: name='%s'\n",
+                i, mTouchedWallpaperWindows[i]->name.string());
     }
     for (size_t i = 0; i < mWindows.size(); i++) {
-        dump.appendFormat("  windows[%d]: '%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
-                "visible=%s, flags=0x%08x, type=0x%08x, "
+        dump.appendFormat("  windows[%d]: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
+                "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
                 "frame=[%d,%d][%d,%d], "
                 "visibleFrame=[%d,%d][%d,%d], "
                 "touchableArea=[%d,%d][%d,%d], "
                 "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
-                i, mWindows[i].inputChannel->getName().string(),
+                i, mWindows[i].name.string(),
                 toString(mWindows[i].paused),
                 toString(mWindows[i].hasFocus),
                 toString(mWindows[i].hasWallpaper),
                 toString(mWindows[i].visible),
+                toString(mWindows[i].canReceiveKeys),
                 mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType,
+                mWindows[i].layer,
                 mWindows[i].frameLeft, mWindows[i].frameTop,
                 mWindows[i].frameRight, mWindows[i].frameBottom,
                 mWindows[i].visibleFrameLeft, mWindows[i].visibleFrameTop,
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 88084c0..783cbc4 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -325,9 +325,6 @@
     if (classes & INPUT_DEVICE_CLASS_DPAD) {
         keyboardSources |= AINPUT_SOURCE_DPAD;
     }
-    if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
-        keyboardSources |= AINPUT_SOURCE_GAMEPAD;
-    }
 
     if (keyboardSources != 0) {
         device->addMapper(new KeyboardInputMapper(device,
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index 4c402dc..2c6346e 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -131,7 +131,10 @@
 }
 
 status_t InputChannel::sendSignal(char signal) {
-    ssize_t nWrite = ::write(mSendPipeFd, & signal, 1);
+    ssize_t nWrite;
+    do {
+        nWrite = ::write(mSendPipeFd, & signal, 1);
+    } while (nWrite == -1 && errno == EINTR);
 
     if (nWrite == 1) {
 #if DEBUG_CHANNEL_SIGNALS
@@ -147,7 +150,11 @@
 }
 
 status_t InputChannel::receiveSignal(char* outSignal) {
-    ssize_t nRead = ::read(mReceivePipeFd, outSignal, 1);
+    ssize_t nRead;
+    do {
+        nRead = ::read(mReceivePipeFd, outSignal, 1);
+    } while (nRead == -1 && errno == EINTR);
+
     if (nRead == 1) {
 #if DEBUG_CHANNEL_SIGNALS
         LOGD("channel '%s' ~ received signal '%c'", mName.string(), *outSignal);
diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp
index fd287da..4aa50d6 100644
--- a/libs/utils/Looper.cpp
+++ b/libs/utils/Looper.cpp
@@ -162,9 +162,11 @@
     struct epoll_event eventItems[EPOLL_MAX_EVENTS];
     int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
     if (eventCount < 0) {
-        if (errno != EINTR) {
-            LOGW("Poll failed with an unexpected error, errno=%d", errno);
+        if (errno == EINTR) {
+            return ALOOPER_POLL_WAKE;
         }
+
+        LOGW("Poll failed with an unexpected error, errno=%d", errno);
         return ALOOPER_POLL_ERROR;
     }
 
@@ -196,7 +198,7 @@
                     ssize_t nRead;
                     do {
                         nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
-                    } while (nRead == sizeof(buffer));
+                    } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
                 } else {
                     LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
                 }
@@ -272,7 +274,11 @@
     LOGD("%p ~ wake", this);
 #endif
 
-    ssize_t nWrite = write(mWakeWritePipeFd, "W", 1);
+    ssize_t nWrite;
+    do {
+        nWrite = write(mWakeWritePipeFd, "W", 1);
+    } while (nWrite == -1 && errno == EINTR);
+
     if (nWrite != 1) {
         if (errno != EAGAIN) {
             LOGW("Could not write wake signal, errno=%d", errno);
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 90756d0..8f40130 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -145,6 +145,7 @@
                                 void          *pParam,
                                 size_t        *pValueSize,
                                 void          *pValue);
+int Effect_setEnabled(EffectContext *pContext, bool enabled);
 
 /* Effect Library Interface Implementation */
 extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects){
@@ -303,32 +304,34 @@
     }
     LOGV("\tEffectCreate - pBundledContext is %p", pContext->pBundledContext);
 
+    SessionContext *pSessionContext = &GlobalSessionMemory[pContext->pBundledContext->SessionNo];
+
     // Create each Effect
     if (memcmp(uuid, &gBassBoostDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
         // Create Bass Boost
         LOGV("\tEffectCreate - Effect to be created is LVM_BASS_BOOST");
-        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBassInstantiated = LVM_TRUE;
+        pSessionContext->bBassInstantiated = LVM_TRUE;
 
         pContext->itfe       = &gLvmEffectInterface;
         pContext->EffectType = LVM_BASS_BOOST;
     } else if (memcmp(uuid, &gVirtualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
         // Create Virtualizer
         LOGV("\tEffectCreate - Effect to be created is LVM_VIRTUALIZER");
-        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVirtualizerInstantiated=LVM_TRUE;
+        pSessionContext->bVirtualizerInstantiated=LVM_TRUE;
 
         pContext->itfe       = &gLvmEffectInterface;
         pContext->EffectType = LVM_VIRTUALIZER;
     } else if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
         // Create Equalizer
         LOGV("\tEffectCreate - Effect to be created is LVM_EQUALIZER");
-        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bEqualizerInstantiated = LVM_TRUE;
+        pSessionContext->bEqualizerInstantiated = LVM_TRUE;
 
         pContext->itfe       = &gLvmEffectInterface;
         pContext->EffectType = LVM_EQUALIZER;
     } else if (memcmp(uuid, &gVolumeDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
         // Create Volume
         LOGV("\tEffectCreate - Effect to be created is LVM_VOLUME");
-        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVolumeInstantiated = LVM_TRUE;
+        pSessionContext->bVolumeInstantiated = LVM_TRUE;
 
         pContext->itfe       = &gLvmEffectInterface;
         pContext->EffectType = LVM_VOLUME;
@@ -353,29 +356,33 @@
         return -EINVAL;
     }
 
+
+    Effect_setEnabled(pContext, LVM_FALSE);
+
+    SessionContext *pSessionContext = &GlobalSessionMemory[pContext->pBundledContext->SessionNo];
+
     // Clear the instantiated flag for the effect
     if(pContext->EffectType == LVM_BASS_BOOST) {
         LOGV("\tEffectRelease LVM_BASS_BOOST Clearing global intstantiated flag");
-        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBassInstantiated = LVM_FALSE;
+        pSessionContext->bBassInstantiated = LVM_FALSE;
     } else if(pContext->EffectType == LVM_VIRTUALIZER) {
         LOGV("\tEffectRelease LVM_VIRTUALIZER Clearing global intstantiated flag");
-        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVirtualizerInstantiated
-            = LVM_FALSE;
+        pSessionContext->bVirtualizerInstantiated = LVM_FALSE;
     } else if(pContext->EffectType == LVM_EQUALIZER) {
         LOGV("\tEffectRelease LVM_EQUALIZER Clearing global intstantiated flag");
-        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bEqualizerInstantiated =LVM_FALSE;
+        pSessionContext->bEqualizerInstantiated =LVM_FALSE;
     } else if(pContext->EffectType == LVM_VOLUME) {
         LOGV("\tEffectRelease LVM_VOLUME Clearing global intstantiated flag");
-        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVolumeInstantiated = LVM_FALSE;
+        pSessionContext->bVolumeInstantiated = LVM_FALSE;
     } else {
         LOGV("\tLVM_ERROR : EffectRelease : Unsupported effect\n\n\n\n\n\n\n");
     }
 
     // if all effects are no longer instantiaed free the lvm memory and delete BundledEffectContext
-    if((GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBassInstantiated == LVM_FALSE)&&
-    (GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVolumeInstantiated == LVM_FALSE)&&
-    (GlobalSessionMemory[pContext->pBundledContext->SessionNo].bEqualizerInstantiated ==LVM_FALSE)&&
-    (GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVirtualizerInstantiated==LVM_FALSE))
+    if ((pSessionContext->bBassInstantiated == LVM_FALSE) &&
+            (pSessionContext->bVolumeInstantiated == LVM_FALSE) &&
+            (pSessionContext->bEqualizerInstantiated ==LVM_FALSE) &&
+            (pSessionContext->bVirtualizerInstantiated==LVM_FALSE))
     {
         #ifdef LVM_PCM
         if (pContext->pBundledContext->PcmInPtr != NULL) {
@@ -402,8 +409,8 @@
         }
 
         LOGV("\tEffectRelease: All effects are no longer instantiated\n");
-        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBundledEffectsEnabled =LVM_FALSE;
-        GlobalSessionMemory[pContext->pBundledContext->SessionNo].pBundledContext = LVM_NULL;
+        pSessionContext->bBundledEffectsEnabled =LVM_FALSE;
+        pSessionContext->pBundledContext = LVM_NULL;
         LOGV("\tEffectRelease: Freeing LVM Bundle memory\n");
         LvmEffect_free(pContext);
         LOGV("\tEffectRelease: Deleting LVM Bundle context %p\n", pContext->pBundledContext);
@@ -2377,6 +2384,107 @@
     return db_fix;
 }
 
+//----------------------------------------------------------------------------
+// Effect_setEnabled()
+//----------------------------------------------------------------------------
+// Purpose:
+// Enable or disable effect
+//
+// Inputs:
+//  pContext      - pointer to effect context
+//  enabled       - true if enabling the effect, false otherwise
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Effect_setEnabled(EffectContext *pContext, bool enabled)
+{
+    LOGV("\tEffect_setEnabled() type %d, enabled %d", pContext->EffectType, enabled);
+
+    if (enabled) {
+        switch (pContext->EffectType) {
+            case LVM_BASS_BOOST:
+                if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
+                     LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_BASS_BOOST is already enabled");
+                     return -EINVAL;
+                }
+                pContext->pBundledContext->SamplesToExitCountBb =
+                     (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
+                pContext->pBundledContext->bBassEnabled = LVM_TRUE;
+                break;
+            case LVM_EQUALIZER:
+                if (pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE) {
+                    LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_EQUALIZER is already enabled");
+                    return -EINVAL;
+                }
+                pContext->pBundledContext->SamplesToExitCountEq =
+                     (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
+                pContext->pBundledContext->bEqualizerEnabled = LVM_TRUE;
+                break;
+            case LVM_VIRTUALIZER:
+                if (pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE) {
+                    LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_VIRTUALIZER is already enabled");
+                    return -EINVAL;
+                }
+                pContext->pBundledContext->SamplesToExitCountVirt =
+                     (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
+                pContext->pBundledContext->bVirtualizerEnabled = LVM_TRUE;
+                break;
+            case LVM_VOLUME:
+                if (pContext->pBundledContext->bVolumeEnabled == LVM_TRUE) {
+                    LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_VOLUME is already enabled");
+                    return -EINVAL;
+                }
+                pContext->pBundledContext->bVolumeEnabled = LVM_TRUE;
+                break;
+            default:
+                LOGV("\tLVM_ERROR : Effect_setEnabled() invalid effect type");
+                return -EINVAL;
+        }
+        pContext->pBundledContext->NumberEffectsEnabled++;
+        LvmEffect_enable(pContext);
+    } else {
+        switch (pContext->EffectType) {
+            case LVM_BASS_BOOST:
+                if (pContext->pBundledContext->bBassEnabled == LVM_FALSE) {
+                    LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_BASS_BOOST is already disabled");
+                    return -EINVAL;
+                }
+                pContext->pBundledContext->bBassEnabled = LVM_FALSE;
+                break;
+            case LVM_EQUALIZER:
+                if (pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE) {
+                    LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_EQUALIZER is already disabled");
+                    return -EINVAL;
+                }
+                pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
+                break;
+            case LVM_VIRTUALIZER:
+                if (pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE) {
+                    LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_VIRTUALIZER is already disabled");
+                    return -EINVAL;
+                }
+                pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
+                break;
+            case LVM_VOLUME:
+                if (pContext->pBundledContext->bVolumeEnabled == LVM_FALSE) {
+                    LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_VOLUME is already disabled");
+                    return -EINVAL;
+                }
+                pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
+                break;
+            default:
+                LOGV("\tLVM_ERROR : Effect_setEnabled() invalid effect type");
+                return -EINVAL;
+        }
+        pContext->pBundledContext->NumberEffectsEnabled--;
+        LvmEffect_disable(pContext);
+    }
+
+    return 0;
+}
+
 } // namespace
 } // namespace
 
@@ -2426,7 +2534,7 @@
             //LOGV("\tEffect_process: Waiting to turn off BASS_BOOST, %d samples left",
             //    pContext->pBundledContext->SamplesToExitCountBb);
         } else {
-        status = -ENODATA;
+            status = -ENODATA;
         }
     }
     if ((pContext->pBundledContext->bVolumeEnabled == LVM_FALSE)&&
@@ -2843,62 +2951,8 @@
                 LOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
                 return -EINVAL;
             }
-            switch (pContext->EffectType){
-                case LVM_BASS_BOOST:
-                    if(pContext->pBundledContext->bBassEnabled == LVM_TRUE){
-                         LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
-                                 "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
-                         return -EINVAL;
-                    }
-                    pContext->pBundledContext->bBassEnabled = LVM_TRUE;
-                    //LOGV("\tEffect_command cmdCode Case:EFFECT_CMD_ENABLE LVM_BASS_BOOSTenabled");
-                    break;
-                case LVM_EQUALIZER:
-                    if(pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE){
-                         LOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
-                                 "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
-                         return -EINVAL;
-                    }
-                    pContext->pBundledContext->bEqualizerEnabled = LVM_TRUE;
-                    //LOGV("\tEffect_command cmdCode Case:EFFECT_CMD_ENABLE LVM_EQUALIZER enabled");
-                    break;
-                case LVM_VIRTUALIZER:
-                    if(pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE){
-                         LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
-                                 "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
-                         return -EINVAL;
-                    }
-                    pContext->pBundledContext->bVirtualizerEnabled = LVM_TRUE;
-                    //LOGV("\tEffect_command cmdCode :EFFECT_CMD_ENABLE LVM_VIRTUALIZER enabled");
-                    break;
-                case LVM_VOLUME:
-                    if(pContext->pBundledContext->bVolumeEnabled == LVM_TRUE){
-                         LOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
-                                 "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
-                         return -EINVAL;
-                    }
-                    pContext->pBundledContext->bVolumeEnabled = LVM_TRUE;
-                    LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE LVM_VOLUME enabled");
-                    break;
-                default:
-                    LOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
-                        "EFFECT_CMD_ENABLE: ERROR, invalid Effect Type");
-                    return -EINVAL;
-            }
-            *(int *)pReplyData = 0;
-            pContext->pBundledContext->NumberEffectsEnabled++;
-            android::LvmEffect_enable(pContext);
-            pContext->pBundledContext->SamplesToExitCountEq =
-                 (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1); // 0.1 secs Stereo
-            pContext->pBundledContext->SamplesToExitCountBb =
-                 (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1); // 0.1 secs Stereo
-            pContext->pBundledContext->SamplesToExitCountVirt =
-                 (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1); // 0.1 secs Stereo
-            LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE Samples to Exit = %d",
-                pContext->pBundledContext->SamplesToExitCountBb);
-            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE NumberEffectsEnabled = %d",
-            //        pContext->pBundledContext->NumberEffectsEnabled);
-            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE end");
+
+            *(int *)pReplyData = android::Effect_setEnabled(pContext, LVM_TRUE);
             break;
 
         case EFFECT_CMD_DISABLE:
@@ -2907,57 +2961,7 @@
                 LOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
                 return -EINVAL;
             }
-            switch (pContext->EffectType){
-                case LVM_BASS_BOOST:
-                    if(pContext->pBundledContext->bBassEnabled == LVM_FALSE){
-                         LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
-                                 "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
-                         return -EINVAL;
-                    }
-                    pContext->pBundledContext->bBassEnabled      = LVM_FALSE;
-                    //LOGV("\tEffect_command cmdCode Case: "
-                    //       "EFFECT_CMD_DISABLE LVM_BASS_BOOST disabled");
-                    break;
-                case LVM_EQUALIZER:
-                    if(pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE){
-                         LOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
-                                 "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
-                         return -EINVAL;
-                    }
-                    pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
-                    //LOGV("\tEffect_command cmdCode Case: "
-                    //       "EFFECT_CMD_DISABLE LVM_EQUALIZER disabled");
-                    break;
-                case LVM_VIRTUALIZER:
-                    if(pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE){
-                         LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
-                                 "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
-                         return -EINVAL;
-                    }
-                    pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
-                    //LOGV("\tEffect_command cmdCode Case: "
-                    //     "EFFECT_CMD_DISABLE LVM_VIRTUALIZER disabled");
-                    break;
-                case LVM_VOLUME:
-                    if(pContext->pBundledContext->bVolumeEnabled == LVM_FALSE){
-                         LOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
-                                 "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
-                         return -EINVAL;
-                    }
-                    pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
-                    //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE LVM_VOLUME disabled");
-                    break;
-                default:
-                    LOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
-                        "EFFECT_CMD_DISABLE: ERROR, invalid Effect Type");
-                    return -EINVAL;
-            }
-            *(int *)pReplyData = 0;
-            pContext->pBundledContext->NumberEffectsEnabled--;
-            android::LvmEffect_disable(pContext);
-            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE NumberEffectsEnabled = %d",
-            //        pContext->pBundledContext->NumberEffectsEnabled);
-            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE end");
+            *(int *)pReplyData = android::Effect_setEnabled(pContext, LVM_FALSE);
             break;
 
         case EFFECT_CMD_SET_DEVICE:
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 86fa668..e0321a5 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -34,6 +34,7 @@
         ShoutcastSource.cpp               \
         StagefrightMediaScanner.cpp       \
         StagefrightMetadataRetriever.cpp  \
+        ThreadedSource.cpp                \
         ThrottledSource.cpp               \
         TimeSource.cpp                    \
         TimedEventQueue.cpp               \
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index fd23b61..cd70a3d 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -52,6 +52,8 @@
 #include <OMX_Audio.h>
 #include <OMX_Component.h>
 
+#include "include/ThreadedSource.h"
+
 namespace android {
 
 static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
@@ -134,6 +136,10 @@
     for (size_t i = 0;
          i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
         if (!strcmp(name, kFactoryInfo[i].name)) {
+            if (!strcmp(name, "VPXDecoder")) {
+                return new ThreadedSource(
+                        (*kFactoryInfo[i].CreateFunc)(source));
+            }
             return (*kFactoryInfo[i].CreateFunc)(source);
         }
     }
@@ -1029,7 +1035,7 @@
                 mNode, OMX_IndexParamVideoProfileLevelQuerySupported,
                 &param, sizeof(param));
 
-        if (err != OK) return err;
+        if (err != OK) break;
 
         int32_t supportedProfile = static_cast<int32_t>(param.eProfile);
         int32_t supportedLevel = static_cast<int32_t>(param.eLevel);
@@ -1037,7 +1043,10 @@
             supportedProfile, supportedLevel);
 
         if (profile == supportedProfile &&
-            level == supportedLevel) {
+            level <= supportedLevel) {
+            // We can further check whether the level is a valid
+            // value; but we will leave that to the omx encoder component
+            // via OMX_SetParameter call.
             profileLevel.mProfile = profile;
             profileLevel.mLevel = level;
             return OK;
diff --git a/media/libstagefright/ThreadedSource.cpp b/media/libstagefright/ThreadedSource.cpp
new file mode 100644
index 0000000..5add2a5
--- /dev/null
+++ b/media/libstagefright/ThreadedSource.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/ThreadedSource.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+static const size_t kMaxQueueSize = 2;
+
+ThreadedSource::ThreadedSource(const sp<MediaSource> &source)
+    : mSource(source),
+      mReflector(new AHandlerReflector<ThreadedSource>(this)),
+      mLooper(new ALooper),
+      mStarted(false) {
+    mLooper->registerHandler(mReflector);
+}
+
+ThreadedSource::~ThreadedSource() {
+    if (mStarted) {
+        stop();
+    }
+}
+
+status_t ThreadedSource::start(MetaData *params) {
+    CHECK(!mStarted);
+
+    status_t err = mSource->start(params);
+
+    if (err != OK) {
+        return err;
+    }
+
+    mFinalResult = OK;
+    mSeekTimeUs = -1;
+    mDecodePending = false;
+
+    Mutex::Autolock autoLock(mLock);
+    postDecodeMore_l();
+
+    CHECK_EQ(mLooper->start(), (status_t)OK);
+
+    mStarted = true;
+
+    return OK;
+}
+
+status_t ThreadedSource::stop() {
+    CHECK(mStarted);
+
+    CHECK_EQ(mLooper->stop(), (status_t)OK);
+
+    Mutex::Autolock autoLock(mLock);
+    clearQueue_l();
+
+    status_t err = mSource->stop();
+
+    mStarted = false;
+
+    return err;
+}
+
+sp<MetaData> ThreadedSource::getFormat() {
+    return mSource->getFormat();
+}
+
+status_t ThreadedSource::read(
+        MediaBuffer **buffer, const ReadOptions *options) {
+    *buffer = NULL;
+
+    Mutex::Autolock autoLock(mLock);
+
+    int64_t seekTimeUs;
+    ReadOptions::SeekMode seekMode;
+    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
+        int32_t seekComplete = 0;
+
+        sp<AMessage> msg = new AMessage(kWhatSeek, mReflector->id());
+        msg->setInt64("timeUs", seekTimeUs);
+        msg->setInt32("mode", seekMode);
+        msg->setPointer("complete", &seekComplete);
+        msg->post();
+
+        while (!seekComplete) {
+            mCondition.wait(mLock);
+        }
+    }
+
+    while (mQueue.empty() && mFinalResult == OK) {
+        mCondition.wait(mLock);
+    }
+
+    if (!mQueue.empty()) {
+        *buffer = *mQueue.begin();
+        mQueue.erase(mQueue.begin());
+
+        if (mFinalResult == OK) {
+            postDecodeMore_l();
+        }
+
+        return OK;
+    }
+
+    return mFinalResult;
+}
+
+void ThreadedSource::onMessageReceived(const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatSeek:
+        {
+            CHECK(msg->findInt64("timeUs", &mSeekTimeUs));
+            CHECK_GE(mSeekTimeUs, 0ll);
+
+            int32_t x;
+            CHECK(msg->findInt32("mode", &x));
+            mSeekMode = (ReadOptions::SeekMode)x;
+
+            int32_t *seekComplete;
+            CHECK(msg->findPointer("complete", (void **)&seekComplete));
+
+            Mutex::Autolock autoLock(mLock);
+            clearQueue_l();
+            mFinalResult = OK;
+
+            *seekComplete = 1;
+            mCondition.signal();
+
+            postDecodeMore_l();
+            break;
+        }
+
+        case kWhatDecodeMore:
+        {
+            {
+                Mutex::Autolock autoLock(mLock);
+                mDecodePending = false;
+
+                if (mQueue.size() == kMaxQueueSize) {
+                    break;
+                }
+            }
+
+            MediaBuffer *buffer;
+            ReadOptions options;
+            if (mSeekTimeUs >= 0) {
+                options.setSeekTo(mSeekTimeUs, mSeekMode);
+                mSeekTimeUs = -1ll;
+            }
+            status_t err = mSource->read(&buffer, &options);
+
+            Mutex::Autolock autoLock(mLock);
+
+            if (err != OK) {
+                mFinalResult = err;
+            } else {
+                mQueue.push_back(buffer);
+
+                if (mQueue.size() < kMaxQueueSize) {
+                    postDecodeMore_l();
+                }
+            }
+
+            mCondition.signal();
+            break;
+        }
+
+        default:
+            TRESPASS();
+            break;
+    }
+}
+
+void ThreadedSource::postDecodeMore_l() {
+    if (mDecodePending) {
+        return;
+    }
+
+    mDecodePending = true;
+    (new AMessage(kWhatDecodeMore, mReflector->id()))->post();
+}
+
+void ThreadedSource::clearQueue_l() {
+    while (!mQueue.empty()) {
+        MediaBuffer *buffer = *mQueue.begin();
+        mQueue.erase(mQueue.begin());
+
+        buffer->release();
+        buffer = NULL;
+    }
+}
+
+}  // namespace android
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index 57c1075..aff06bc 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -331,9 +331,20 @@
         return err;
     }
 
+    size_t maxBytesToRead =
+        mBitsPerSample == 8 ? kMaxFrameSize / 2 : kMaxFrameSize;
+
+    size_t maxBytesAvailable =
+        (mCurrentPos - mOffset >= (off_t)mSize)
+            ? 0 : mSize - (mCurrentPos - mOffset);
+
+    if (maxBytesToRead > maxBytesAvailable) {
+        maxBytesToRead = maxBytesAvailable;
+    }
+
     ssize_t n = mDataSource->readAt(
             mCurrentPos, buffer->data(),
-            mBitsPerSample == 8 ? kMaxFrameSize / 2 : kMaxFrameSize);
+            maxBytesToRead);
 
     if (n <= 0) {
         buffer->release();
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index 7154ba5..7483d60 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -317,7 +317,7 @@
                 &nalType, &nalRefIdc);
 
     if (res != AVCDEC_SUCCESS) {
-        LOGE("cannot determine nal type");
+        LOGV("cannot determine nal type");
     } else if (nalType == AVC_NALTYPE_SPS || nalType == AVC_NALTYPE_PPS
                 || (mSPSSeen && mPPSSeen)) {
         switch (nalType) {
@@ -330,6 +330,7 @@
                         fragSize);
 
                 if (res != AVCDEC_SUCCESS) {
+                    LOGV("PVAVCDecSeqParamSet returned error %d", res);
                     break;
                 }
 
@@ -396,6 +397,7 @@
                         fragSize);
 
                 if (res != AVCDEC_SUCCESS) {
+                    LOGV("PVAVCDecPicParamSet returned error %d", res);
                     break;
                 }
 
@@ -418,8 +420,13 @@
                     AVCFrameIO Output;
                     Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
 
-                    CHECK_EQ(PVAVCDecGetOutput(mHandle, &index, &Release, &Output),
-                             AVCDEC_SUCCESS);
+                    AVCDec_Status status =
+                        PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
+
+                    if (status != AVCDEC_SUCCESS) {
+                        LOGV("PVAVCDecGetOutput returned error %d", status);
+                        break;
+                    }
 
                     CHECK(index >= 0);
                     CHECK(index < (int32_t)mFrames.size());
@@ -466,7 +473,7 @@
 
                     err = OK;
                 } else {
-                    LOGV("failed to decode frame (res = %d)", res);
+                    LOGV("PVAVCDecodeSlice returned error %d", res);
                 }
                 break;
             }
diff --git a/media/libstagefright/include/ThreadedSource.h b/media/libstagefright/include/ThreadedSource.h
new file mode 100644
index 0000000..c67295c
--- /dev/null
+++ b/media/libstagefright/include/ThreadedSource.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef THREADED_SOURCE_H_
+
+#define THREADED_SOURCE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandlerReflector.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct ThreadedSource : public MediaSource {
+    ThreadedSource(const sp<MediaSource> &source);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options);
+
+    virtual void onMessageReceived(const sp<AMessage> &msg);
+
+protected:
+    virtual ~ThreadedSource();
+
+private:
+    enum {
+        kWhatDecodeMore = 'deco',
+        kWhatSeek       = 'seek',
+    };
+
+    sp<MediaSource> mSource;
+    sp<AHandlerReflector<ThreadedSource> > mReflector;
+    sp<ALooper> mLooper;
+
+    Mutex mLock;
+    Condition mCondition;
+    List<MediaBuffer *> mQueue;
+    status_t mFinalResult;
+    bool mDecodePending;
+    bool mStarted;
+
+    int64_t mSeekTimeUs;
+    ReadOptions::SeekMode mSeekMode;
+
+    void postDecodeMore_l();
+    void clearQueue_l();
+
+    DISALLOW_EVIL_CONSTRUCTORS(ThreadedSource);
+};
+
+}  // namespace android
+
+#endif  // THREADED_SOURCE_H_
diff --git a/native/include/android/input.h b/native/include/android/input.h
index c1134bf..5580700 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -295,7 +295,6 @@
     AINPUT_SOURCE_CLASS_POINTER = 0x00000002,
     AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004,
     AINPUT_SOURCE_CLASS_POSITION = 0x00000008,
-    AINPUT_SOURCE_CLASS_JOYSTICK = 0x00000010,
 };
 
 enum {
@@ -303,13 +302,10 @@
 
     AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON,
     AINPUT_SOURCE_DPAD = 0x00000200 | AINPUT_SOURCE_CLASS_BUTTON,
-    AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON,
     AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER,
     AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER,
     AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
     AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
-    AINPUT_SOURCE_JOYSTICK_LEFT = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
-    AINPUT_SOURCE_JOYSTICK_RIGHT = 0x02000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
 };
 
 /*
diff --git a/opengl/include/GLES/glext.h b/opengl/include/GLES/glext.h
index a5b3ead..65ab5e4 100644
--- a/opengl/include/GLES/glext.h
+++ b/opengl/include/GLES/glext.h
@@ -211,9 +211,12 @@
 #define GL_VERTEX_ARRAY_BINDING_OES                             0x85B5
 #endif
 
-/* GL_OES_texture_external */
-#ifndef GL_TEXTURE_EXTERNAL_OES
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
 #define GL_TEXTURE_EXTERNAL_OES                                 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES                                 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES                         0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES                     0x8D68
 #endif
 
 /*------------------------------------------------------------------------*
@@ -782,9 +785,9 @@
 typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
 #endif
 
-/* GL_OES_texture_external */
-#ifndef GL_OES_texture_external
-#define GL_OES_texture_external 1
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+#define GL_OES_EGL_image_external 1
 #endif
 
 /*------------------------------------------------------------------------*
diff --git a/opengl/include/GLES2/gl2ext.h b/opengl/include/GLES2/gl2ext.h
index de5d65a..9db4e252c 100644
--- a/opengl/include/GLES2/gl2ext.h
+++ b/opengl/include/GLES2/gl2ext.h
@@ -146,9 +146,12 @@
 #define GL_INT_10_10_10_2_OES                                   0x8DF7
 #endif
 
-/* GL_OES_texture_external */
-#ifndef GL_TEXTURE_EXTERNAL_OES
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
 #define GL_TEXTURE_EXTERNAL_OES                                 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES                                 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES                         0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES                     0x8D68
 #endif
 
 /*------------------------------------------------------------------------*
@@ -546,9 +549,9 @@
 #define GL_OES_vertex_type_10_10_10_2 1
 #endif
 
-/* GL_OES_texture_external */
-#ifndef GL_OES_texture_external
-#define GL_OES_texture_external 1
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+#define GL_OES_EGL_image_external 1
 #endif
 
 /*------------------------------------------------------------------------*
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index cbdfba9..d27c2c6 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -408,10 +408,15 @@
 
 jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
         const sp<InputChannel>& inputChannel) {
+    InputChannel* inputChannelPtr = inputChannel.get();
+    if (! inputChannelPtr) {
+        return NULL;
+    }
+
     {
         AutoMutex _l(mInputChannelRegistryLock);
 
-        ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
+        ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannelPtr);
         if (index < 0) {
             return NULL;
         }
@@ -718,13 +723,7 @@
         tokenObjLocal = NULL;
     }
 
-    jobject inputChannelObjLocal;
-    if (inputChannel.get()) {
-        inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
-    } else {
-        inputChannelObjLocal = NULL;
-    }
-
+    jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
     jlong newTimeout = env->CallLongMethod(mCallbacksObj,
                 gCallbacksClassInfo.notifyANR, tokenObjLocal, inputChannelObjLocal);
     if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
@@ -957,23 +956,17 @@
 
     JNIEnv* env = jniEnv();
 
+    // Note: inputChannel may be null.
     jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
-    if (inputChannelObj) {
-        jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
-                gCallbacksClassInfo.interceptKeyBeforeDispatching,
-                inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
-                keyEvent->getKeyCode(), keyEvent->getMetaState(),
-                keyEvent->getRepeatCount(), policyFlags);
-        bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
+    jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
+            gCallbacksClassInfo.interceptKeyBeforeDispatching,
+            inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
+            keyEvent->getKeyCode(), keyEvent->getMetaState(),
+            keyEvent->getRepeatCount(), policyFlags);
+    bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
 
-        env->DeleteLocalRef(inputChannelObj);
-
-        return consumed && ! error;
-    } else {
-        LOGW("Could not apply key dispatch policy because input channel '%s' is "
-                "no longer valid.", inputChannel->getName().string());
-        return false;
-    }
+    env->DeleteLocalRef(inputChannelObj);
+    return consumed && ! error;
 }
 
 void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t windowType, int32_t eventType) {
diff --git a/services/surfaceflinger/GLExtensions.cpp b/services/surfaceflinger/GLExtensions.cpp
index 7f4f9fc..850866a 100644
--- a/services/surfaceflinger/GLExtensions.cpp
+++ b/services/surfaceflinger/GLExtensions.cpp
@@ -86,7 +86,7 @@
         mHaveNpot = true;
     }
 
-    if (hasExtension("GL_OES_texture_external")) {
+    if (hasExtension("GL_OES_EGL_image_external")) {
         mHaveTextureExternal = true;
     } else if (strstr(mRenderer.string(), "Adreno")) {
         // hack for Adreno 200
diff --git a/services/surfaceflinger/LayerBlur.cpp b/services/surfaceflinger/LayerBlur.cpp
index 2ee21b9..4cfcfe3 100644
--- a/services/surfaceflinger/LayerBlur.cpp
+++ b/services/surfaceflinger/LayerBlur.cpp
@@ -146,7 +146,7 @@
     Region::const_iterator it = clip.begin();
     Region::const_iterator const end = clip.end();
     if (it != end) {
-#if defined(GL_OES_texture_external)
+#if defined(GL_OES_EGL_image_external)
         if (GLExtensions::getInstance().haveTextureExternal()) {
             glDisable(GL_TEXTURE_EXTERNAL_OES);
         }
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index a1f339e..80cc52c 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -71,7 +71,7 @@
         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
         glColor4f(0, 0, 0, alpha);
 
-#if defined(GL_OES_texture_external)
+#if defined(GL_OES_EGL_image_external)
         if (GLExtensions::getInstance().haveTextureExternal()) {
             glDisable(GL_TEXTURE_EXTERNAL_OES);
         }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f199ca9..dc241d4e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -917,7 +917,7 @@
         glVertexPointer(2, GL_SHORT, 0, vertices);
         glTexCoordPointer(2, GL_SHORT, 0, tcoords);
         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-#if defined(GL_OES_texture_external)
+#if defined(GL_OES_EGL_image_external)
         if (GLExtensions::getInstance().haveTextureExternal()) {
             glDisable(GL_TEXTURE_EXTERNAL_OES);
         }
diff --git a/services/surfaceflinger/TextureManager.cpp b/services/surfaceflinger/TextureManager.cpp
index 76f6159..c9a15f5 100644
--- a/services/surfaceflinger/TextureManager.cpp
+++ b/services/surfaceflinger/TextureManager.cpp
@@ -43,7 +43,7 @@
 }
 
 GLenum TextureManager::getTextureTarget(const Image* image) {
-#if defined(GL_OES_texture_external)
+#if defined(GL_OES_EGL_image_external)
     switch (image->target) {
         case Texture::TEXTURE_EXTERNAL:
             return GL_TEXTURE_EXTERNAL_OES;
@@ -85,7 +85,7 @@
     pImage->height = 0;
 
     GLenum target = GL_TEXTURE_2D;
-#if defined(GL_OES_texture_external)
+#if defined(GL_OES_EGL_image_external)
     if (GLExtensions::getInstance().haveTextureExternal()) {
         if (format && isYuvFormat(format)) {
             target = GL_TEXTURE_EXTERNAL_OES;
@@ -306,7 +306,7 @@
     if (target == GL_TEXTURE_2D) {
         glBindTexture(GL_TEXTURE_2D, texture.name);
         glEnable(GL_TEXTURE_2D);
-#if defined(GL_OES_texture_external)
+#if defined(GL_OES_EGL_image_external)
         if (GLExtensions::getInstance().haveTextureExternal()) {
             glDisable(GL_TEXTURE_EXTERNAL_OES);
         }
@@ -329,7 +329,7 @@
 void TextureManager::deactivateTextures()
 {
     glDisable(GL_TEXTURE_2D);
-#if defined(GL_OES_texture_external)
+#if defined(GL_OES_EGL_image_external)
     if (GLExtensions::getInstance().haveTextureExternal()) {
         glDisable(GL_TEXTURE_EXTERNAL_OES);
     }