Merge "Expose unchecked copyFrom variants." into honeycomb
diff --git a/api/11.xml b/api/11.xml
index 945c614..31cfc85 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -160213,17 +160213,6 @@
  visibility="public"
 >
 </field>
-<field name="ACTION_MTP_SESSION_END"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.provider.action.MTP_SESSION_END&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="ACTION_VIDEO_CAPTURE"
  type="java.lang.String"
  transient="false"
diff --git a/api/current.xml b/api/current.xml
index 945c614..83bfedb 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -146705,6 +146705,17 @@
  visibility="public"
 >
 </method>
+<method name="detectActivityLeaks"
+ return="android.os.StrictMode.VmPolicy.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="detectAll"
  return="android.os.StrictMode.VmPolicy.Builder"
  abstract="false"
@@ -160213,17 +160224,6 @@
  visibility="public"
 >
 </field>
-<field name="ACTION_MTP_SESSION_END"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.provider.action.MTP_SESSION_END&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="ACTION_VIDEO_CAPTURE"
  type="java.lang.String"
  transient="false"
diff --git a/build/phone-hdpi-512-dalvik-heap.mk b/build/phone-hdpi-512-dalvik-heap.mk
index afc45ee..a7f9d32 100644
--- a/build/phone-hdpi-512-dalvik-heap.mk
+++ b/build/phone-hdpi-512-dalvik-heap.mk
@@ -19,5 +19,4 @@
 
 PRODUCT_PROPERTY_OVERRIDES += \
     dalvik.vm.heapstartsize=5m \
-    dalvik.vm.smallheapsize=32m \
     dalvik.vm.heapsize=32m
diff --git a/build/phone-hdpi-dalvik-heap.mk b/build/phone-hdpi-dalvik-heap.mk
index ee30b92..ab33b96 100644
--- a/build/phone-hdpi-dalvik-heap.mk
+++ b/build/phone-hdpi-dalvik-heap.mk
@@ -18,5 +18,4 @@
 
 PRODUCT_PROPERTY_OVERRIDES += \
     dalvik.vm.heapstartsize=5m \
-    dalvik.vm.smallheapsize=32m \
     dalvik.vm.heapsize=32m
diff --git a/build/tablet-dalvik-heap.mk b/build/tablet-dalvik-heap.mk
index 9cb2f6b..37c3ec5 100644
--- a/build/tablet-dalvik-heap.mk
+++ b/build/tablet-dalvik-heap.mk
@@ -18,5 +18,5 @@
 
 PRODUCT_PROPERTY_OVERRIDES += \
     dalvik.vm.heapstartsize=5m \
-    dalvik.vm.smallheapsize=48m \
-    dalvik.vm.heapsize=48m
+    dalvik.vm.growthlimit=48m \
+    dalvik.vm.heapsize=256m
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 0a64070..ec6eaaa 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4433,6 +4433,9 @@
             mStopped = true;
         }
         mResumed = false;
+
+        // Check for Activity leaks, if enabled.
+        StrictMode.conditionallyCheckInstanceCounts();
     }
 
     final void performDestroy() {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0243b02..de84c56 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -34,6 +34,9 @@
  * A class that represents how a persistent notification is to be presented to
  * the user using the {@link android.app.NotificationManager}.
  *
+ * <p>The {@link Notification.Builder Notification.Builder} has been added to make it
+ * easier to construct Notifications.</p>
+ *
  * <p>For a guide to creating notifications, see the
  * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status 
  * Bar Notifications</a> document in the Dev Guide.</p>
@@ -119,15 +122,8 @@
 
     /**
      * An intent to launch instead of posting the notification to the status bar.
-     * Only for use with extremely high-priority notifications demanding the user's
-     * <strong>immediate</strong> attention, such as an incoming phone call or
-     * alarm clock that the user has explicitly set to a particular time.
-     * If this facility is used for something else, please give the user an option
-     * to turn it off and use a normal notification, as this can be extremely
-     * disruptive.
-     * 
-     * <p>Use with {@link #FLAG_HIGH_PRIORITY} to ensure that this notification
-     * will reach the user even when other notifications are suppressed.
+     *
+     * @see Notification.Builder#setFullScreenIntent
      */
     public PendingIntent fullScreenIntent;
 
@@ -278,7 +274,7 @@
     /**
      * Bit to be bitwise-ored into the {@link #flags} field that should be
      * set if the notification should be canceled when it is clicked by the
-     * user. 
+     * user.  On tablets, the 
      */
     public static final int FLAG_AUTO_CANCEL        = 0x00000010;
 
@@ -618,6 +614,10 @@
         return sb.toString();
     }
 
+    /**
+     * Builder class for {@link Notification} objects.  Allows easier control over
+     * all the flags, as well as help constructing the typical notification layouts.
+     */
     public static class Builder {
         private Context mContext;
 
@@ -644,6 +644,16 @@
         private int mDefaults;
         private int mFlags;
 
+        /**
+         * Constructor.
+         *
+         * Automatically sets the when field to {@link System#currentTimeMillis()
+         * System.currentTimeMllis()} and the audio stream to the {@link #STREAM_DEFAULT}.
+         *
+         * @param context A {@link Context} that will be used to construct the
+         *      RemoteViews. The Context will not be held past the lifetime of this
+         *      Builder object.
+         */
         public Builder(Context context) {
             mContext = context;
 
@@ -652,96 +662,192 @@
             mAudioStreamType = STREAM_DEFAULT;
         }
 
+        /**
+         * Set the time that the event occurred.  Notifications in the panel are
+         * sorted by this time.
+         */
         public Builder setWhen(long when) {
             mWhen = when;
             return this;
         }
 
+        /**
+         * Set the small icon to use in the notification layouts.  Different classes of devices
+         * may return different sizes.  See the UX guidelines for more information on how to
+         * design these icons.
+         *
+         * @param icon A resource ID in the application's package of the drawble to use.
+         */
         public Builder setSmallIcon(int icon) {
             mSmallIcon = icon;
             return this;
         }
 
+        /**
+         * A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional
+         * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable
+         * LevelListDrawable}.
+         *
+         * @param icon A resource ID in the application's package of the drawble to use.
+         * @param level The level to use for the icon.
+         *
+         * @see android.graphics.drawable.LevelListDrawable
+         */
         public Builder setSmallIcon(int icon, int level) {
             mSmallIcon = icon;
             mSmallIconLevel = level;
             return this;
         }
 
+        /**
+         * Set the title (first row) of the notification, in a standard notification.
+         */
         public Builder setContentTitle(CharSequence title) {
             mContentTitle = title;
             return this;
         }
 
+        /**
+         * Set the text (second row) of the notification, in a standard notification.
+         */
         public Builder setContentText(CharSequence text) {
             mContentText = text;
             return this;
         }
 
+        /**
+         * Set the large number at the right-hand side of the notification.  This is
+         * equivalent to setContentInfo, although it might show the number in a different
+         * font size for readability.
+         */
         public Builder setNumber(int number) {
             mNumber = number;
             return this;
         }
 
+        /**
+         * Set the large text at the right-hand side of the notification.
+         */
         public Builder setContentInfo(CharSequence info) {
             mContentInfo = info;
             return this;
         }
 
+        /**
+         * Supply a custom RemoteViews to use instead of the standard one.
+         */
         public Builder setContent(RemoteViews views) {
             mContentView = views;
             return this;
         }
 
+        /**
+         * Supply a {@link PendingIntent} to send when the notification is clicked.
+         * If you do not supply an intent, you can now add PendingIntents to individual
+         * views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent
+         * RemoteViews.setOnClickPendingIntent(int,PendingIntent)}.
+         */
         public Builder setContentIntent(PendingIntent intent) {
             mContentIntent = intent;
             return this;
         }
 
+        /**
+         * Supply a {@link PendingIntent} to send when the notification is cleared by the user
+         * directly from the notification panel.  For example, this intent is sent when the user
+         * clicks the "Clear all" button, or the individual "X" buttons on notifications.  This
+         * intent is not sent when the application calls {@link NotificationManager#cancel
+         * NotificationManager.cancel(int)}.
+         */
         public Builder setDeleteIntent(PendingIntent intent) {
             mDeleteIntent = intent;
             return this;
         }
 
+        /**
+         * An intent to launch instead of posting the notification to the status bar.
+         * Only for use with extremely high-priority notifications demanding the user's
+         * <strong>immediate</strong> attention, such as an incoming phone call or
+         * alarm clock that the user has explicitly set to a particular time.
+         * If this facility is used for something else, please give the user an option
+         * to turn it off and use a normal notification, as this can be extremely
+         * disruptive.
+         *
+         * @param intent The pending intent to launch.
+         * @param highPriority Passing true will cause this notification to be sent
+         *          even if other notifications are suppressed.
+         */
         public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) {
             mFullScreenIntent = intent;
             setFlag(FLAG_HIGH_PRIORITY, highPriority);
             return this;
         }
 
+        /**
+         * Set the text that is displayed in the status bar when the notification first
+         * arrives.
+         */
         public Builder setTicker(CharSequence tickerText) {
             mTickerText = tickerText;
             return this;
         }
 
+        /**
+         * Set the text that is displayed in the status bar when the notification first
+         * arrives, and also a RemoteViews object that may be displayed instead on some
+         * devices.
+         */
         public Builder setTicker(CharSequence tickerText, RemoteViews views) {
             mTickerText = tickerText;
             mTickerView = views;
             return this;
         }
 
+        /**
+         * Set the large icon that is shown in the ticker and notification.
+         */
         public Builder setLargeIcon(Bitmap icon) {
             mLargeIcon = icon;
             return this;
         }
 
+        /**
+         * Set the sound to play.  It will play on the default stream.
+         */
         public Builder setSound(Uri sound) {
             mSound = sound;
             mAudioStreamType = STREAM_DEFAULT;
             return this;
         }
 
+        /**
+         * Set the sound to play.  It will play on the stream you supply.
+         *
+         * @see #STREAM_DEFAULT
+         * @see AudioManager for the <code>STREAM_</code> constants.
+         */
         public Builder setSound(Uri sound, int streamType) {
             mSound = sound;
             mAudioStreamType = streamType;
             return this;
         }
 
+        /**
+         * Set the vibration pattern to use.
+         *
+         * @see android.os.Vibrator for a discussion of the <code>pattern</code>
+         * parameter.
+         */
         public Builder setVibrate(long[] pattern) {
             mVibrate = pattern;
             return this;
         }
 
+        /**
+         * Set the argb value that you would like the LED on the device to blnk, as well as the
+         * rate.  The rate is specified in terms of the number of milliseconds to be on
+         * and then the number of milliseconds to be off.
+         */
         public Builder setLights(int argb, int onMs, int offMs) {
             mLedArgb = argb;
             mLedOnMs = onMs;
@@ -749,21 +855,51 @@
             return this;
         }
 
+        /**
+         * Set whether this is an ongoing notification.
+         *
+         * <p>Ongoing notifications differ from regular notifications in the following ways:
+         * <ul>
+         *   <li>Ongoing notifications are sorted above the regular notifications in the
+         *   notification panel.</li>
+         *   <li>Ongoing notifications do not have an 'X' close button, and are not affected
+         *   by the "Clear all" button.
+         * </ul>
+         */
         public Builder setOngoing(boolean ongoing) {
             setFlag(FLAG_ONGOING_EVENT, ongoing);
             return this;
         }
 
+        /**
+         * Set this flag if you would only like the sound, vibrate
+         * and ticker to be played if the notification is not already showing.
+         */
         public Builder setOnlyAlertOnce(boolean onlyAlertOnce) {
             setFlag(FLAG_ONLY_ALERT_ONCE, onlyAlertOnce);
             return this;
         }
 
+        /**
+         * Setting this flag will make it so the notification is automatically
+         * canceled when the user clicks it in the panel.  The PendingIntent
+         * set with {@link #setDeleteIntent} will be broadcast when the notification
+         * is canceled.
+         */
         public Builder setAutoCancel(boolean autoCancel) {
             setFlag(FLAG_AUTO_CANCEL, autoCancel);
             return this;
         }
 
+        /**
+         * Set the default notification options that will be used.
+         * <p>
+         * The value should be one or more of the following fields combined with
+         * bitwise-or:
+         * {@link #DEFAULT_SOUND}, {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}.
+         * <p>
+         * For all default values, use {@link #DEFAULT_ALL}.
+         */
         public Builder setDefaults(int defaults) {
             mDefaults = defaults;
             return this;
@@ -834,6 +970,10 @@
             }
         }
 
+        /**
+         * Combine all of the options that have been set and return a new {@link Notification}
+         * object.
+         */
         public Notification getNotification() {
             Notification n = new Notification();
             n.when = mWhen;
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index bc8a836..a70de59 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -85,6 +85,19 @@
      */
     public static final int PRIORITY_UNDEFINED = -1;
 
+    /**
+     * Return codes for the connect and disconnect Bluez / Dbus calls.
+     */
+    public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
+
+    public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
+
+    public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002;
+
+    public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003;
+
+    public static final int INPUT_OPERATION_SUCCESS = 5004;
+
     private final IBluetooth mService;
     private final Context mContext;
 
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 7dee25e..1f07349 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -70,6 +70,19 @@
     public static final int STATE_CONNECTED    = 2;
     public static final int STATE_DISCONNECTING = 3;
 
+    /**
+     * Return codes for the connect and disconnect Bluez / Dbus calls.
+     */
+    public static final int PAN_DISCONNECT_FAILED_NOT_CONNECTED = 1000;
+
+    public static final int PAN_CONNECT_FAILED_ALREADY_CONNECTED = 1001;
+
+    public static final int PAN_CONNECT_FAILED_ATTEMPT_FAILED = 1002;
+
+    public static final int PAN_OPERATION_GENERIC_FAILURE = 1003;
+
+    public static final int PAN_OPERATION_SUCCESS = 1004;
+
     private final IBluetooth mService;
     private final Context mContext;
 
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 997ea53..ae92b09 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -30,6 +30,7 @@
 
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
+import dalvik.system.VMDebug;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -184,6 +185,15 @@
     /**
      * @hide
      */
+    private static final int DETECT_VM_INSTANCE_LEAKS = 0x1000;  // for VmPolicy
+
+    private static final int ALL_VM_DETECT_BITS =
+            DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
+            DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS;
+
+    /**
+     * @hide
+     */
     public static final int PENALTY_LOG = 0x10;  // normal android.util.Log
 
     // Used for both process and thread policy:
@@ -573,11 +583,15 @@
                 } else if (mClassInstanceLimit == null) {
                     mClassInstanceLimit = new HashMap<Class, Integer>();
                 }
+                mMask |= DETECT_VM_INSTANCE_LEAKS;
                 mClassInstanceLimit.put(klass, instanceLimit);
                 return this;
             }
 
-            private Builder detectActivityLeaks() {
+            /**
+             * Detect leaks of {@link android.app.Activity} subclasses.
+             */
+            public Builder detectActivityLeaks() {
                 return enable(DETECT_VM_ACTIVITY_LEAKS);
             }
 
@@ -585,8 +599,8 @@
              * Detect everything that's potentially suspect.
              *
              * <p>In the Honeycomb release this includes leaks of
-             * SQLite cursors and other closable objects but will
-             * likely expand in future releases.
+             * SQLite cursors, Activities, and other closable objects
+             * but will likely expand in future releases.
              */
             public Builder detectAll() {
                 return enable(DETECT_VM_ACTIVITY_LEAKS |
@@ -1347,6 +1361,41 @@
     }
 
     /**
+     * @hide
+     */
+    public static void conditionallyCheckInstanceCounts() {
+        VmPolicy policy = getVmPolicy();
+        if (policy.classInstanceLimit.size() == 0) {
+            return;
+        }
+        Runtime.getRuntime().gc();
+        // Note: classInstanceLimit is immutable, so this is lock-free
+        for (Class klass : policy.classInstanceLimit.keySet()) {
+            int limit = policy.classInstanceLimit.get(klass);
+            long instances = VMDebug.countInstancesOfClass(klass, false);
+            if (instances <= limit) {
+                continue;
+            }
+            Throwable tr = new InstanceCountViolation(klass, instances, limit);
+            onVmPolicyViolation(tr.getMessage(), tr);
+        }
+    }
+
+    private static long sLastInstanceCountCheckMillis = 0;
+    private static boolean sIsIdlerRegistered = false;  // guarded by sProcessIdleHandler
+    private static final MessageQueue.IdleHandler sProcessIdleHandler =
+            new MessageQueue.IdleHandler() {
+                public boolean queueIdle() {
+                    long now = SystemClock.uptimeMillis();
+                    if (now - sLastInstanceCountCheckMillis > 30 * 1000) {
+                        sLastInstanceCountCheckMillis = now;
+                        conditionallyCheckInstanceCounts();
+                    }
+                    return true;
+                }
+            };
+
+    /**
      * Sets the policy for what actions in the VM process (on any
      * thread) should be detected, as well as the penalty if such
      * actions occur.
@@ -1357,6 +1406,19 @@
         sVmPolicy = policy;
         sVmPolicyMask = policy.mask;
         setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
+
+        Looper looper = Looper.getMainLooper();
+        if (looper != null) {
+            MessageQueue mq = looper.mQueue;
+            synchronized (sProcessIdleHandler) {
+                if (policy.classInstanceLimit.size() == 0) {
+                    mq.removeIdleHandler(sProcessIdleHandler);
+                } else if (!sIsIdlerRegistered) {
+                    mq.addIdleHandler(sProcessIdleHandler);
+                    sIsIdlerRegistered = true;
+                }
+            }
+        }
     }
 
     /**
@@ -1406,19 +1468,39 @@
         onVmPolicyViolation(message, originStack);
     }
 
+    // Map from VM violation fingerprint to uptime millis.
+    private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
+
     /**
      * @hide
      */
     public static void onVmPolicyViolation(String message, Throwable originStack) {
-        if ((sVmPolicyMask & PENALTY_LOG) != 0) {
+        final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
+        final boolean penaltyDeath = (sVmPolicyMask & PENALTY_DEATH) != 0;
+        final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
+        final ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask);
+
+        final Integer fingerprint = info.hashCode();
+        final long now = SystemClock.uptimeMillis();
+        long lastViolationTime = 0;
+        long timeSinceLastViolationMillis = Long.MAX_VALUE;
+        synchronized (sLastVmViolationTime) {
+            if (sLastVmViolationTime.containsKey(fingerprint)) {
+                lastViolationTime = sLastVmViolationTime.get(fingerprint);
+                timeSinceLastViolationMillis = now - lastViolationTime;
+            }
+            if (timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
+                sLastVmViolationTime.put(fingerprint, now);
+            }
+        }
+
+        Log.d(TAG, "Time since last vm violation: " + timeSinceLastViolationMillis);
+
+        if (penaltyLog && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) {
             Log.e(TAG, message, originStack);
         }
 
-        boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
-        boolean penaltyDeath = (sVmPolicyMask & PENALTY_DEATH) != 0;
-
-        int violationMaskSubset = PENALTY_DROPBOX | DETECT_VM_CURSOR_LEAKS;
-        ViolationInfo info = new ViolationInfo(originStack, sVmPolicyMask);
+        int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);
 
         if (penaltyDropbox && !penaltyDeath) {
             // Common case for userdebug/eng builds.  If no death and
@@ -1428,7 +1510,7 @@
             return;
         }
 
-        if (penaltyDropbox) {
+        if (penaltyDropbox && lastViolationTime == 0) {
             // The violationMask, passed to ActivityManager, is a
             // subset of the original StrictMode policy bitmask, with
             // only the bit violated and penalty bits to be executed
@@ -1786,6 +1868,12 @@
         public String broadcastIntentAction;
 
         /**
+         * If this is a instance count violation, the number of instances in memory,
+         * else -1.
+         */
+        public long numInstances = -1;
+
+        /**
          * Create an uninitialized instance of ViolationInfo
          */
         public ViolationInfo() {
@@ -1806,6 +1894,9 @@
                 broadcastIntentAction = broadcastIntent.getAction();
             }
             ThreadSpanState state = sThisThreadSpanState.get();
+            if (tr instanceof InstanceCountViolation) {
+                this.numInstances = ((InstanceCountViolation) tr).mInstances;
+            }
             synchronized (state) {
                 int spanActiveCount = state.mActiveSize;
                 if (spanActiveCount > MAX_SPAN_TAGS) {
@@ -1867,6 +1958,7 @@
             violationNumThisLoop = in.readInt();
             numAnimationsRunning = in.readInt();
             violationUptimeMillis = in.readLong();
+            numInstances = in.readLong();
             broadcastIntentAction = in.readString();
             tags = in.readStringArray();
         }
@@ -1881,6 +1973,7 @@
             dest.writeInt(violationNumThisLoop);
             dest.writeInt(numAnimationsRunning);
             dest.writeLong(violationUptimeMillis);
+            dest.writeLong(numInstances);
             dest.writeString(broadcastIntentAction);
             dest.writeStringArray(tags);
         }
@@ -1895,6 +1988,9 @@
             if (durationMillis != -1) {
                 pw.println(prefix + "durationMillis: " + durationMillis);
             }
+            if (numInstances != -1) {
+                pw.println(prefix + "numInstances: " + numInstances);
+            }
             if (violationNumThisLoop != 0) {
                 pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
             }
@@ -1914,4 +2010,29 @@
         }
 
     }
+
+    // Dummy throwable, for now, since we don't know when or where the
+    // leaked instances came from.  We might in the future, but for
+    // now we suppress the stack trace because it's useless and/or
+    // misleading.
+    private static class InstanceCountViolation extends Throwable {
+        final Class mClass;
+        final long mInstances;
+        final int mLimit;
+
+        private static final StackTraceElement[] FAKE_STACK = new StackTraceElement[1];
+        static {
+            FAKE_STACK[0] = new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit",
+                                                  "StrictMode.java", 1);
+        }
+
+        public InstanceCountViolation(Class klass, long instances, int limit) {
+            // Note: now including instances here, otherwise signatures would all be different.
+            super(klass.toString() + "; limit=" + limit);
+            setStackTrace(FAKE_STACK);
+            mClass = klass;
+            mInstances = instances;
+            mLimit = limit;
+        }
+    }
 }
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 9f0ea32..82fe7de 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -57,6 +57,8 @@
      * Broadcast Action:  A broadcast to indicate the end of an MTP session with the host.
      * This broadcast is only sent if MTP activity has modified the media database during the
      * most recent MTP session.
+     *
+     * @hide
      */
     public static final String ACTION_MTP_SESSION_END = "android.provider.action.MTP_SESSION_END";
 
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 539a696..cd3bc3e 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -748,9 +748,9 @@
         }
     }
 
-    private void onInputDeviceConnectionResult(String path, boolean result) {
+    private void onInputDeviceConnectionResult(String path, int result) {
         // Success case gets handled by Property Change signal
-        if (!result) {
+        if (result != BluetoothInputDevice.INPUT_OPERATION_SUCCESS) {
             String address = mBluetoothService.getAddressFromObjectPath(path);
             if (address == null) return;
 
@@ -758,9 +758,18 @@
             BluetoothDevice device = mAdapter.getRemoteDevice(address);
             int state = mBluetoothService.getInputDeviceState(device);
             if (state == BluetoothInputDevice.STATE_CONNECTING) {
-                connected = false;
+                if (result == BluetoothInputDevice.INPUT_CONNECT_FAILED_ALREADY_CONNECTED) {
+                    connected = true;
+                } else {
+                    connected = false;
+                }
             } else if (state == BluetoothInputDevice.STATE_DISCONNECTING) {
-                connected = true;
+                if (result == BluetoothInputDevice.INPUT_DISCONNECT_FAILED_NOT_CONNECTED) {
+                    connected = false;
+                } else {
+                    // There is no better way to handle this, this shouldn't happen
+                    connected = true;
+                }
             } else {
                 Log.e(TAG, "Error onInputDeviceConnectionResult. State is:" + state);
             }
@@ -768,10 +777,10 @@
         }
     }
 
-    private void onPanDeviceConnectionResult(String path, boolean result) {
+    private void onPanDeviceConnectionResult(String path, int result) {
         log ("onPanDeviceConnectionResult " + path + " " + result);
         // Success case gets handled by Property Change signal
-        if (!result) {
+        if (result != BluetoothPan.PAN_OPERATION_SUCCESS) {
             String address = mBluetoothService.getAddressFromObjectPath(path);
             if (address == null) return;
 
@@ -779,9 +788,18 @@
             BluetoothDevice device = mAdapter.getRemoteDevice(address);
             int state = mBluetoothService.getPanDeviceState(device);
             if (state == BluetoothPan.STATE_CONNECTING) {
-                connected = false;
+                if (result == BluetoothPan.PAN_CONNECT_FAILED_ALREADY_CONNECTED) {
+                    connected = true;
+                } else {
+                    connected = false;
+                }
             } else if (state == BluetoothPan.STATE_DISCONNECTING) {
-                connected = true;
+                if (result == BluetoothPan.PAN_DISCONNECT_FAILED_NOT_CONNECTED) {
+                    connected = false;
+                } else {
+                    // There is no better way to handle this, this shouldn't happen
+                    connected = true;
+                }
             } else {
                 Log.e(TAG, "Error onPanDeviceConnectionResult. State is: "
                         + state + " result: "+ result);
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 99b686e..f480554 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -452,11 +452,14 @@
     @Override
     public int saveLayer(float left, float top, float right, float bottom, Paint paint,
             int saveFlags) {
-        boolean hasColorFilter = paint != null && setupColorFilter(paint);
-        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
-        int count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
-        if (hasColorFilter) nResetModifiers(mRenderer);
-        return count;
+        if (left < right && top < bottom) {
+            boolean hasColorFilter = paint != null && setupColorFilter(paint);
+            final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+            int count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
+            if (hasColorFilter) nResetModifiers(mRenderer);
+            return count;
+        }
+        return save(saveFlags);
     }
 
     private native int nSaveLayer(int renderer, float left, float top, float right, float bottom,
@@ -471,7 +474,10 @@
     @Override
     public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
             int saveFlags) {
-        return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
+        if (left < right && top < bottom) {
+            return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
+        }
+        return save(saveFlags);
     }
 
     private native int nSaveLayerAlpha(int renderer, float left, float top, float right,
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 270ea76..2447f8c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -58,7 +58,6 @@
 import android.util.Pools;
 import android.util.SparseArray;
 import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View.MeasureSpec;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityEventSource;
 import android.view.accessibility.AccessibilityManager;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d1781cc..115431e 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -935,15 +935,17 @@
         } break;
 
         case DragEvent.ACTION_DRAG_ENDED: {
-            // If a child was notified about an ongoing drag, it's told that it's over
-            for (View child : mDragNotifiedChildren) {
-                child.dispatchDragEvent(event);
-            }
-
             // Release the bookkeeping now that the drag lifecycle has ended
-            mDragNotifiedChildren.clear();
-            mCurrentDrag.recycle();
-            mCurrentDrag = null;
+            if (mDragNotifiedChildren != null) {
+                for (View child : mDragNotifiedChildren) {
+                    // If a child was notified about an ongoing drag, it's told that it's over
+                    child.dispatchDragEvent(event);
+                }
+
+                mDragNotifiedChildren.clear();
+                mCurrentDrag.recycle();
+                mCurrentDrag = null;
+            }
 
             // We consider drag-ended to have been handled if one of our children
             // had offered to handle the drag.
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 961b633..1f15628 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -2803,6 +2803,7 @@
 
                 // Report the drop result when we're done
                 if (what == DragEvent.ACTION_DROP) {
+                    mDragDescription = null;
                     try {
                         Log.i(TAG, "Reporting drop result: " + result);
                         sWindowSession.reportDropResult(mWindow, result);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index c54a3cf..8eb4269 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -817,7 +817,7 @@
         public static final int SOFT_INPUT_IS_FORWARD_NAVIGATION = 0x100;
 
         /**
-         * Desired operating mode for any soft input area.  May any combination
+         * Desired operating mode for any soft input area.  May be any combination
          * of:
          * 
          * <ul>
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c509dae..7b3ea74 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -408,10 +408,13 @@
     PluginFullScreenHolder mFullScreenHolder;
 
     /**
-     * Position of the last touch event.
+     * Position of the last touch event in pixels.
+     * Use integer to prevent loss of dragging delta calculation accuracy;
+     * which was done in float and converted to integer, and resulted in gradual
+     * and compounding touch position and view dragging mismatch.
      */
-    private float mLastTouchX;
-    private float mLastTouchY;
+    private int mLastTouchX;
+    private int mLastTouchY;
 
     /**
      * Time of the last touch event.
@@ -2218,8 +2221,8 @@
         if (type == HitTestResult.UNKNOWN_TYPE
                 || type == HitTestResult.SRC_ANCHOR_TYPE) {
             // Now check to see if it is an image.
-            int contentX = viewToContentX((int) mLastTouchX + mScrollX);
-            int contentY = viewToContentY((int) mLastTouchY + mScrollY);
+            int contentX = viewToContentX(mLastTouchX + mScrollX);
+            int contentY = viewToContentY(mLastTouchY + mScrollY);
             String text = nativeImageURI(contentX, contentY);
             if (text != null) {
                 result.setType(type == HitTestResult.UNKNOWN_TYPE ?
@@ -2256,8 +2259,8 @@
         if (hrefMsg == null) {
             return;
         }
-        int contentX = viewToContentX((int) mLastTouchX + mScrollX);
-        int contentY = viewToContentY((int) mLastTouchY + mScrollY);
+        int contentX = viewToContentX(mLastTouchX + mScrollX);
+        int contentY = viewToContentY(mLastTouchY + mScrollY);
         mWebViewCore.sendMessage(EventHub.REQUEST_CURSOR_HREF,
                 contentX, contentY, hrefMsg);
     }
@@ -2271,8 +2274,8 @@
      */
     public void requestImageRef(Message msg) {
         if (0 == mNativeClass) return; // client isn't initialized
-        int contentX = viewToContentX((int) mLastTouchX + mScrollX);
-        int contentY = viewToContentY((int) mLastTouchY + mScrollY);
+        int contentX = viewToContentX(mLastTouchX + mScrollX);
+        int contentY = viewToContentY(mLastTouchY + mScrollY);
         String ref = nativeImageURI(contentX, contentY);
         Bundle data = msg.getData();
         data.putString("url", ref);
@@ -3856,8 +3859,8 @@
      * @hide pending API council approval
      */
     public boolean selectText() {
-        int x = viewToContentX((int) mLastTouchX + mScrollX);
-        int y = viewToContentY((int) mLastTouchY + mScrollY);
+        int x = viewToContentX(mLastTouchX + mScrollX);
+        int y = viewToContentY(mLastTouchY + mScrollY);
         return selectText(x, y);
     }
 
@@ -4858,8 +4861,8 @@
             mSelectX = contentToViewX(rect.left);
             mSelectY = contentToViewY(rect.top);
         } else if (mLastTouchY > getVisibleTitleHeight()) {
-            mSelectX = mScrollX + (int) mLastTouchX;
-            mSelectY = mScrollY + (int) mLastTouchY;
+            mSelectX = mScrollX + mLastTouchX;
+            mSelectY = mScrollY + mLastTouchY;
         } else {
             mSelectX = mScrollX + getViewWidth() / 2;
             mSelectY = mScrollY + getViewHeightWithTitle() / 2;
@@ -5357,7 +5360,7 @@
             return true;
         }
 
-        return handleTouchEventCommon(ev, ev.getX(), ev.getY());
+        return handleTouchEventCommon(ev, Math.round(ev.getX()), Math.round(ev.getY()));
     }
 
     /*
@@ -5365,7 +5368,7 @@
      * (x, y) denotes current focus point, which is the touch point for single touch
      * and the middle point for multi-touch.
      */
-    private boolean handleTouchEventCommon(MotionEvent ev, float x, float y) {
+    private boolean handleTouchEventCommon(MotionEvent ev, int x, int y) {
         int action = ev.getAction();
         long eventTime = ev.getEventTime();
 
@@ -5377,12 +5380,10 @@
         x = Math.min(x, getViewWidth() - 1);
         y = Math.min(y, getViewHeightWithTitle() - 1);
 
-        float fDeltaX = mLastTouchX - x;
-        float fDeltaY = mLastTouchY - y;
-        int deltaX = (int) fDeltaX;
-        int deltaY = (int) fDeltaY;
-        int contentX = viewToContentX((int) x + mScrollX);
-        int contentY = viewToContentY((int) y + mScrollY);
+        int deltaX = mLastTouchX - x;
+        int deltaY = mLastTouchY - y;
+        int contentX = viewToContentX(x + mScrollX);
+        int contentY = viewToContentY(y + mScrollY);
 
         switch (action) {
             case MotionEvent.ACTION_DOWN: {
@@ -5607,8 +5608,6 @@
                     mTouchMode = TOUCH_DRAG_MODE;
                     mLastTouchX = x;
                     mLastTouchY = y;
-                    fDeltaX = 0.0f;
-                    fDeltaY = 0.0f;
                     deltaX = 0;
                     deltaY = 0;
 
@@ -5619,9 +5618,7 @@
                 // do pan
                 boolean done = false;
                 boolean keepScrollBarsVisible = false;
-                if (Math.abs(fDeltaX) < 1.0f && Math.abs(fDeltaY) < 1.0f) {
-                    mLastTouchX = x;
-                    mLastTouchY = y;
+                if (deltaX == 0 && deltaY == 0) {
                     keepScrollBarsVisible = done = true;
                 } else {
                     if (mSnapScrollMode == SNAP_X || mSnapScrollMode == SNAP_Y) {
@@ -5670,12 +5667,6 @@
                             mLastTouchY = y;
                         }
                         mHeldMotionless = MOTIONLESS_FALSE;
-                    } else {
-                        // keep the scrollbar on the screen even there is no
-                        // scroll
-                        mLastTouchX = x;
-                        mLastTouchY = y;
-                        keepScrollBarsVisible = true;
                     }
                     mLastTouchTime = eventTime;
                     mUserScroll = true;
@@ -5937,8 +5928,8 @@
             action = MotionEvent.ACTION_DOWN;
         } else if (action == MotionEvent.ACTION_POINTER_UP) {
             // set mLastTouchX/Y to the remaining point
-            mLastTouchX = x;
-            mLastTouchY = y;
+            mLastTouchX = Math.round(x);
+            mLastTouchY = Math.round(y);
         } else if (action == MotionEvent.ACTION_MOVE) {
             // negative x or y indicate it is on the edge, skip it.
             if (x < 0 || y < 0) {
@@ -5946,7 +5937,7 @@
             }
         }
 
-        return handleTouchEventCommon(ev, x, y);
+        return handleTouchEventCommon(ev, Math.round(x), Math.round(y));
     }
 
     private void cancelWebCoreTouchEvent(int x, int y, boolean removeEvents) {
@@ -5967,8 +5958,8 @@
 
     private void startTouch(float x, float y, long eventTime) {
         // Remember where the motion event started
-        mLastTouchX = x;
-        mLastTouchY = y;
+        mLastTouchX = Math.round(x);
+        mLastTouchY = Math.round(y);
         mLastTouchTime = eventTime;
         mVelocityTracker = VelocityTracker.obtain();
         mSnapScrollMode = SNAP_NONE;
@@ -6598,8 +6589,8 @@
             return;
         }
         // mLastTouchX and mLastTouchY are the point in the current viewport
-        int contentX = viewToContentX((int) mLastTouchX + mScrollX);
-        int contentY = viewToContentY((int) mLastTouchY + mScrollY);
+        int contentX = viewToContentX(mLastTouchX + mScrollX);
+        int contentY = viewToContentY(mLastTouchY + mScrollY);
         Rect rect = new Rect(contentX - mNavSlop, contentY - mNavSlop,
                 contentX + mNavSlop, contentY + mNavSlop);
         nativeSelectBestAt(rect);
@@ -6630,8 +6621,8 @@
         if (!inEditingMode()) {
             return;
         }
-        mLastTouchX = x + (float) (mWebTextView.getLeft() - mScrollX);
-        mLastTouchY = y + (float) (mWebTextView.getTop() - mScrollY);
+        mLastTouchX = Math.round(x + mWebTextView.getLeft() - mScrollX);
+        mLastTouchY = Math.round(y + mWebTextView.getTop() - mScrollY);
         mLastTouchTime = eventTime;
         if (!mScroller.isFinished()) {
             abortAnimation();
@@ -6690,8 +6681,8 @@
         mTouchMode = TOUCH_DONE_MODE;
         switchOutDrawHistory();
         // mLastTouchX and mLastTouchY are the point in the current viewport
-        int contentX = viewToContentX((int) mLastTouchX + mScrollX);
-        int contentY = viewToContentY((int) mLastTouchY + mScrollY);
+        int contentX = viewToContentX(mLastTouchX + mScrollX);
+        int contentY = viewToContentY(mLastTouchY + mScrollY);
         if (getSettings().supportTouchOnly()) {
             removeTouchHighlight(false);
             WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData();
@@ -7052,8 +7043,8 @@
                             || (msg.arg1 == MotionEvent.ACTION_MOVE
                             && mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN)) {
                         cancelWebCoreTouchEvent(
-                                viewToContentX((int) mLastTouchX + mScrollX),
-                                viewToContentY((int) mLastTouchY + mScrollY),
+                                viewToContentX(mLastTouchX + mScrollX),
+                                viewToContentY(mLastTouchY + mScrollY),
                                 true);
                     }
                     break;
@@ -7104,8 +7095,8 @@
                         ted.mIds = new int[1];
                         ted.mIds[0] = 0;
                         ted.mPoints = new Point[1];
-                        ted.mPoints[0] = new Point(viewToContentX((int) mLastTouchX + mScrollX),
-                                                   viewToContentY((int) mLastTouchY + mScrollY));
+                        ted.mPoints[0] = new Point(viewToContentX(mLastTouchX + mScrollX),
+                                                   viewToContentY(mLastTouchY + mScrollY));
                         // metaState for long press is tricky. Should it be the
                         // state when the press started or when the press was
                         // released? Or some intermediary key state? For
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index b4ece24..593cb59 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -25,9 +25,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.List;
-import java.util.Comparator;
 import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
 
 /**
  * A concrete BaseAdapter that is backed by an array of arbitrary
@@ -86,6 +86,8 @@
 
     private Context mContext;
 
+    // A copy of the original mObjects array, initialized from and then used instead as soon as
+    // the mFilter ArrayFilter is used. mObjects will then only contain the filtered values.
     private ArrayList<T> mOriginalValues;
     private ArrayFilter mFilter;
 
@@ -170,15 +172,14 @@
      * @param object The object to add at the end of the array.
      */
     public void add(T object) {
-        if (mOriginalValues != null) {
-            synchronized (mLock) {
+        synchronized (mLock) {
+            if (mOriginalValues != null) {
                 mOriginalValues.add(object);
-                if (mNotifyOnChange) notifyDataSetChanged();
+            } else {
+                mObjects.add(object);
             }
-        } else {
-            mObjects.add(object);
-            if (mNotifyOnChange) notifyDataSetChanged();
         }
+        if (mNotifyOnChange) notifyDataSetChanged();
     }
 
     /**
@@ -187,15 +188,14 @@
      * @param collection The Collection to add at the end of the array.
      */
     public void addAll(Collection<? extends T> collection) {
-        if (mOriginalValues != null) {
-            synchronized (mLock) {
+        synchronized (mLock) {
+            if (mOriginalValues != null) {
                 mOriginalValues.addAll(collection);
-                if (mNotifyOnChange) notifyDataSetChanged();
+            } else {
+                mObjects.addAll(collection);
             }
-        } else {
-            mObjects.addAll(collection);
-            if (mNotifyOnChange) notifyDataSetChanged();
         }
+        if (mNotifyOnChange) notifyDataSetChanged();
     }
 
     /**
@@ -204,19 +204,18 @@
      * @param items The items to add at the end of the array.
      */
     public void addAll(T ... items) {
-        if (mOriginalValues != null) {
-            synchronized (mLock) {
+        synchronized (mLock) {
+            if (mOriginalValues != null) {
                 for (T item : items) {
                     mOriginalValues.add(item);
                 }
-                if (mNotifyOnChange) notifyDataSetChanged();
+            } else {
+                for (T item : items) {
+                    mObjects.add(item);
+                }
             }
-        } else {
-            for (T item : items) {
-                mObjects.add(item);
-            }
-            if (mNotifyOnChange) notifyDataSetChanged();
         }
+        if (mNotifyOnChange) notifyDataSetChanged();
     }
 
     /**
@@ -226,15 +225,14 @@
      * @param index The index at which the object must be inserted.
      */
     public void insert(T object, int index) {
-        if (mOriginalValues != null) {
-            synchronized (mLock) {
+        synchronized (mLock) {
+            if (mOriginalValues != null) {
                 mOriginalValues.add(index, object);
-                if (mNotifyOnChange) notifyDataSetChanged();
+            } else {
+                mObjects.add(index, object);
             }
-        } else {
-            mObjects.add(index, object);
-            if (mNotifyOnChange) notifyDataSetChanged();
         }
+        if (mNotifyOnChange) notifyDataSetChanged();
     }
 
     /**
@@ -243,12 +241,12 @@
      * @param object The object to remove.
      */
     public void remove(T object) {
-        if (mOriginalValues != null) {
-            synchronized (mLock) {
+        synchronized (mLock) {
+            if (mOriginalValues != null) {
                 mOriginalValues.remove(object);
+            } else {
+                mObjects.remove(object);
             }
-        } else {
-            mObjects.remove(object);
         }
         if (mNotifyOnChange) notifyDataSetChanged();
     }
@@ -257,12 +255,12 @@
      * Remove all elements from the list.
      */
     public void clear() {
-        if (mOriginalValues != null) {
-            synchronized (mLock) {
+        synchronized (mLock) {
+            if (mOriginalValues != null) {
                 mOriginalValues.clear();
+            } else {
+                mObjects.clear();
             }
-        } else {
-            mObjects.clear();
         }
         if (mNotifyOnChange) notifyDataSetChanged();
     }
@@ -274,7 +272,13 @@
      *        in this adapter.
      */
     public void sort(Comparator<? super T> comparator) {
-        Collections.sort(mObjects, comparator);
+        synchronized (mLock) {
+            if (mOriginalValues != null) {
+                Collections.sort(mOriginalValues, comparator);
+            } else {
+                Collections.sort(mObjects, comparator);
+            }
+        }
         if (mNotifyOnChange) notifyDataSetChanged();
     }
 
@@ -482,6 +486,7 @@
                         final String[] words = valueText.split(" ");
                         final int wordCount = words.length;
 
+                        // Start at index 0, in case valueText starts with space(s)
                         for (int k = 0; k < wordCount; k++) {
                             if (words[k].startsWith(prefixString)) {
                                 newValues.add(value);
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 4d8d21f..707b92d 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -16,6 +16,8 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.database.DataSetObserver;
@@ -36,8 +38,6 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 
-import com.android.internal.R;
-
 
 /**
  * <p>An editable text view that shows completion suggestions automatically
@@ -113,6 +113,7 @@
 
     private Validator mValidator = null;
 
+    // Set to true when text is set directly and no filtering shall be performed
     private boolean mBlockCompletion;
 
     private PassThroughClickListener mPassThroughClickListener;
@@ -721,6 +722,10 @@
             return;
         }
 
+        updateList();
+    }
+
+    private void updateList() {
         // the drop down is shown only when a minimum number of characters
         // was typed in the text view
         if (enoughToFilter()) {
@@ -840,7 +845,7 @@
 
             mBlockCompletion = true;
             replaceText(convertSelectionToString(selectedItem));
-            mBlockCompletion = false;            
+            mBlockCompletion = false;
 
             if (mItemClickListener != null) {
                 final ListPopupWindow list = mPopup;
@@ -903,10 +908,10 @@
 
     /** {@inheritDoc} */
     public void onFilterComplete(int count) {
-        updateDropDownForFilter(count);
+        updateDropDownForFilter(count, true);
     }
 
-    private void updateDropDownForFilter(int count) {
+    private void updateDropDownForFilter(int count, boolean forceShow) {
         // Not attached to window, don't update drop-down
         if (getWindowVisibility() == View.GONE) return;
 
@@ -919,7 +924,7 @@
 
         final boolean dropDownAlwaysVisible = mPopup.isDropDownAlwaysVisible();
         if ((count > 0 || dropDownAlwaysVisible) && enoughToFilter()) {
-            if (hasFocus() && hasWindowFocus()) {
+            if (hasFocus() && hasWindowFocus() && (forceShow || isPopupShowing())) {
                 showDropDown();
             }
         } else if (!dropDownAlwaysVisible) {
@@ -1182,12 +1187,14 @@
                 // If the popup is not showing already, showing it will cause
                 // the list of data set observers attached to the adapter to
                 // change. We can't do it from here, because we are in the middle
-                // of iterating throught he list of observers.
+                // of iterating through the list of observers.
                 post(new Runnable() {
                     public void run() {
                         final ListAdapter adapter = mAdapter;
                         if (adapter != null) {
-                            updateDropDownForFilter(adapter.getCount());
+                            // This will re-layout, thus resetting mDataChanged, so that the
+                            // listView click listener stays responsive
+                            updateDropDownForFilter(adapter.getCount(), false);
                         }
                     }
                 });
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f023e94..342b884 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -568,6 +568,7 @@
     char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
     char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
     char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
+    char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];
     char extraOptsBuf[PROPERTY_VALUE_MAX];
     char* stackTraceFile = NULL;
     bool checkJni = false;
@@ -659,6 +660,13 @@
     opt.optionString = heapsizeOptsBuf;
     mOptions.add(opt);
 
+    strcpy(heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
+    property_get("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf+20, "");
+    if (heapgrowthlimitOptsBuf[20] != '\0') {
+        opt.optionString = heapgrowthlimitOptsBuf;
+        mOptions.add(opt);
+    }
+
     /*
      * Enable or disable dexopt features, such as bytecode verification and
      * calculation of register maps for precise GC.
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index c43b5ce..2445229 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -154,6 +154,16 @@
         scale_rgn(rgn, *rgn, scale);
 }
 
+static jstring Region_toString(JNIEnv* env, jobject clazz, SkRegion* region) {
+    char* str = region->toString();
+    if (str == NULL) {
+        return NULL;
+    }
+    jstring result = env->NewStringUTF(str);
+    free(str);
+    return result;
+}
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 static SkRegion* Region_createFromParcel(JNIEnv* env, jobject clazz, jobject parcel)
@@ -262,6 +272,7 @@
     { "quickReject",            "(Landroid/graphics/Region;)Z",     (void*)Region_quickRejectRgn    },
     { "scale",                  "(FLandroid/graphics/Region;)V",    (void*)Region_scale             },
     { "translate",              "(IILandroid/graphics/Region;)V",   (void*)Region_translate         },
+    { "nativeToString",         "(I)Ljava/lang/String;",            (void*)Region_toString          },
     // parceling methods
     { "nativeCreateFromParcel", "(Landroid/os/Parcel;)I",           (void*)Region_createFromParcel  },
     { "nativeWriteToParcel",    "(ILandroid/os/Parcel;)Z",          (void*)Region_writeToParcel     },
diff --git a/core/jni/android_bluetooth_common.h b/core/jni/android_bluetooth_common.h
index 9222e1a..3364703 100644
--- a/core/jni/android_bluetooth_common.h
+++ b/core/jni/android_bluetooth_common.h
@@ -38,6 +38,7 @@
 #ifdef HAVE_BLUETOOTH
 #define BLUEZ_DBUS_BASE_PATH      "/org/bluez"
 #define BLUEZ_DBUS_BASE_IFC       "org.bluez"
+#define BLUEZ_ERROR_IFC           "org.bluez.Error"
 
 // It would be nicer to retrieve this from bluez using GetDefaultAdapter,
 // but this is only possible when the adapter is up (and hcid is running).
@@ -171,6 +172,30 @@
 
 bool debug_no_encrypt();
 
+
+// Result codes from Bluez DBus calls
+#define BOND_RESULT_ERROR                      -1
+#define BOND_RESULT_SUCCESS                     0
+#define BOND_RESULT_AUTH_FAILED                 1
+#define BOND_RESULT_AUTH_REJECTED               2
+#define BOND_RESULT_AUTH_CANCELED               3
+#define BOND_RESULT_REMOTE_DEVICE_DOWN          4
+#define BOND_RESULT_DISCOVERY_IN_PROGRESS       5
+#define BOND_RESULT_AUTH_TIMEOUT                6
+#define BOND_RESULT_REPEATED_ATTEMPTS           7
+
+#define PAN_DISCONNECT_FAILED_NOT_CONNECTED  1000
+#define PAN_CONNECT_FAILED_ALREADY_CONNECTED 1001
+#define PAN_CONNECT_FAILED_ATTEMPT_FAILED    1002
+#define PAN_OPERATION_GENERIC_FAILURE        1003
+#define PAN_OPERATION_SUCCESS                1004
+
+#define INPUT_DISCONNECT_FAILED_NOT_CONNECTED  5000
+#define INPUT_CONNECT_FAILED_ALREADY_CONNECTED 5001
+#define INPUT_CONNECT_FAILED_ATTEMPT_FAILED    5002
+#define INPUT_OPERATION_GENERIC_FAILURE        5003
+#define INPUT_OPERATION_SUCCESS                5004
+
 #endif
 } /* namespace android */
 
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index b0ba695..fd12c2d7 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -134,11 +134,11 @@
     method_onInputDevicePropertyChanged = env->GetMethodID(clazz, "onInputDevicePropertyChanged",
                                                "(Ljava/lang/String;[Ljava/lang/String;)V");
     method_onInputDeviceConnectionResult = env->GetMethodID(clazz, "onInputDeviceConnectionResult",
-                                               "(Ljava/lang/String;Z)V");
+                                               "(Ljava/lang/String;I)V");
     method_onPanDevicePropertyChanged = env->GetMethodID(clazz, "onPanDevicePropertyChanged",
                                                "(Ljava/lang/String;[Ljava/lang/String;)V");
     method_onPanDeviceConnectionResult = env->GetMethodID(clazz, "onPanDeviceConnectionResult",
-                                               "(Ljava/lang/String;Z)V");
+                                               "(Ljava/lang/String;I)V");
     method_onRequestOobData = env->GetMethodID(clazz, "onRequestOobData",
                                                "(Ljava/lang/String;I)V");
 
@@ -1227,16 +1227,6 @@
 
 
 #ifdef HAVE_BLUETOOTH
-//TODO: Unify result codes in a header
-#define BOND_RESULT_ERROR -1000
-#define BOND_RESULT_SUCCESS 0
-#define BOND_RESULT_AUTH_FAILED 1
-#define BOND_RESULT_AUTH_REJECTED 2
-#define BOND_RESULT_AUTH_CANCELED 3
-#define BOND_RESULT_REMOTE_DEVICE_DOWN 4
-#define BOND_RESULT_DISCOVERY_IN_PROGRESS 5
-#define BOND_RESULT_AUTH_TIMEOUT 6
-#define BOND_RESULT_REPEATED_ATTEMPTS 7
 
 void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) {
     LOGV(__FUNCTION__);
@@ -1406,11 +1396,25 @@
     JNIEnv *env;
     nat->vm->GetEnv((void**)&env, nat->envVer);
 
-    bool result = JNI_TRUE;
+    jint result = INPUT_OPERATION_SUCCESS;
     if (dbus_set_error_from_message(&err, msg)) {
+        if (!strcmp(err.name, BLUEZ_ERROR_IFC ".ConnectionAttemptFailed")) {
+            result = INPUT_CONNECT_FAILED_ATTEMPT_FAILED;
+        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".AlreadyConnected")) {
+            result = INPUT_CONNECT_FAILED_ALREADY_CONNECTED;
+        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".Failed")) {
+            // TODO():This is flaky, need to change Bluez to add new error codes
+            if (!strcmp(err.message, "Transport endpoint is not connected")) {
+              result = INPUT_DISCONNECT_FAILED_NOT_CONNECTED;
+            } else {
+              result = INPUT_OPERATION_GENERIC_FAILURE;
+            }
+        } else {
+            result = INPUT_OPERATION_GENERIC_FAILURE;
+        }
         LOG_AND_FREE_DBUS_ERROR(&err);
-        result = JNI_FALSE;
     }
+
     LOGV("... Device Path = %s, result = %d", path, result);
     jstring jPath = env->NewStringUTF(path);
     env->CallVoidMethod(nat->me,
@@ -1431,11 +1435,25 @@
     JNIEnv *env;
     nat->vm->GetEnv((void**)&env, nat->envVer);
 
-    bool result = JNI_TRUE;
+    jint result = PAN_OPERATION_SUCCESS;
     if (dbus_set_error_from_message(&err, msg)) {
+        if (!strcmp(err.name, BLUEZ_ERROR_IFC ".ConnectionAttemptFailed")) {
+            result = PAN_CONNECT_FAILED_ATTEMPT_FAILED;
+        } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".Failed")) {
+            // TODO():This is flaky, need to change Bluez to add new error codes
+            if (!strcmp(err.message, "Device already connected")) {
+                result = PAN_CONNECT_FAILED_ALREADY_CONNECTED;
+            } else if (!strcmp(err.message, "Device not connected")) {
+                result = PAN_DISCONNECT_FAILED_NOT_CONNECTED;
+            } else {
+                result = PAN_OPERATION_GENERIC_FAILURE;
+            }
+        } else {
+            result = PAN_OPERATION_GENERIC_FAILURE;
+        }
         LOG_AND_FREE_DBUS_ERROR(&err);
-        result = JNI_FALSE;
     }
+
     LOGV("... Pan Device Path = %s, result = %d", path, result);
     jstring jPath = env->NewStringUTF(path);
     env->CallVoidMethod(nat->me,
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index 75edac6..ddbd220 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -382,7 +382,7 @@
     }
 
     data.writeInt32(playbackStatus);
-    data.writeInt32(position);
+    data.writeInt64(position);
 
     remote()->transact(SET_PLAYBACK_STATUS, data, &reply);
     return reply.readInt32();
@@ -1111,7 +1111,7 @@
         }
 
         const status_t status
-            = setPlaybackStatus(uniqueId, &handle, data.readInt32(), data.readInt32());
+            = setPlaybackStatus(uniqueId, &handle, data.readInt32(), data.readInt64());
         reply->writeInt32(status);
 
         delete handle.decryptInfo; handle.decryptInfo = NULL;
diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java
index e540806..27ea0f0 100644
--- a/graphics/java/android/graphics/Region.java
+++ b/graphics/java/android/graphics/Region.java
@@ -287,6 +287,10 @@
                         region2.mNativeRegion, op.nativeInt);
     }
 
+    public String toString() {
+        return nativeToString(mNativeRegion);
+    }
+
     //////////////////////////////////////////////////////////////////////////
     
     public static final Parcelable.Creator<Region> CREATOR
@@ -357,6 +361,8 @@
         return mNativeRegion;
     }
 
+    private static native boolean nativeEquals(int native_r1, int native_r2);
+
     private static native int nativeConstructor();
     private static native void nativeDestructor(int native_region);
 
@@ -381,5 +387,5 @@
     private static native boolean nativeWriteToParcel(int native_region,
                                                       Parcel p);
 
-    private static native boolean nativeEquals(int native_r1, int native_r2);
+    private static native String nativeToString(int native_region);
 }
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index c080501..c43e40d 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -298,8 +298,10 @@
 // FontRenderer
 ///////////////////////////////////////////////////////////////////////////////
 
+static bool sLogFontRendererCreate = true;
+
 FontRenderer::FontRenderer() {
-    LOGD("Creating FontRenderer");
+    if (sLogFontRendererCreate) LOGD("Creating FontRenderer");
 
     mGammaTable = NULL;
     mInitialized = false;
@@ -317,18 +319,24 @@
 
     char property[PROPERTY_VALUE_MAX];
     if (property_get(PROPERTY_TEXT_CACHE_WIDTH, property, NULL) > 0) {
-        LOGD("  Setting text cache width to %s pixels", property);
+        if (sLogFontRendererCreate) LOGD("  Setting text cache width to %s pixels", property);
         mCacheWidth = atoi(property);
     } else {
-        LOGD("  Using default text cache width of %i pixels", mCacheWidth);
+        if (sLogFontRendererCreate) {
+            LOGD("  Using default text cache width of %i pixels", mCacheWidth);
+        }
     }
 
     if (property_get(PROPERTY_TEXT_CACHE_HEIGHT, property, NULL) > 0) {
-        LOGD("  Setting text cache width to %s pixels", property);
+        if (sLogFontRendererCreate) LOGD("  Setting text cache width to %s pixels", property);
         mCacheHeight = atoi(property);
     } else {
-        LOGD("  Using default text cache height of %i pixels", mCacheHeight);
+        if (sLogFontRendererCreate) {
+            LOGD("  Using default text cache height of %i pixels", mCacheHeight);
+        }
     }
+
+    sLogFontRendererCreate = false;
 }
 
 FontRenderer::~FontRenderer() {
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index e6bea78..a167429 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -29,7 +29,6 @@
 void LayerRenderer::prepare(bool opaque) {
     LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo);
 
-    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &mPreviousFbo);
     glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo);
 
     OpenGLRenderer::prepare(opaque);
@@ -37,11 +36,17 @@
 
 void LayerRenderer::finish() {
     OpenGLRenderer::finish();
-    glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFbo);
 
     generateMesh();
 
     LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->mFbo);
+
+    // No need to unbind our FBO, this will be taken care of by the caller
+    // who will invoke OpenGLRenderer::resume()
+}
+
+GLint LayerRenderer::getTargetFbo() {
+    return mLayer->fbo;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index f2fb898..1e39847 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -51,6 +51,7 @@
 
     bool hasLayer();
     Region* getRegion();
+    GLint getTargetFbo();
 
     static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
     static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
@@ -61,8 +62,6 @@
     void generateMesh();
 
     Layer* mLayer;
-    GLuint mPreviousFbo;
-
 }; // class LayerRenderer
 
 }; // namespace uirenderer
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 2067acc1..6477eb0 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -200,7 +200,7 @@
 
     glDisable(GL_DITHER);
 
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
     mCaches.blend = true;
@@ -430,18 +430,18 @@
     } else {
         // Copy the framebuffer into the layer
         glBindTexture(GL_TEXTURE_2D, layer->texture);
-
-        if (layer->empty) {
-            glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left,
-                    snapshot->height - bounds.bottom, layer->width, layer->height, 0);
-            layer->empty = false;
-        } else {
-            glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left,
-                    snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
+        if (!bounds.isEmpty()) {
+            if (layer->empty) {
+                glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left,
+                        snapshot->height - bounds.bottom, layer->width, layer->height, 0);
+                layer->empty = false;
+            } else {
+                glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left,
+                        snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
+            }
+            // Enqueue the buffer coordinates to clear the corresponding region later
+            mLayers.push(new Rect(bounds));
         }
-
-        // Enqueue the buffer coordinates to clear the corresponding region later
-        mLayers.push(new Rect(bounds));
     }
 
     return true;
@@ -565,8 +565,10 @@
             resetColorFilter();
         }
     } else {
-        dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
-        composeLayerRect(layer, rect, true);
+        if (!rect.isEmpty()) {
+            dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
+            composeLayerRect(layer, rect, true);
+        }
     }
 
     if (fboLayer) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 272c5c2..4150ddc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -145,14 +145,27 @@
         return mSnapshot;
     }
 
+    /**
+     * Returns the region of the current layer.
+     */
     virtual Region* getRegion() {
         return mSnapshot->region;
     }
 
+    /**
+     * Indicates whether rendering is currently targeted at a layer.
+     */
     virtual bool hasLayer() {
         return (mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region;
     }
 
+    /**
+     * Returns the name of the FBO this renderer is rendering into.
+     */
+    virtual GLint getTargetFbo() {
+        return 0;
+    }
+
 private:
     /**
      * Saves the current state of the renderer as a new snapshot.
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index b03588f..1c02878 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -93,29 +93,28 @@
      *
      * @throws IOException
      */
-    public MediaImageItem(VideoEditor editor, String mediaItemId,
-                         String filename, long durationMs,
-                         int renderingMode) throws IOException {
+    public MediaImageItem(VideoEditor editor, String mediaItemId, String filename, long durationMs,
+        int renderingMode) throws IOException {
 
         super(editor, mediaItemId, filename, renderingMode);
 
         mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext();
         mVideoEditor = ((VideoEditorImpl)editor);
         try {
-            final Properties properties =
-                                   mMANativeHelper.getMediaProperties(filename);
+            final Properties properties = mMANativeHelper.getMediaProperties(filename);
 
             switch (mMANativeHelper.getFileType(properties.fileType)) {
                 case MediaProperties.FILE_JPEG:
+                case MediaProperties.FILE_PNG: {
                     break;
-                case MediaProperties.FILE_PNG:
-                    break;
+                }
 
-                default:
-                throw new IllegalArgumentException("Unsupported Input File Type");
+                default: {
+                    throw new IllegalArgumentException("Unsupported Input File Type");
+                }
             }
         } catch (Exception e) {
-            throw new IllegalArgumentException("Unsupported file or file not found");
+            throw new IllegalArgumentException("Unsupported file or file not found: " + filename);
         }
 
         /**
@@ -130,13 +129,13 @@
         mDurationMs = durationMs;
         mDecodedFilename = String.format(mMANativeHelper.getProjectPath() +
                 "/" + "decoded" + getId()+ ".rgb");
-        final FileOutputStream fl = new FileOutputStream(mDecodedFilename);
-        final DataOutputStream dos = new DataOutputStream(fl);
+
         try {
             mAspectRatio = mMANativeHelper.getAspectRatio(mWidth, mHeight);
         } catch(IllegalArgumentException e) {
             throw new IllegalArgumentException ("Null width and height");
         }
+
         mGeneratedClipHeight = 0;
         mGeneratedClipWidth = 0;
 
@@ -146,9 +145,12 @@
          */
         final Pair<Integer, Integer>[] resolutions =
             MediaProperties.getSupportedResolutions(mAspectRatio);
+
         /**
          *  Get the highest resolution
          */
+        final FileOutputStream fl = new FileOutputStream(mDecodedFilename);
+        final DataOutputStream dos = new DataOutputStream(fl);
         final Pair<Integer, Integer> maxResolution = resolutions[resolutions.length - 1];
         if (mHeight > maxResolution.second) {
             /**
@@ -171,16 +173,16 @@
             int mNewHeight = 0;
             if ((mScaledWidth % 2 ) != 0) {
                 mNewWidth = mScaledWidth - 1;
-            }
-            else {
+            } else {
                 mNewWidth = mScaledWidth;
             }
+
             if ((mScaledHeight % 2 ) != 0) {
                 mNewHeight = mScaledHeight - 1;
-            }
-            else {
+            } else {
                 mNewHeight = mScaledHeight;
             }
+
             final int [] framingBuffer = new int[mNewWidth];
             final ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
             IntBuffer intBuffer;
@@ -195,6 +197,7 @@
                 dos.write(array);
                 tmp += 1;
             }
+
             mScaledWidth = mNewWidth;
             mScaledHeight = mNewHeight;
             scaledImage.recycle();
@@ -204,10 +207,11 @@
                                 + "/" + "scaled" + getId()+ ".JPG");
             if (!((new File(mScaledFilename)).exists())) {
                 super.mRegenerateClip = true;
-                FileOutputStream f1 = new FileOutputStream(mScaledFilename);
+                final FileOutputStream f1 = new FileOutputStream(mScaledFilename);
                 scaledImage.compress(Bitmap.CompressFormat.JPEG, 50,f1);
                 f1.close();
             }
+
             mScaledWidth = scaledImage.getWidth();
             mScaledHeight = scaledImage.getHeight();
 
@@ -215,17 +219,17 @@
             int mNewheight = 0;
             if ((mScaledWidth % 2 ) != 0) {
                 mNewWidth = mScaledWidth - 1;
-            }
-            else {
+            } else {
                 mNewWidth = mScaledWidth;
             }
+
             if ((mScaledHeight % 2 ) != 0) {
                 mNewheight = mScaledHeight - 1;
-            }
-            else {
+            } else {
                 mNewheight = mScaledHeight;
             }
-            Bitmap imageBitmap = BitmapFactory.decodeFile(mScaledFilename);
+
+            final Bitmap imageBitmap = BitmapFactory.decodeFile(mScaledFilename);
             final int [] framingBuffer = new int[mNewWidth];
             ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
             IntBuffer intBuffer;
@@ -240,10 +244,12 @@
                 dos.write(array);
                 tmp += 1;
             }
+
             mScaledWidth = mNewWidth;
             mScaledHeight = mNewheight;
             imageBitmap.recycle();
         }
+
         fl.close();
         System.gc();
     }
@@ -286,7 +292,7 @@
 
     /**
      * @return The file name of image which is decoded and stored
-     * in rgb format
+     * in RGB format
      */
     String getDecodedImageFileName() {
         return mDecodedFilename;
@@ -447,7 +453,7 @@
                  *  Check if the effect overlaps with the end transition
                  */
                 if (effect.getStartTime() + effect.getDuration() >
-                mDurationMs - transitionDurationMs) {
+                    mDurationMs - transitionDurationMs) {
                     mEndTransition.invalidate();
                     break;
                 }
@@ -464,7 +470,7 @@
                      *  Check if the overlay overlaps with the end transition
                      */
                     if (overlay.getStartTime() + overlay.getDuration() >
-                    mDurationMs - transitionDurationMs) {
+                        mDurationMs - transitionDurationMs) {
                         mEndTransition.invalidate();
                         break;
                     }
@@ -648,23 +654,24 @@
             for (int i = 0; i < thumbnailCount; i++) {
                 thumbnailArray[i] = thumbnail;
             }
+
             return thumbnailArray;
-
-
-        }
-        else {
+        } else {
             if (startMs > endMs) {
                 throw new IllegalArgumentException("Start time is greater than end time");
             }
+
             if (endMs > mDurationMs) {
                 throw new IllegalArgumentException("End time is greater than file duration");
             }
+
             if (startMs == endMs) {
                 Bitmap[] bitmap = new Bitmap[1];
                 bitmap[0] = mMANativeHelper.getPixels(getGeneratedImageClip(),
                     width, height,startMs);
                 return bitmap;
             }
+
             return mMANativeHelper.getPixelsList(getGeneratedImageClip(), width,
                 height,startMs,endMs,thumbnailCount);
         }
@@ -704,31 +711,51 @@
          */
         if (mBeginTransition != null) {
             final long transitionDurationMs = mBeginTransition.getDuration();
+            final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs, 0,
+                    transitionDurationMs);
+            final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs, 0,
+                    transitionDurationMs);
             /**
-             *  If the start time has changed and if the old or the new item
-             *  overlaps with the begin transition, invalidate the transition.
+             * Invalidate transition if:
+             *
+             * 1. New item overlaps the transition, the old one did not
+             * 2. New item does not overlap the transition, the old one did
+             * 3. New and old item overlap the transition if begin or end
+             * time changed
              */
-            if (((oldStartTimeMs != newStartTimeMs)
-                    || (oldDurationMs != newDurationMs) )&&
-                    (isOverlapping(oldStartTimeMs, oldDurationMs, 0, transitionDurationMs) ||
-                    isOverlapping(newStartTimeMs, newDurationMs, 0,
-                    transitionDurationMs))) {
+            if (newOverlap != oldOverlap) { // Overlap has changed
                 mBeginTransition.invalidate();
+            } else if (newOverlap) { // Both old and new overlap
+                if ((oldStartTimeMs != newStartTimeMs) ||
+                        !(oldStartTimeMs + oldDurationMs > transitionDurationMs &&
+                        newStartTimeMs + newDurationMs > transitionDurationMs)) {
+                    mBeginTransition.invalidate();
+                }
             }
         }
 
         if (mEndTransition != null) {
             final long transitionDurationMs = mEndTransition.getDuration();
+            final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs,
+                    mDurationMs - transitionDurationMs, transitionDurationMs);
+            final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs,
+                    mDurationMs - transitionDurationMs, transitionDurationMs);
             /**
-             *  If the start time + duration has changed and if the old or the new
-             *  item overlaps the end transition, invalidate the transition
+             * Invalidate transition if:
+             *
+             * 1. New item overlaps the transition, the old one did not
+             * 2. New item does not overlap the transition, the old one did
+             * 3. New and old item overlap the transition if begin or end
+             * time changed
              */
-            if (oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs &&
-                    (isOverlapping(oldStartTimeMs, oldDurationMs,
-                    mDurationMs - transitionDurationMs, transitionDurationMs) ||
-                    isOverlapping(newStartTimeMs, newDurationMs,
-                    mDurationMs - transitionDurationMs, transitionDurationMs))) {
+            if (newOverlap != oldOverlap) { // Overlap has changed
                 mEndTransition.invalidate();
+            } else if (newOverlap) { // Both old and new overlap
+                if ((oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs) ||
+                        ((oldStartTimeMs > mDurationMs - transitionDurationMs) ||
+                        newStartTimeMs > mDurationMs - transitionDurationMs)) {
+                    mEndTransition.invalidate();
+                }
             }
         }
     }
@@ -743,10 +770,12 @@
             setGeneratedImageClip(null);
             setRegenerateClip(true);
         }
+
         if (mScaledFilename != null) {
             new File(mScaledFilename).delete();
             mScaledFilename = null;
         }
+
         if (mDecodedFilename != null) {
             new File(mDecodedFilename).delete();
             mDecodedFilename = null;
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index 772b360..2981b41 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -78,12 +78,9 @@
      *
      * @throws IOException if the file cannot be opened for reading
      */
-    public MediaVideoItem(VideoEditor editor, String mediaItemId,
-            String filename,
-            int renderingMode)
-    throws IOException {
-        this(editor, mediaItemId, filename, renderingMode, 0, END_OF_FILE,
-                100, false, null);
+    public MediaVideoItem(VideoEditor editor, String mediaItemId, String filename,
+            int renderingMode) throws IOException {
+        this(editor, mediaItemId, filename, renderingMode, 0, END_OF_FILE, 100, false, null);
     }
 
     /**
@@ -105,20 +102,22 @@
      * @throws IOException if the file cannot be opened for reading
      */
     MediaVideoItem(VideoEditor editor, String mediaItemId, String filename,
-            int renderingMode,
-            long beginMs, long endMs, int volumePercent, boolean muted,
+            int renderingMode, long beginMs, long endMs, int volumePercent, boolean muted,
             String audioWaveformFilename)  throws IOException {
         super(editor, mediaItemId, filename, renderingMode);
+
         if (editor instanceof VideoEditorImpl) {
             mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext();
             mVideoEditor = ((VideoEditorImpl)editor);
         }
-        Properties properties = null;
+
+        final Properties properties;
         try {
              properties = mMANativeHelper.getMediaProperties(filename);
         } catch ( Exception e) {
-            throw new IllegalArgumentException("Unsupported file or file not found");
+            throw new IllegalArgumentException("Unsupported file or file not found: " + filename);
         }
+
         switch (mMANativeHelper.getFileType(properties.fileType)) {
             case MediaProperties.FILE_3GP:
                 break;
@@ -163,8 +162,7 @@
         mMuted = muted;
         mAudioWaveformFilename = audioWaveformFilename;
         if (audioWaveformFilename != null) {
-            mWaveformData =
-                new SoftReference<WaveformData>(
+            mWaveformData = new SoftReference<WaveformData>(
                         new WaveformData(audioWaveformFilename));
         } else {
             mWaveformData = null;
@@ -190,9 +188,11 @@
         if (beginMs > mDurationMs) {
             throw new IllegalArgumentException("setExtractBoundaries: Invalid start time");
         }
+
         if (endMs > mDurationMs) {
             throw new IllegalArgumentException("setExtractBoundaries: Invalid end time");
         }
+
         if ((endMs != -1) && (beginMs >= endMs) ) {
             throw new IllegalArgumentException("setExtractBoundaries: Start time is greater than end time");
         }
@@ -255,18 +255,18 @@
      */
     @Override
     public Bitmap getThumbnail(int width, int height, long timeMs) {
-        if (timeMs > mDurationMs)
-        {
+        if (timeMs > mDurationMs) {
             throw new IllegalArgumentException("Time Exceeds duration");
         }
-        if (timeMs < 0)
-        {
+
+        if (timeMs < 0) {
             throw new IllegalArgumentException("Invalid Time duration");
         }
-        if ((width <=0) || (height <= 0))
-        {
+
+        if ((width <=0) || (height <= 0)) {
             throw new IllegalArgumentException("Invalid Dimensions");
         }
+
         return mMANativeHelper.getPixels(super.getFilename(),
                 width, height,timeMs);
     }
@@ -280,18 +280,21 @@
         if (startMs > endMs) {
             throw new IllegalArgumentException("Start time is greater than end time");
         }
+
         if (endMs > mDurationMs) {
             throw new IllegalArgumentException("End time is greater than file duration");
         }
+
         if ((height <= 0) || (width <= 0)) {
             throw new IllegalArgumentException("Invalid dimension");
         }
+
         if (startMs == endMs) {
-            Bitmap[] bitmap = new Bitmap[1];
-            bitmap[0] = mMANativeHelper.getPixels(super.getFilename(),
-                    width, height,startMs);
+            final Bitmap[] bitmap = new Bitmap[1];
+            bitmap[0] = mMANativeHelper.getPixels(super.getFilename(), width, height,startMs);
             return bitmap;
         }
+
         return mMANativeHelper.getPixelsList(super.getFilename(), width,
                 height,startMs,endMs,thumbnailCount);
     }
@@ -324,40 +327,58 @@
      * {@inheritDoc}
      */
     @Override
-    void invalidateTransitions(long oldStartTimeMs, long oldDurationMs,
-            long newStartTimeMs,
+    void invalidateTransitions(long oldStartTimeMs, long oldDurationMs, long newStartTimeMs,
             long newDurationMs) {
         /**
          *  Check if the item overlaps with the beginning and end transitions
          */
         if (mBeginTransition != null) {
             final long transitionDurationMs = mBeginTransition.getDuration();
+            final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs,
+                    mBeginBoundaryTimeMs, transitionDurationMs);
+            final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs,
+                    mBeginBoundaryTimeMs, transitionDurationMs);
             /**
-             *  If the start time has changed and if the old or the new item
-             *  overlaps with the begin transition, invalidate the transition.
+             * Invalidate transition if:
+             *
+             * 1. New item overlaps the transition, the old one did not
+             * 2. New item does not overlap the transition, the old one did
+             * 3. New and old item overlap the transition if begin or end
+             * time changed
              */
-            if (((oldStartTimeMs != newStartTimeMs)
-                    || (oldDurationMs != newDurationMs) )&&
-                    (isOverlapping(oldStartTimeMs, oldDurationMs,
-                            mBeginBoundaryTimeMs, transitionDurationMs) ||
-                            isOverlapping(newStartTimeMs, newDurationMs,
-                                    mBeginBoundaryTimeMs, transitionDurationMs))) {
+            if (newOverlap != oldOverlap) { // Overlap has changed
                 mBeginTransition.invalidate();
+            } else if (newOverlap) { // Both old and new overlap
+                if ((oldStartTimeMs != newStartTimeMs) ||
+                        !(oldStartTimeMs + oldDurationMs > transitionDurationMs &&
+                        newStartTimeMs + newDurationMs > transitionDurationMs)) {
+                    mBeginTransition.invalidate();
+                }
             }
         }
 
         if (mEndTransition != null) {
             final long transitionDurationMs = mEndTransition.getDuration();
+            final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs,
+                    mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs);
+            final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs,
+                    mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs);
             /**
-             *  If the start time + duration has changed and if the old or the new
-             *  item overlaps the end transition, invalidate the transition
+             * Invalidate transition if:
+             *
+             * 1. New item overlaps the transition, the old one did not
+             * 2. New item does not overlap the transition, the old one did
+             * 3. New and old item overlap the transition if begin or end
+             * time changed
              */
-            if (oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs &&
-                    (isOverlapping(oldStartTimeMs, oldDurationMs,
-                            mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs) ||
-                            isOverlapping(newStartTimeMs, newDurationMs,
-                                    mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs))) {
+            if (newOverlap != oldOverlap) { // Overlap has changed
                 mEndTransition.invalidate();
+            } else if (newOverlap) { // Both old and new overlap
+                if ((oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs) ||
+                        ((oldStartTimeMs > mEndBoundaryTimeMs - transitionDurationMs) ||
+                        newStartTimeMs > mEndBoundaryTimeMs - transitionDurationMs)) {
+                    mEndTransition.invalidate();
+                }
             }
         }
     }
@@ -434,7 +455,7 @@
             throw new IllegalArgumentException("requested time not correct");
         }
 
-        Surface surface = surfaceHolder.getSurface();
+        final Surface surface = surfaceHolder.getSurface();
         if (surface == null) {
             throw new RuntimeException("Surface could not be retrieved from Surface holder");
         }
@@ -442,8 +463,7 @@
         if (mFilename != null) {
             return mMANativeHelper.renderMediaItemPreviewFrame(surface,
                     mFilename,timeMs,mWidth,mHeight);
-        }
-        else {
+        } else {
             return 0;
         }
     }
@@ -462,7 +482,7 @@
      *             Audio track
      */
     public void extractAudioWaveform(ExtractAudioWaveformProgressListener listener)
-    throws IOException {
+        throws IOException {
         int frameDuration = 0;
         int sampleCount = 0;
         final String projectPath = mMANativeHelper.getProjectPath();
@@ -481,19 +501,17 @@
              * Logic to get frame duration = (no. of frames per sample * 1000)/
              * sampling frequency
              */
-            if ( mMANativeHelper.getAudioCodecType(mAudioType) ==
+            if (mMANativeHelper.getAudioCodecType(mAudioType) ==
                 MediaProperties.ACODEC_AMRNB ) {
                 frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRNB*1000)/
                 MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
                 sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRNB;
-            }
-            else if ( mMANativeHelper.getAudioCodecType(mAudioType) ==
+            } else if (mMANativeHelper.getAudioCodecType(mAudioType) ==
                 MediaProperties.ACODEC_AMRWB ) {
                 frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRWB * 1000)/
                 MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
                 sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRWB;
-            }
-            else if ( mMANativeHelper.getAudioCodecType(mAudioType) ==
+            } else if (mMANativeHelper.getAudioCodecType(mAudioType) ==
                 MediaProperties.ACODEC_AAC_LC ) {
                 frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AAC * 1000)/
                 MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
@@ -682,5 +700,4 @@
 
         return clipSettings;
     }
-
 }
diff --git a/media/jni/mediaeditor/Android.mk b/media/jni/mediaeditor/Android.mk
index 27c41be..0a01fb2 100755
--- a/media/jni/mediaeditor/Android.mk
+++ b/media/jni/mediaeditor/Android.mk
@@ -85,6 +85,6 @@
 # to add this library to the prelink map and set this to true.
 LOCAL_PRELINK_MODULE := false
 
-LOCAL_MODULE_TAGS := eng development
+LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 58c4a2e..11ac56c 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -58,6 +58,8 @@
 
 static int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
 static int64_t kHighWaterMarkUs = 10000000ll;  // 10secs
+static const size_t kLowWaterMarkBytes = 40000;
+static const size_t kHighWaterMarkBytes = 200000;
 
 struct AwesomeEvent : public TimedEventQueue::Event {
     AwesomeEvent(
@@ -610,9 +612,6 @@
                 // We don't know the bitrate of the stream, use absolute size
                 // limits to maintain the cache.
 
-                const size_t kLowWaterMarkBytes = 40000;
-                const size_t kHighWaterMarkBytes = 200000;
-
                 if ((mFlags & PLAYING) && !eos
                         && (cachedDataRemaining < kLowWaterMarkBytes)) {
                     LOGI("cache is running low (< %d) , pausing.",
@@ -1535,6 +1534,34 @@
         mConnectingDataSource.clear();
 
         dataSource = mCachedSource;
+
+        // We're going to prefill the cache before trying to instantiate
+        // the extractor below, as the latter is an operation that otherwise
+        // could block on the datasource for a significant amount of time.
+        // During that time we'd be unable to abort the preparation phase
+        // without this prefill.
+
+        mLock.unlock();
+
+        for (;;) {
+            status_t finalStatus;
+            size_t cachedDataRemaining =
+                mCachedSource->approxDataRemaining(&finalStatus);
+
+            if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
+                    || (mFlags & PREPARE_CANCELLED)) {
+                break;
+            }
+
+            usleep(200000);
+        }
+
+        mLock.lock();
+
+        if (mFlags & PREPARE_CANCELLED) {
+            LOGI("Prepare cancelled while waiting for initial cache fill.");
+            return UNKNOWN_ERROR;
+        }
     } else if (!strncasecmp(mUri.string(), "httplive://", 11)) {
         String8 uri("http://");
         uri.append(mUri.string() + 11);
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 06c4c98..a47ee3a 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -590,6 +590,7 @@
 
     status_t err = OK;
     int64_t maxDurationUs = 0;
+    int64_t minDurationUs = 0x7fffffffffffffffLL;
     for (List<Track *>::iterator it = mTracks.begin();
          it != mTracks.end(); ++it) {
         status_t status = (*it)->stop();
@@ -601,6 +602,14 @@
         if (durationUs > maxDurationUs) {
             maxDurationUs = durationUs;
         }
+        if (durationUs < minDurationUs) {
+            minDurationUs = durationUs;
+        }
+    }
+
+    if (mTracks.size() > 1) {
+        LOGD("Duration from tracks range is [%lld, %lld] us",
+            minDurationUs, maxDurationUs);
     }
 
     stopWriterThread();
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 20f1655..741aa1c 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
 #define LOG_TAG "NuCachedSource2"
 #include <utils/Log.h>
 
@@ -487,4 +488,5 @@
 String8 NuCachedSource2::getUri() {
     return mSource->getUri();
 }
+
 }  // namespace android
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml
index 0533b6f..852b729 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml
@@ -78,15 +78,14 @@
             </LinearLayout>
 
             <!-- fake space bar zone -->
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/fake_space_bar"
+            <com.android.systemui.statusbar.policy.EventHole android:id="@+id/fake_space_bar"
                 android:layout_height="match_parent"
-                android:layout_width="match_parent"
+                android:layout_width="0dp"
                 android:paddingLeft="8dip"
                 android:paddingRight="8dip"
                 android:layout_toRightOf="@+id/navigationArea"
                 android:layout_toLeftOf="@+id/notificationArea"
                 android:visibility="gone"
-                systemui:keyCode="62"
                 />
         </RelativeLayout>
     </FrameLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java
new file mode 100644
index 0000000..47e758c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Region;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.ServiceManager;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.HapticFeedbackConstants;
+import android.view.IWindowManager;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewTreeObserver;
+import android.widget.RemoteViews.RemoteView;
+
+import com.android.systemui.R;
+
+public class EventHole extends View implements ViewTreeObserver.OnComputeInternalInsetsListener {
+    private static final String TAG = "StatusBar.EventHole";
+
+    private boolean mWindowVis;
+    private int[] mLoc = new int[2];
+
+    public EventHole(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public EventHole(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onWindowVisibilityChanged(int visibility) {
+        super.onWindowVisibilityChanged(visibility);
+        mWindowVis = visibility == View.VISIBLE;
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        getViewTreeObserver().addOnComputeInternalInsetsListener(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
+    }
+
+    public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
+        final boolean visible = isShown() && mWindowVis && getWidth() > 0 && getHeight() > 0;
+        final int[] loc = mLoc;
+        getLocationInWindow(loc);
+        final int l = loc[0];
+        final int r = l + getWidth();
+        final int t = loc[1];
+        final int b = t + getHeight();
+        
+        View top = this;
+        while (top.getParent() instanceof View) {
+            top = (View)top.getParent();
+        }
+
+        if (visible) {
+            info.setTouchableInsets(
+                    ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+            info.touchableRegion.set(0, 0, top.getWidth(), top.getHeight());
+            info.touchableRegion.op(l, t, r, b, Region.Op.DIFFERENCE);
+        } else {
+            info.setTouchableInsets(
+                    ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
+        }
+    }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 45a22b6..800f4b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -52,7 +52,7 @@
     View mNotificationScroller;
     View mNotificationGlow;
     ViewGroup mContentFrame;
-    Rect mContentArea;
+    Rect mContentArea = new Rect();
     View mSettingsView;
     View mScrim, mGlow;
     ViewGroup mContentParent;
@@ -136,7 +136,6 @@
     @Override
     public void onSizeChanged(int w, int h, int oldw, int oldh) {
         super.onSizeChanged(w, h, oldw, oldh);
-        mContentArea = null;
     }
 
     public void onClick(View v) {
@@ -165,13 +164,11 @@
     }
 
     public boolean isInContentArea(int x, int y) {
-        if (mContentArea == null) {
-            mContentArea = new Rect(mContentFrame.getLeft(),
-                    mTitleArea.getTop(),
-                    mContentFrame.getRight(),
-                    mContentFrame.getBottom());
-            offsetDescendantRectToMyCoords(mContentParent, mContentArea);
-        }
+        mContentArea.left = mContentFrame.getLeft();
+        mContentArea.top = mTitleArea.getTop();
+        mContentArea.right = mContentFrame.getRight();
+        mContentArea.bottom = mContentFrame.getBottom();
+        offsetDescendantRectToMyCoords(mContentParent, mContentArea);
         return mContentArea.contains(x, y);
     }
 
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 3e930ae..bbb2228 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -583,7 +583,7 @@
         void broadcastDragStartedLw(final float touchX, final float touchY) {
             // Cache a base-class instance of the clip metadata so that parceling
             // works correctly in calling out to the apps.
-            mDataDescription = mData.getDescription();
+            mDataDescription = (mData != null) ? mData.getDescription() : null;
             mNotifiedWindows.clear();
             mDragInProgress = true;
 
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 2ef85d5..9e9a4f2 100755
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6817,6 +6817,9 @@
             if (info.durationMillis != -1) {
                 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
             }
+            if (info.numInstances != -1) {
+                sb.append("Instance-Count: ").append(info.numInstances).append("\n");
+            }
             if (info.tags != null) {
                 for (String tag : info.tags) {
                     sb.append("Span-Tag: ").append(tag).append("\n");
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 691aff28..7a61b3c 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -53,6 +53,15 @@
         </activity>
         
         <activity
+                android:name="ViewLayersActivity3"
+                android:label="_ViewLayers3">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <activity
                 android:name="AlphaLayersActivity"
                 android:label="_αLayers">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/res/layout/view_layers_3.xml b/tests/HwAccelerationTest/res/layout/view_layers_3.xml
new file mode 100644
index 0000000..a820f5f
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/view_layers_3.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:background="#30ff0000"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
+
+    <LinearLayout
+        android:background="#3000ff00"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:padding="12dip">
+
+        <ListView
+            android:id="@+id/list1"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:background="#300000ff"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
+
+</LinearLayout>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
new file mode 100644
index 0000000..c8ae75b
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class ViewLayersActivity3 extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(R.layout.view_layers_3);
+
+        setupList(R.id.list1);
+    }
+
+    private void setupList(int listId) {
+        final ListView list = (ListView) findViewById(listId);
+        list.setAdapter(new SimpleListAdapter(this));
+        list.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+        ((View) list.getParent()).setLayerType(View.LAYER_TYPE_HARDWARE, null);
+    }
+
+    private static class SimpleListAdapter extends ArrayAdapter<String> {
+        public SimpleListAdapter(Context context) {
+            super(context, android.R.layout.simple_list_item_1, DATA_LIST);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            TextView v = (TextView) super.getView(position, convertView, parent);
+            final Resources r = getContext().getResources();
+            final DisplayMetrics metrics = r.getDisplayMetrics();
+            v.setCompoundDrawablePadding((int) (6 * metrics.density + 0.5f));
+            v.setCompoundDrawablesWithIntrinsicBounds(r.getDrawable(R.drawable.icon),
+                    null, null, null);
+            return v;
+        }
+    }
+
+    private static final String[] DATA_LIST = {
+            "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
+            "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
+            "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
+            "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
+            "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
+            "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
+            "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria",
+            "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
+            "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
+            "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
+            "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
+            "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
+            "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
+            "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
+            "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
+            "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
+            "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
+            "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
+            "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
+            "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
+            "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
+            "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
+            "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
+            "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
+            "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
+            "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
+            "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
+            "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
+            "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
+            "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
+            "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
+            "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
+            "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
+            "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
+            "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
+            "Ukraine", "United Arab Emirates", "United Kingdom",
+            "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
+            "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
+            "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
+    };
+}