Merge "Create logic for applying padding only to custom preference layouts"
diff --git a/api/current.xml b/api/current.xml
index e6ac507..04d7a1d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -18994,7 +18994,7 @@
  visibility="public"
 >
 <method name="after"
- return="void"
+ return="android.animation.AnimatorSet.Builder"
  abstract="false"
  native="false"
  synchronized="false"
@@ -19007,7 +19007,7 @@
 </parameter>
 </method>
 <method name="after"
- return="void"
+ return="android.animation.AnimatorSet.Builder"
  abstract="false"
  native="false"
  synchronized="false"
@@ -19020,7 +19020,7 @@
 </parameter>
 </method>
 <method name="before"
- return="void"
+ return="android.animation.AnimatorSet.Builder"
  abstract="false"
  native="false"
  synchronized="false"
@@ -19033,7 +19033,7 @@
 </parameter>
 </method>
 <method name="with"
- return="void"
+ return="android.animation.AnimatorSet.Builder"
  abstract="false"
  native="false"
  synchronized="false"
@@ -221206,7 +221206,7 @@
 >
 </method>
 <method name="getShortcutInputMethodsAndSubtypes"
- return="java.util.List&lt;android.util.Pair&lt;android.view.inputmethod.InputMethodInfo, android.view.inputmethod.InputMethodSubtype&gt;&gt;"
+ return="java.util.Map&lt;android.view.inputmethod.InputMethodInfo, java.util.List&lt;android.view.inputmethod.InputMethodSubtype&gt;&gt;"
  abstract="false"
  native="false"
  synchronized="false"
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 9ba9388..f5420d1 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -341,6 +341,20 @@
         return this;
     }
 
+    @Override
+    public void setupStartValues() {
+        for (Node node : mNodes) {
+            node.animation.setupStartValues();
+        }
+    }
+
+    @Override
+    public void setupEndValues() {
+        for (Node node : mNodes) {
+            node.animation.setupEndValues();
+        }
+    }
+
     /**
      * {@inheritDoc}
      *
@@ -401,6 +415,7 @@
                     }
                 }
             });
+            delayAnim.start();
         }
         if (mListeners != null) {
             ArrayList<AnimatorListener> tmpListeners =
@@ -408,6 +423,11 @@
             int numListeners = tmpListeners.size();
             for (int i = 0; i < numListeners; ++i) {
                 tmpListeners.get(i).onAnimationStart(this);
+                if (mNodes.size() == 0) {
+                    // Handle unusual case where empty AnimatorSet is started - should send out
+                    // end event immediately since the event will not be sent out at all otherwise
+                    tmpListeners.get(i).onAnimationEnd(this);
+                }
             }
         }
     }
@@ -894,7 +914,7 @@
          * @param anim The animation that will play when the animation supplied to the
          * {@link AnimatorSet#play(Animator)} method starts.
          */
-        public void with(Animator anim) {
+        public Builder with(Animator anim) {
             Node node = mNodeMap.get(anim);
             if (node == null) {
                 node = new Node(anim);
@@ -903,6 +923,7 @@
             }
             Dependency dependency = new Dependency(mCurrentNode, Dependency.WITH);
             node.addDependency(dependency);
+            return this;
         }
 
         /**
@@ -913,7 +934,7 @@
          * @param anim The animation that will play when the animation supplied to the
          * {@link AnimatorSet#play(Animator)} method ends.
          */
-        public void before(Animator anim) {
+        public Builder before(Animator anim) {
             Node node = mNodeMap.get(anim);
             if (node == null) {
                 node = new Node(anim);
@@ -922,6 +943,7 @@
             }
             Dependency dependency = new Dependency(mCurrentNode, Dependency.AFTER);
             node.addDependency(dependency);
+            return this;
         }
 
         /**
@@ -932,7 +954,7 @@
          * @param anim The animation whose end will cause the animation supplied to the
          * {@link AnimatorSet#play(Animator)} method to play.
          */
-        public void after(Animator anim) {
+        public Builder after(Animator anim) {
             Node node = mNodeMap.get(anim);
             if (node == null) {
                 node = new Node(anim);
@@ -941,6 +963,7 @@
             }
             Dependency dependency = new Dependency(node, Dependency.AFTER);
             mCurrentNode.addDependency(dependency);
+            return this;
         }
 
         /**
@@ -951,11 +974,12 @@
          * @param delay The number of milliseconds that should elapse before the
          * animation starts.
          */
-        public void after(long delay) {
+        public Builder after(long delay) {
             // setup dummy ValueAnimator just to run the clock
             ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
             anim.setDuration(delay);
             after(anim);
+            return this;
         }
 
     }
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index b021e75..e192067 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -19,6 +19,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.util.AndroidRuntimeException;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.AnimationUtils;
 
@@ -860,21 +861,22 @@
     /**
      * Start the animation playing. This version of start() takes a boolean flag that indicates
      * whether the animation should play in reverse. The flag is usually false, but may be set
-     * to true if called from the reverse() method/
+     * to true if called from the reverse() method.
+     *
+     * <p>The animation started by calling this method will be run on the thread that called
+     * this method. This thread should have a Looper on it (a runtime exception will be thrown if
+     * this is not the case). Also, if the animation will animate
+     * properties of objects in the view hierarchy, then the calling thread should be the UI
+     * thread for that view hierarchy.</p>
      *
      * @param playBackwards Whether the ValueAnimator should start playing in reverse.
      */
     private void start(boolean playBackwards) {
-        mPlayingBackwards = playBackwards;
-        Looper looper = Looper.getMainLooper();
-        final boolean isUiThread;
-        if (looper != null) {
-            isUiThread = Thread.currentThread() == looper.getThread();
-        } else {
-            // ignore check if we don't have a Looper (this isn't an Activity)
-            isUiThread = true;
+        if (Looper.myLooper() == null) {
+            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
         }
-        if ((mStartDelay == 0) && isUiThread) {
+        mPlayingBackwards = playBackwards;
+        if (mStartDelay == 0) {
             if (mListeners != null) {
                 ArrayList<AnimatorListener> tmpListeners =
                         (ArrayList<AnimatorListener>) mListeners.clone();
@@ -912,9 +914,14 @@
                 listener.onAnimationCancel(this);
             }
         }
-        // Just set the CANCELED flag - this causes the animation to end the next time a frame
-        // is processed.
-        mPlayingState = CANCELED;
+        // Only cancel if the animation is actually running or has been started and is about
+        // to run
+        if (mPlayingState != STOPPED || sPendingAnimations.get().contains(this) ||
+                sDelayedAnims.get().contains(this)) {
+            // Just set the CANCELED flag - this causes the animation to end the next time a frame
+            // is processed.
+            mPlayingState = CANCELED;
+        }
     }
 
     @Override
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 2b4f39a..1c295a7 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -513,21 +513,27 @@
     }
 
     /**
-     * Count the number and aggregate size of memory allocations between
-     * two points.
+     * Start counting the number and aggregate size of memory allocations.
      *
-     * The "start" function resets the counts and enables counting.  The
-     * "stop" function disables the counting so that the analysis code
-     * doesn't cause additional allocations.  The "get" function returns
-     * the specified value.
+     * <p>The {@link #startAllocCounting() start} function resets the counts and enables counting.
+     * The {@link #stopAllocCounting() stop} function disables the counting so that the analysis
+     * code doesn't cause additional allocations.  The various <code>get</code> functions return
+     * the specified value. And the various <code>reset</code> functions reset the specified
+     * count.</p>
      *
-     * Counts are kept for the system as a whole and for each thread.
+     * <p>Counts are kept for the system as a whole and for each thread.
      * The per-thread counts for threads other than the current thread
-     * are not cleared by the "reset" or "start" calls.
+     * are not cleared by the "reset" or "start" calls.</p>
      */
     public static void startAllocCounting() {
         VMDebug.startAllocCounting();
     }
+
+    /**
+     * Stop counting the number and aggregate size of memory allocations.
+     *
+     * @see #startAllocCounting()
+     */
     public static void stopAllocCounting() {
         VMDebug.stopAllocCounting();
     }
@@ -671,11 +677,11 @@
      * for catching regressions in code that is expected to operate
      * without causing any allocations.
      *
-     * Pass in the maximum number of allowed allocations.  Use -1 to disable
-     * the limit.  Returns the previous limit.
+     * <p>Pass in the maximum number of allowed allocations.  Use -1 to disable
+     * the limit.  Returns the previous limit.</p>
      *
-     * The preferred way to use this is:
-     *
+     * <p>The preferred way to use this is:
+     * <pre>
      *  int prevLimit = -1;
      *  try {
      *      prevLimit = Debug.setAllocationLimit(0);
@@ -683,16 +689,16 @@
      *  } finally {
      *      Debug.setAllocationLimit(prevLimit);
      *  }
-     *
+     * </pre>
      * This allows limits to be nested.  The try/finally ensures that the
-     * limit is reset if something fails.
+     * limit is reset if something fails.</p>
      *
-     * Exceeding the limit causes a dalvik.system.AllocationLimitError to
+     * <p>Exceeding the limit causes a dalvik.system.AllocationLimitError to
      * be thrown from a memory allocation call.  The limit is reset to -1
-     * when this happens.
+     * when this happens.</p>
      *
-     * The feature may be disabled in the VM configuration.  If so, this
-     * call has no effect, and always returns -1.
+     * <p>The feature may be disabled in the VM configuration.  If so, this
+     * call has no effect, and always returns -1.</p>
      */
     public static int setAllocationLimit(int limit) {
         return VMDebug.setAllocationLimit(limit);
@@ -846,6 +852,7 @@
      * API for gathering and querying instruction counts.
      *
      * Example usage:
+     * <pre>
      *   Debug.InstructionCount icount = new Debug.InstructionCount();
      *   icount.resetAndStart();
      *    [... do lots of stuff ...]
@@ -855,6 +862,7 @@
      *       System.out.println("Method invocations: "
      *           + icount.globalMethodInvocations());
      *   }
+     * </pre>
      */
     public static class InstructionCount {
         private static final int NUM_INSTR = 256;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index a5f3ade..621a908 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -23,7 +23,6 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
@@ -49,7 +48,9 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -1454,30 +1455,29 @@
         }
     }
 
-    public List<Pair<InputMethodInfo, InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() {
+    public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() {
         synchronized (mH) {
-            List<Pair<InputMethodInfo, InputMethodSubtype>> ret =
-                    new ArrayList<Pair<InputMethodInfo, InputMethodSubtype>>();
+            HashMap<InputMethodInfo, List<InputMethodSubtype>> ret =
+                    new HashMap<InputMethodInfo, List<InputMethodSubtype>>();
             try {
                 // TODO: We should change the return type from List<Object> to List<Parcelable>
                 List<Object> info = mService.getShortcutInputMethodsAndSubtypes();
-                // "info" has imi1, subtype1, imi2, subtype2, imi3, subtype3,..... in the list
-                Object imi;
-                Object subtype;
-                if (info != null && info.size() > 0) {
-                    final int N = info.size();
-                    if (N % 2 == 0) {
-                        for (int i = 0; i < N;) {
-                            if ((imi = info.get(i++)) instanceof InputMethodInfo) {
-                                subtype = info.get(i++);
-                                ret.add(new Pair<InputMethodInfo, InputMethodSubtype> (
-                                        (InputMethodInfo)imi,
-                                        (subtype instanceof InputMethodSubtype) ?
-                                                (InputMethodSubtype)subtype : null));
+                // "info" has imi1, subtype1, subtype2, imi2, subtype2, imi3, subtype3..in the list
+                ArrayList<InputMethodSubtype> subtypes = null;
+                final int N = info.size();
+                if (info != null && N > 0) {
+                    for (int i = 0; i < N; ++i) {
+                        Object o = info.get(i);
+                        if (o instanceof InputMethodInfo) {
+                            if (ret.containsKey(o)) {
+                                Log.e(TAG, "IMI list already contains the same InputMethod.");
+                                break;
                             }
+                            subtypes = new ArrayList<InputMethodSubtype>();
+                            ret.put((InputMethodInfo)o, subtypes);
+                        } else if (subtypes != null && o instanceof InputMethodSubtype) {
+                            subtypes.add((InputMethodSubtype)o);
                         }
-                    } else {
-                        Log.w(TAG, "The size of list was illegal.");
                     }
                 }
             } catch (RemoteException e) {
@@ -1486,6 +1486,7 @@
             return ret;
         }
     }
+
     public boolean switchToLastInputMethod(IBinder imeToken) {
         synchronized (mH) {
             try {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 3faec55..900c9ec 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -24,6 +24,7 @@
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.os.StrictMode;
 import android.util.AttributeSet;
 import android.view.FocusFinder;
 import android.view.KeyEvent;
@@ -128,7 +129,16 @@
      * drags/flings if multiple pointers are used.
      */
     private int mActivePointerId = INVALID_POINTER;
-    
+
+    /**
+     * The StrictMode "critical time span" objects to catch animation
+     * stutters.  Non-null when a time-sensitive animation is
+     * in-flight.  Must call finish() on them when done animating.
+     * These are no-ops on user builds.
+     */
+    private StrictMode.Span mScrollStrictSpan = null;  // aka "drag"
+    private StrictMode.Span mFlingStrictSpan = null;
+
     /**
      * Sentinel value for no current active pointer.
      * Used by {@link #mActivePointerId}.
@@ -437,6 +447,9 @@
                 if (yDiff > mTouchSlop) {
                     mIsBeingDragged = true;
                     mLastMotionY = y;
+                    if (mScrollStrictSpan == null) {
+                        mScrollStrictSpan = StrictMode.enterCriticalSpan("ScrollView-scroll");
+                    }
                 }
                 break;
             }
@@ -461,6 +474,9 @@
                 * being flinged.
                 */
                 mIsBeingDragged = !mScroller.isFinished();
+                if (mIsBeingDragged && mScrollStrictSpan == null) {
+                    mScrollStrictSpan = StrictMode.enterCriticalSpan("ScrollView-scroll");
+                }
                 break;
             }
 
@@ -512,6 +528,10 @@
                  */
                 if (!mScroller.isFinished()) {
                     mScroller.abortAnimation();
+                    if (mFlingStrictSpan != null) {
+                        mFlingStrictSpan.finish();
+                        mFlingStrictSpan = null;
+                    }
                 }
 
                 // Remember where the motion event started
@@ -577,16 +597,7 @@
                     }
 
                     mActivePointerId = INVALID_POINTER;
-                    mIsBeingDragged = false;
-
-                    if (mVelocityTracker != null) {
-                        mVelocityTracker.recycle();
-                        mVelocityTracker = null;
-                    }
-                    if (mEdgeGlowTop != null) {
-                        mEdgeGlowTop.onRelease();
-                        mEdgeGlowBottom.onRelease();
-                    }
+                    endDrag();
                 }
                 break;
             case MotionEvent.ACTION_CANCEL:
@@ -595,15 +606,7 @@
                         invalidate();
                     }
                     mActivePointerId = INVALID_POINTER;
-                    mIsBeingDragged = false;
-                    if (mVelocityTracker != null) {
-                        mVelocityTracker.recycle();
-                        mVelocityTracker = null;
-                    }
-                    if (mEdgeGlowTop != null) {
-                        mEdgeGlowTop.onRelease();
-                        mEdgeGlowBottom.onRelease();
-                    }
+                    endDrag();
                 }
                 break;
             case MotionEvent.ACTION_POINTER_UP:
@@ -1004,6 +1007,10 @@
         } else {
             if (!mScroller.isFinished()) {
                 mScroller.abortAnimation();
+                if (mFlingStrictSpan != null) {
+                    mFlingStrictSpan.finish();
+                    mFlingStrictSpan = null;
+                }
             }
             scrollBy(dx, dy);
         }
@@ -1122,6 +1129,11 @@
 
             // Keep on drawing until the animation has finished.
             postInvalidate();
+        } else {
+            if (mFlingStrictSpan != null) {
+                mFlingStrictSpan.finish();
+                mFlingStrictSpan = null;
+            }
         }
     }
 
@@ -1296,6 +1308,20 @@
     }
 
     @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+
+        if (mScrollStrictSpan != null) {
+            mScrollStrictSpan.finish();
+            mScrollStrictSpan = null;
+        }
+        if (mFlingStrictSpan != null) {
+            mFlingStrictSpan.finish();
+            mFlingStrictSpan = null;
+        }
+    }
+
+    @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
         mIsLayoutDirty = false;
@@ -1368,11 +1394,34 @@
                 mScrollViewMovedFocus = true;
                 mScrollViewMovedFocus = false;
             }
-    
+
+            if (mFlingStrictSpan == null) {
+                mFlingStrictSpan = StrictMode.enterCriticalSpan("ScrollView-fling");
+            }
+
             invalidate();
         }
     }
 
+    private void endDrag() {
+        mIsBeingDragged = false;
+
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+            mVelocityTracker = null;
+        }
+
+        if (mEdgeGlowTop != null) {
+            mEdgeGlowTop.onRelease();
+            mEdgeGlowBottom.onRelease();
+        }
+
+        if (mScrollStrictSpan != null) {
+            mScrollStrictSpan.finish();
+            mScrollStrictSpan = null;
+        }
+    }
+
     /**
      * {@inheritDoc}
      *
diff --git a/docs/html/guide/topics/fragments/index.jd b/docs/html/guide/topics/fragments/index.jd
index ce10ef7..766146e 100644
--- a/docs/html/guide/topics/fragments/index.jd
+++ b/docs/html/guide/topics/fragments/index.jd
@@ -399,7 +399,7 @@
 Fragment newFragment = new MyFragment();
 FragmentTransaction ft = openFragmentTransaction();
 // Replace and add to back stack
-ft.replace(newFragment, R.id.myfragment);
+ft.replace(R.id.myfragment, newFragment);
 ft.addToBackStack(null);
 // Apply changes
 ft.commit();
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index 8d5c913..241ab17 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -30,7 +30,7 @@
 
     /** Create a new compose shader, given shaders A, B, and a combining mode.
         When the mode is applied, it will be given the result from shader A as its
-        "dst", and the result of from shader B as its "src".
+        "dst", and the result from shader B as its "src".
         @param shaderA  The colors from this shader are seen as the "dst" by the mode
         @param shaderB  The colors from this shader are seen as the "src" by the mode
         @param mode     The mode that combines the colors from the two shaders. If mode
@@ -53,7 +53,7 @@
 
     /** Create a new compose shader, given shaders A, B, and a combining PorterDuff mode.
         When the mode is applied, it will be given the result from shader A as its
-        "dst", and the result of from shader B as its "src".
+        "dst", and the result from shader B as its "src".
         @param shaderA  The colors from this shader are seen as the "dst" by the mode
         @param shaderB  The colors from this shader are seen as the "src" by the mode
         @param mode     The PorterDuff mode that combines the colors from the two shaders.
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 3f32f2f..3108e4e 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -3898,32 +3898,34 @@
             mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
             mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
 
-            OMX_CONFIG_RECTTYPE rect;
-            status_t err =
-                     mOMX->getConfig(
-                         mNode, OMX_IndexConfigCommonOutputCrop,
-                         &rect, sizeof(rect));
+            if (!mIsEncoder) {
+                OMX_CONFIG_RECTTYPE rect;
+                status_t err =
+                        mOMX->getConfig(
+                            mNode, OMX_IndexConfigCommonOutputCrop,
+                            &rect, sizeof(rect));
 
-            if (err == OK) {
-                CHECK_GE(rect.nLeft, 0);
-                CHECK_GE(rect.nTop, 0);
-                CHECK_GE(rect.nWidth, 0u);
-                CHECK_GE(rect.nHeight, 0u);
-                CHECK_LE(rect.nLeft + rect.nWidth - 1, video_def->nFrameWidth);
-                CHECK_LE(rect.nTop + rect.nHeight - 1, video_def->nFrameHeight);
+                if (err == OK) {
+                    CHECK_GE(rect.nLeft, 0);
+                    CHECK_GE(rect.nTop, 0);
+                    CHECK_GE(rect.nWidth, 0u);
+                    CHECK_GE(rect.nHeight, 0u);
+                    CHECK_LE(rect.nLeft + rect.nWidth - 1, video_def->nFrameWidth);
+                    CHECK_LE(rect.nTop + rect.nHeight - 1, video_def->nFrameHeight);
 
-                mOutputFormat->setRect(
-                        kKeyCropRect,
-                        rect.nLeft,
-                        rect.nTop,
-                        rect.nLeft + rect.nWidth - 1,
-                        rect.nTop + rect.nHeight - 1);
-            } else {
-                mOutputFormat->setRect(
-                        kKeyCropRect,
-                        0, 0,
-                        video_def->nFrameWidth - 1,
-                        video_def->nFrameHeight - 1);
+                    mOutputFormat->setRect(
+                            kKeyCropRect,
+                            rect.nLeft,
+                            rect.nTop,
+                            rect.nLeft + rect.nWidth - 1,
+                            rect.nTop + rect.nHeight - 1);
+                } else {
+                    mOutputFormat->setRect(
+                            kKeyCropRect,
+                            0, 0,
+                            video_def->nFrameWidth - 1,
+                            video_def->nFrameHeight - 1);
+                }
             }
 
             break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 4ff2429..cd2679a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -116,7 +116,6 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
-        filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         context.registerReceiver(this, filter);
@@ -141,7 +140,6 @@
         final String action = intent.getAction();
         if (action.equals(WifiManager.RSSI_CHANGED_ACTION)
                 || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)
-                || action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)
                 || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
             updateWifiState(intent);
             refreshViews();
@@ -489,8 +487,7 @@
             mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                     WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
 
-        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)
-                || action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
+        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
             final NetworkInfo networkInfo = (NetworkInfo)
                     intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
             boolean wasConnected = mWifiConnected;
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index b2cc6bd..eca37b7 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -240,10 +240,9 @@
     private InputMethodSubtype mCurrentSubtype;
 
     // This list contains the pairs of InputMethodInfo and InputMethodSubtype.
-    private List<Pair<InputMethodInfo, InputMethodSubtype>> mShortcutInputMethodsAndSubtypes;
-    // This list is used for returning the pairs of InputMethodInfo and InputMethodSubtype through
-    // aidl. This list has imi1, subtype1 imi2, subtype2...
-    private List mShortcutInputMethodsAndSubtypesObjectList;
+    private final HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>
+            mShortcutInputMethodsAndSubtypes =
+                new HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>();
 
     /**
      * Set to true if our ServiceConnection is currently actively bound to
@@ -992,7 +991,7 @@
                 mCurMethodId = null;
                 unbindCurrentMethodLocked(true);
             }
-            mShortcutInputMethodsAndSubtypes = null;
+            mShortcutInputMethodsAndSubtypes.clear();
         } else {
             // There is no longer an input method set, so stop any current one.
             mCurMethodId = null;
@@ -2022,7 +2021,6 @@
                     + mostApplicableIMI.getId() + "," + mostApplicableSubtypeId);
         }
         if (mostApplicableIMI != null && mostApplicableSubtypeId != NOT_A_SUBTYPE_ID) {
-            ArrayList<Parcelable> ret = new ArrayList<Parcelable>(2);
             return new Pair<InputMethodInfo, InputMethodSubtype> (mostApplicableIMI,
                     mostApplicableIMI.getSubtypes().get(mostApplicableSubtypeId));
         } else {
@@ -2067,25 +2065,37 @@
         }
     }
 
+    private void addShortcutInputMethodAndSubtypes(InputMethodInfo imi,
+            InputMethodSubtype subtype) {
+        if (mShortcutInputMethodsAndSubtypes.containsKey(imi)) {
+            mShortcutInputMethodsAndSubtypes.get(imi).add(subtype);
+        } else {
+            ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+            subtypes.add(subtype);
+            mShortcutInputMethodsAndSubtypes.put(imi, subtypes);
+        }
+    }
+
     // TODO: We should change the return type from List to List<Parcelable>
     public List getShortcutInputMethodsAndSubtypes() {
         synchronized (mMethodMap) {
-            if (mShortcutInputMethodsAndSubtypesObjectList != null) {
+            if (mShortcutInputMethodsAndSubtypes.size() == 0) {
                 // If there are no selected shortcut subtypes, the framework will try to find
                 // the most applicable subtype from all subtypes whose mode is
                 // SUBTYPE_MODE_VOICE. This is an exceptional case, so we will hardcode the mode.
-                mShortcutInputMethodsAndSubtypes =
-                        new ArrayList<Pair<InputMethodInfo, InputMethodSubtype>>();
-                mShortcutInputMethodsAndSubtypes.add(
-                        findLastResortApplicableShortcutInputMethodAndSubtypeLocked(
-                                SUBTYPE_MODE_VOICE));
-                mShortcutInputMethodsAndSubtypesObjectList = new ArrayList<Parcelable>();
-                for (Pair ime: mShortcutInputMethodsAndSubtypes) {
-                    mShortcutInputMethodsAndSubtypesObjectList.add(ime.first);
-                    mShortcutInputMethodsAndSubtypesObjectList.add(ime.second);
+                Pair<InputMethodInfo, InputMethodSubtype> info =
+                    findLastResortApplicableShortcutInputMethodAndSubtypeLocked(
+                            SUBTYPE_MODE_VOICE);
+                addShortcutInputMethodAndSubtypes(info.first, info.second);
+            }
+            ArrayList ret = new ArrayList<Object>();
+            for (InputMethodInfo imi: mShortcutInputMethodsAndSubtypes.keySet()) {
+                ret.add(imi);
+                for (InputMethodSubtype subtype: mShortcutInputMethodsAndSubtypes.get(imi)) {
+                    ret.add(subtype);
                 }
             }
-            return mShortcutInputMethodsAndSubtypesObjectList;
+            return ret;
         }
     }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
index 6fd59c4..212223c 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
@@ -456,7 +456,11 @@
             // into is.read(...) This number is not related to the value passed
             // to mark(...) above.
             try {
-                bm = Bitmap_Delegate.createBitmap(is, Density.MEDIUM);
+                Density density = Density.MEDIUM;
+                if (opts != null) {
+                    density = Density.getEnum(opts.inDensity);
+                }
+                bm = Bitmap_Delegate.createBitmap(is, true, density);
             } catch (IOException e) {
                 return null;
             }
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 0920497..b4c51b2 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -75,32 +75,56 @@
 
     /**
      * Creates and returns a {@link Bitmap} initialized with the given file content.
+     *
+     * @param input the file from which to read the bitmap content
+     * @param isMutable whether the bitmap is mutable
+     * @param density the density associated with the bitmap
+     *
+     * @see Bitmap#isMutable()
+     * @see Bitmap#getDensity()
      */
-    public static Bitmap createBitmap(File input, Density density) throws IOException {
+    public static Bitmap createBitmap(File input, boolean isMutable, Density density)
+            throws IOException {
         // create a delegate with the content of the file.
         Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input));
 
-        return createBitmap(delegate, density.getValue());
+        return createBitmap(delegate, isMutable, density.getValue());
     }
 
     /**
      * Creates and returns a {@link Bitmap} initialized with the given stream content.
+     *
+     * @param input the stream from which to read the bitmap content
+     * @param isMutable whether the bitmap is mutable
+     * @param density the density associated with the bitmap
+     *
+     * @see Bitmap#isMutable()
+     * @see Bitmap#getDensity()
      */
-    public static Bitmap createBitmap(InputStream input, Density density) throws IOException {
+    public static Bitmap createBitmap(InputStream input, boolean isMutable, Density density)
+            throws IOException {
         // create a delegate with the content of the stream.
         Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input));
 
-        return createBitmap(delegate, density.getValue());
+        return createBitmap(delegate, isMutable, density.getValue());
     }
 
     /**
      * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
+     *
+     * @param image the bitmap content
+     * @param isMutable whether the bitmap is mutable
+     * @param density the density associated with the bitmap
+     *
+     * @see Bitmap#isMutable()
+     * @see Bitmap#getDensity()
      */
-    public static Bitmap createBitmap(BufferedImage image, Density density) throws IOException {
+    public static Bitmap createBitmap(BufferedImage image, boolean isMutable, Density density)
+            throws IOException {
         // create a delegate with the given image.
         Bitmap_Delegate delegate = new Bitmap_Delegate(image);
 
-        return createBitmap(delegate, density.getValue());
+        return createBitmap(delegate, isMutable, density.getValue());
     }
 
     /**
@@ -153,7 +177,7 @@
         // create a delegate with the content of the stream.
         Bitmap_Delegate delegate = new Bitmap_Delegate(image);
 
-        return createBitmap(delegate, Bitmap.getDefaultDensity());
+        return createBitmap(delegate, mutable, Bitmap.getDefaultDensity());
     }
 
     /*package*/ static Bitmap nativeCopy(int srcBitmap, int nativeConfig, boolean isMutable) {
@@ -166,8 +190,7 @@
     }
 
     /*package*/ static void nativeRecycle(int nativeBitmap) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap");
+        sManager.removeDelegate(nativeBitmap);
     }
 
     /*package*/ static boolean nativeCompress(int nativeBitmap, int format, int quality,
@@ -336,11 +359,11 @@
         mImage = image;
     }
 
-    private static Bitmap createBitmap(Bitmap_Delegate delegate, int density) {
+    private static Bitmap createBitmap(Bitmap_Delegate delegate, boolean isMutable, int density) {
         // get its native_int
         int nativeInt = sManager.addDelegate(delegate);
 
         // and create/return a new Bitmap with it
-        return new Bitmap(nativeInt, true /*isMutable*/, null /*ninePatchChunk*/, density);
+        return new Bitmap(nativeInt, isMutable, null /*ninePatchChunk*/, density);
     }
 }
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index cea07af..08f3c7a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -960,7 +960,7 @@
      * Creates a new {@link Graphics2D} based on the {@link Paint} parameters.
      * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used.
      */
-    private Graphics2D getCustomGraphics(Paint_Delegate paint) {
+    /*package*/ Graphics2D getCustomGraphics(Paint_Delegate paint) {
         // make new one
         Graphics2D g = getGraphics2d();
         g = (Graphics2D)g.create();
diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
new file mode 100644
index 0000000..3d26e47
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.ninepatch.NinePatchChunk;
+
+import android.graphics.drawable.NinePatchDrawable;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Delegate implementing the native methods of android.graphics.NinePatch
+ *
+ * Through the layoutlib_create tool, the original native methods of NinePatch have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
+ * around to map int to instance of the delegate.
+ *
+ */
+public class NinePatch_Delegate {
+
+    /**
+     * Cache map for {@link NinePatchChunk}.
+     * When the chunks are created they are serialized into a byte[], and both are put
+     * in the cache, using a {@link SoftReference} for the chunk. The default Java classes
+     * for {@link NinePatch} and {@link NinePatchDrawable} only reference to the byte[] data, and
+     * provide this for drawing.
+     * Using the cache map allows us to not have to deserialize the byte[] back into a
+     * {@link NinePatchChunk} every time a rendering is done.
+     */
+    private final static Map<byte[], SoftReference<NinePatchChunk>> sChunkCache =
+        new HashMap<byte[], SoftReference<NinePatchChunk>>();
+
+    // ---- Public Helper methods ----
+
+    /**
+     * Serializes the given chunk.
+     *
+     * @return the serialized data for the chunk.
+     */
+    public static byte[] serialize(NinePatchChunk chunk) {
+        // serialize the chunk to get a byte[]
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = null;
+        try {
+            oos = new ObjectOutputStream(baos);
+            oos.writeObject(chunk);
+        } catch (IOException e) {
+            //FIXME log this.
+            return null;
+        } finally {
+            if (oos != null) {
+                try {
+                    oos.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+
+        // get the array and add it to the cache
+        byte[] array = baos.toByteArray();
+        sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk));
+        return array;
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static boolean isNinePatchChunk(byte[] chunk) {
+        NinePatchChunk chunkObject = getChunk(chunk);
+        if (chunkObject != null) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /*package*/ static void validateNinePatchChunk(int bitmap, byte[] chunk) {
+        // the default JNI implementation only checks that the byte[] has the same
+        // size as the C struct it represent. Since we cannot do the same check (serialization
+        // will return different size depending on content), we do nothing.
+    }
+
+    /*package*/ static void nativeDraw(int canvas_instance, RectF loc, int bitmap_instance,
+            byte[] c, int paint_instance_or_null, int destDensity, int srcDensity) {
+        draw(canvas_instance,
+                (int) loc.left, (int) loc.top, (int) loc.width(), (int) loc.height(),
+                bitmap_instance, c, paint_instance_or_null,
+                destDensity, srcDensity);
+    }
+
+    /*package*/ static void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance,
+            byte[] c, int paint_instance_or_null, int destDensity, int srcDensity) {
+        draw(canvas_instance,
+                loc.left, loc.top, loc.width(), loc.height(),
+                bitmap_instance, c, paint_instance_or_null,
+                destDensity, srcDensity);
+    }
+
+   private static void draw(int canvas_instance,
+           int left, int top, int right, int bottom,
+           int bitmap_instance, byte[] c, int paint_instance_or_null,
+           int destDensity, int srcDensity) {
+       // get the delegate from the native int.
+       Bitmap_Delegate bitmap_delegate = Bitmap_Delegate.getDelegate(bitmap_instance);
+       if (bitmap_delegate == null) {
+           assert false;
+           return;
+       }
+
+       if (c == null) {
+           // not a 9-patch?
+           BufferedImage image = bitmap_delegate.getImage();
+           Canvas_Delegate.native_drawBitmap(canvas_instance, bitmap_instance,
+                   new Rect(0, 0, image.getWidth(), image.getHeight()),
+                   new Rect(left, top, right, bottom),
+                   paint_instance_or_null, destDensity, srcDensity);
+           return;
+       }
+
+       NinePatchChunk chunkObject = getChunk(c);
+       assert chunkObject != null;
+       if (chunkObject == null) {
+           return;
+       }
+
+       Canvas_Delegate canvas_delegate = Canvas_Delegate.getDelegate(canvas_instance);
+       if (canvas_delegate == null) {
+           assert false;
+           return;
+       }
+
+       // this one can be null
+       Paint_Delegate paint_delegate = Paint_Delegate.getDelegate(paint_instance_or_null);
+
+       Graphics2D graphics;
+       if (paint_delegate != null) {
+           graphics = canvas_delegate.getCustomGraphics(paint_delegate);
+       } else {
+           graphics = canvas_delegate.getGraphics2d();
+       }
+
+       try {
+           chunkObject.draw(bitmap_delegate.getImage(), graphics,
+                   left, top, right - left, bottom - top);
+       } finally {
+           if (paint_delegate != null) {
+               graphics.dispose();
+           }
+       }
+
+    }
+
+    /*package*/ static int nativeGetTransparentRegion(int bitmap, byte[] chunk, Rect location) {
+        return 0;
+    }
+
+    // ---- Private Helper methods ----
+
+    /**
+     * Returns a {@link NinePatchChunk} object for the given serialized representation.
+     *
+     * If the chunk is present in the cache then the object from the cache is returned, otherwise
+     * the array is deserialized into a {@link NinePatchChunk} object.
+     *
+     * @param array the serialized representation of the chunk.
+     * @return the NinePatchChunk or null if deserialization failed.
+     */
+    private static NinePatchChunk getChunk(byte[] array) {
+        SoftReference<NinePatchChunk> chunkRef = sChunkCache.get(array);
+        NinePatchChunk chunk = chunkRef.get();
+        if (chunk == null) {
+            ByteArrayInputStream bais = new ByteArrayInputStream(array);
+            ObjectInputStream ois = null;
+            try {
+                ois = new ObjectInputStream(bais);
+                chunk = (NinePatchChunk) ois.readObject();
+
+                // put back the chunk in the cache
+                if (chunk != null) {
+                    sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk));
+                }
+            } catch (IOException e) {
+                // FIXME: log this
+                return null;
+            } catch (ClassNotFoundException e) {
+                // FIXME: log this
+                return null;
+            } finally {
+                if (ois != null) {
+                    try {
+                        ois.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+        }
+
+        return chunk;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index e691fdf..35ba73d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -26,7 +26,7 @@
 import com.android.layoutlib.bridge.android.BridgeAssetManager;
 import com.android.layoutlib.bridge.impl.FontLoader;
 import com.android.layoutlib.bridge.impl.LayoutSceneImpl;
-import com.android.ninepatch.NinePatch;
+import com.android.ninepatch.NinePatchChunk;
 import com.android.tools.layoutlib.create.MethodAdapter;
 import com.android.tools.layoutlib.create.OverrideMethod;
 
@@ -73,13 +73,13 @@
 
     private final static Map<Object, Map<String, SoftReference<Bitmap>>> sProjectBitmapCache =
         new HashMap<Object, Map<String, SoftReference<Bitmap>>>();
-    private final static Map<Object, Map<String, SoftReference<NinePatch>>> sProject9PatchCache =
-        new HashMap<Object, Map<String, SoftReference<NinePatch>>>();
+    private final static Map<Object, Map<String, SoftReference<NinePatchChunk>>> sProject9PatchCache =
+        new HashMap<Object, Map<String, SoftReference<NinePatchChunk>>>();
 
     private final static Map<String, SoftReference<Bitmap>> sFrameworkBitmapCache =
         new HashMap<String, SoftReference<Bitmap>>();
-    private final static Map<String, SoftReference<NinePatch>> sFramework9PatchCache =
-        new HashMap<String, SoftReference<NinePatch>>();
+    private final static Map<String, SoftReference<NinePatchChunk>> sFramework9PatchCache =
+        new HashMap<String, SoftReference<NinePatchChunk>>();
 
     private static Map<String, Map<String, Integer>> sEnumValueMap;
 
@@ -252,23 +252,23 @@
     }
 
     /**
-     * Sets a 9 patch in a project cache or in the framework cache.
+     * Sets a 9 patch chunk in a project cache or in the framework cache.
      * @param value the path of the 9 patch
      * @param ninePatch the 9 patch object
      * @param projectKey the key of the project, or null to put the bitmap in the framework cache.
      */
-    public static void setCached9Patch(String value, NinePatch ninePatch, Object projectKey) {
+    public static void setCached9Patch(String value, NinePatchChunk ninePatch, Object projectKey) {
         if (projectKey != null) {
-            Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey);
+            Map<String, SoftReference<NinePatchChunk>> map = sProject9PatchCache.get(projectKey);
 
             if (map == null) {
-                map = new HashMap<String, SoftReference<NinePatch>>();
+                map = new HashMap<String, SoftReference<NinePatchChunk>>();
                 sProject9PatchCache.put(projectKey, map);
             }
 
-            map.put(value, new SoftReference<NinePatch>(ninePatch));
+            map.put(value, new SoftReference<NinePatchChunk>(ninePatch));
         } else {
-            sFramework9PatchCache.put(value, new SoftReference<NinePatch>(ninePatch));
+            sFramework9PatchCache.put(value, new SoftReference<NinePatchChunk>(ninePatch));
         }
     }
 
@@ -436,24 +436,24 @@
     }
 
     /**
-     * Returns the 9 patch for a specific path, from a specific project cache, or from the
+     * Returns the 9 patch chunk for a specific path, from a specific project cache, or from the
      * framework cache.
      * @param value the path of the 9 patch
      * @param projectKey the key of the project, or null to query the framework cache.
      * @return the cached 9 patch or null if not found.
      */
-    public static NinePatch getCached9Patch(String value, Object projectKey) {
+    public static NinePatchChunk getCached9Patch(String value, Object projectKey) {
         if (projectKey != null) {
-            Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey);
+            Map<String, SoftReference<NinePatchChunk>> map = sProject9PatchCache.get(projectKey);
 
             if (map != null) {
-                SoftReference<NinePatch> ref = map.get(value);
+                SoftReference<NinePatchChunk> ref = map.get(value);
                 if (ref != null) {
                     return ref.get();
                 }
             }
         } else {
-            SoftReference<NinePatch> ref = sFramework9PatchCache.get(value);
+            SoftReference<NinePatchChunk> ref = sFramework9PatchCache.get(value);
             if (ref != null) {
                 return ref.get();
             }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java
deleted file mode 100644
index 4efa631..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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.layoutlib.bridge.android;
-
-import com.android.ninepatch.NinePatch;
-
-import android.graphics.Canvas;
-import android.graphics.Canvas_Delegate;
-import android.graphics.ColorFilter;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-
-public class NinePatchDrawable extends Drawable {
-
-    private NinePatch m9Patch;
-
-    public NinePatchDrawable(NinePatch ninePatch) {
-        m9Patch = ninePatch;
-    }
-
-    @Override
-    public int getMinimumWidth() {
-        return m9Patch.getWidth();
-    }
-
-    @Override
-    public int getMinimumHeight() {
-        return m9Patch.getHeight();
-    }
-
-    /**
-     * Return the intrinsic width of the underlying drawable object.  Returns
-     * -1 if it has no intrinsic width, such as with a solid color.
-     */
-    @Override
-    public int getIntrinsicWidth() {
-        return m9Patch.getWidth();
-    }
-
-    /**
-     * Return the intrinsic height of the underlying drawable object. Returns
-     * -1 if it has no intrinsic height, such as with a solid color.
-     */
-    @Override
-    public int getIntrinsicHeight() {
-        return m9Patch.getHeight();
-    }
-
-    /**
-     * Return in padding the insets suggested by this Drawable for placing
-     * content inside the drawable's bounds. Positive values move toward the
-     * center of the Drawable (set Rect.inset). Returns true if this drawable
-     * actually has a padding, else false. When false is returned, the padding
-     * is always set to 0.
-     */
-    @Override
-    public boolean getPadding(Rect padding) {
-        int[] padd = new int[4];
-        m9Patch.getPadding(padd);
-        padding.left = padd[0];
-        padding.top = padd[1];
-        padding.right = padd[2];
-        padding.bottom = padd[3];
-        return true;
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        Rect r = getBounds();
-        Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas);
-        m9Patch.draw(canvasDelegate.getGraphics2d(), r.left, r.top, r.width(), r.height());
-
-        return;
-    }
-
-
-    // ----------- Not implemented methods ---------------
-
-
-    @Override
-    public int getOpacity() {
-        // FIXME
-        return 0xFF;
-    }
-
-    @Override
-    public void setAlpha(int arg0) {
-        // FIXME !
-    }
-
-    @Override
-    public void setColorFilter(ColorFilter arg0) {
-        // FIXME
-    }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
index 2e3f9a8..f7d249e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
@@ -313,10 +313,12 @@
 
             // create an Android bitmap around the BufferedImage
             Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
+                    true /*isMutable*/,
                     Density.getEnum(mParams.getDensity()));
 
             // create a Canvas around the Android bitmap
             Canvas canvas = new Canvas(bitmap);
+            canvas.setDensity(mParams.getDensity());
 
             // to set the logger, get the native delegate
             Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 3e506b8..ceb8a0d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -22,8 +22,8 @@
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.android.NinePatchDrawable;
 import com.android.ninepatch.NinePatch;
+import com.android.ninepatch.NinePatchChunk;
 
 import org.kxml2.io.KXmlParser;
 import org.xmlpull.v1.XmlPullParser;
@@ -31,9 +31,12 @@
 
 import android.graphics.Bitmap;
 import android.graphics.Bitmap_Delegate;
+import android.graphics.NinePatch_Delegate;
+import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.NinePatchDrawable;
 import android.util.TypedValue;
 
 import java.io.File;
@@ -121,15 +124,38 @@
         if (lowerCaseValue.endsWith(NinePatch.EXTENSION_9PATCH)) {
             File file = new File(stringValue);
             if (file.isFile()) {
-                NinePatch ninePatch = Bridge.getCached9Patch(stringValue,
+                // see if we still have both the chunk and the bitmap in the caches
+                NinePatchChunk chunk = Bridge.getCached9Patch(stringValue,
+                        isFramework ? null : context.getProjectKey());
+                Bitmap bitmap = Bridge.getCachedBitmap(stringValue,
                         isFramework ? null : context.getProjectKey());
 
-                if (ninePatch == null) {
+                // if either chunk or bitmap is null, then we reload the 9-patch file.
+                if (chunk == null || bitmap == null) {
                     try {
-                        ninePatch = NinePatch.load(file.toURL(), false /* convert */);
+                        NinePatch ninePatch = NinePatch.load(file.toURL(), false /* convert */);
+                        if (ninePatch != null) {
+                            if (chunk == null) {
+                                chunk = ninePatch.getChunk();
 
-                        Bridge.setCached9Patch(stringValue, ninePatch,
-                                isFramework ? null : context.getProjectKey());
+                                Bridge.setCached9Patch(stringValue, chunk,
+                                        isFramework ? null : context.getProjectKey());
+                            }
+
+                            if (bitmap == null) {
+                                Density density = Density.MEDIUM;
+                                if (value instanceof IDensityBasedResourceValue) {
+                                    density = ((IDensityBasedResourceValue)value).getDensity();
+                                }
+
+                                bitmap = Bitmap_Delegate.createBitmap(ninePatch.getImage(),
+                                        false /*isMutable*/,
+                                        density);
+
+                                Bridge.setCachedBitmap(stringValue, bitmap,
+                                        isFramework ? null : context.getProjectKey());
+                            }
+                        }
                     } catch (MalformedURLException e) {
                         // URL is wrong, we'll return null below
                     } catch (IOException e) {
@@ -137,8 +163,13 @@
                     }
                 }
 
-                if (ninePatch != null) {
-                    return new NinePatchDrawable(ninePatch);
+                if (chunk != null && bitmap != null) {
+                    int[] padding = chunk.getPadding();
+                    Rect paddingRect = new Rect(padding[0], padding[1], padding[2], padding[3]);
+
+                    return new NinePatchDrawable(context.getResources(), bitmap,
+                            NinePatch_Delegate.serialize(chunk),
+                            paddingRect, null);
                 }
             }
 
@@ -174,29 +205,17 @@
                             isFramework ? null : context.getProjectKey());
 
                     if (bitmap == null) {
-                        // always create the cache copy in the original density.
-                        bitmap = Bitmap_Delegate.createBitmap(bmpFile, Density.MEDIUM);
+                        Density density = Density.MEDIUM;
+                        if (value instanceof IDensityBasedResourceValue) {
+                            density = ((IDensityBasedResourceValue)value).getDensity();
+                        }
+
+                        bitmap = Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/,
+                                density);
                         Bridge.setCachedBitmap(stringValue, bitmap,
                                 isFramework ? null : context.getProjectKey());
                     }
 
-                    try {
-                        if (value instanceof IDensityBasedResourceValue) {
-                            Density density = ((IDensityBasedResourceValue)value).getDensity();
-                            if (density != Density.MEDIUM) {
-                                // create a copy of the bitmap
-                                bitmap = Bitmap.createBitmap(bitmap);
-
-                                // apply the density
-                                bitmap.setDensity(density.getValue());
-                            }
-                        }
-                    } catch (NoClassDefFoundError error) {
-                        // look like we're running in an older version of ADT that doesn't include
-                        // the new layoutlib_api. Let's just ignore this, the drawing will just be
-                        // wrong.
-                    }
-
                     return new BitmapDrawable(context.getResources(), bitmap);
                 } catch (IOException e) {
                     // we'll return null below
diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/NinePatchTest.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/NinePatchTest.java
index 23351ab..a3219e7 100644
--- a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/NinePatchTest.java
+++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/NinePatchTest.java
@@ -48,5 +48,4 @@
         assertEquals(36, mPatch.getWidth());
         assertEquals(25, mPatch.getHeight());
     }
-
 }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index b9c71133..bb2e6b3 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -109,6 +109,7 @@
         "android.graphics.DashPathEffect",
         "android.graphics.LinearGradient",
         "android.graphics.Matrix",
+        "android.graphics.NinePatch",
         "android.graphics.Paint",
         "android.graphics.PathEffect",
         "android.graphics.PorterDuffXfermode",
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 90abd02..7e3df1a 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -1529,7 +1529,7 @@
     }
 
     void setNetworkAvailable(boolean available) {
-        sendMessage(CMD_SET_NETWORK_AVAILABLE, available ? 1 : 0);
+        sendMessage(obtainMessage(CMD_SET_NETWORK_AVAILABLE, available ? 1 : 0, 0));
     }
 
     /********************************************************