Merge "Fix race condition in resize that was created when GetType for allocation and Types became async."
diff --git a/api/current.xml b/api/current.xml
index 5d5f8ac..b0cb834 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1255,6 +1255,17 @@
  visibility="public"
 >
 </field>
+<field name="WRITE_MEDIA_STORAGE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.WRITE_MEDIA_STORAGE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="WRITE_SECURE_SETTINGS"
  type="java.lang.String"
  transient="false"
@@ -14264,7 +14275,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973947"
+ value="16973949"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14275,7 +14286,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973948"
+ value="16973950"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14425,6 +14436,17 @@
  visibility="public"
 >
 </field>
+<field name="Theme_Holo_Extended"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973943"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Theme_Holo_Light"
  type="int"
  transient="false"
@@ -14447,6 +14469,17 @@
  visibility="public"
 >
 </field>
+<field name="Theme_Holo_Light_Extended"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973944"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Theme_Holo_NoActionBar"
  type="int"
  transient="false"
@@ -14748,7 +14781,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973946"
+ value="16973948"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14759,7 +14792,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973945"
+ value="16973947"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14913,7 +14946,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973949"
+ value="16973951"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14979,7 +15012,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973943"
+ value="16973945"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15034,7 +15067,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973944"
+ value="16973946"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -26625,6 +26658,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;extra_click_download_ids&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="PAUSED_QUEUED_FOR_WIFI"
  type="int"
  transient="false"
@@ -27584,6 +27628,17 @@
  visibility="public"
 >
 </method>
+<method name="onDestroyOptionsMenu"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="onDestroyView"
  return="void"
  abstract="false"
@@ -83567,6 +83622,17 @@
  visibility="public"
 >
 </method>
+<method name="getColor"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getOpacity"
  return="int"
  abstract="false"
@@ -83591,6 +83657,19 @@
 <parameter name="alpha" type="int">
 </parameter>
 </method>
+<method name="setColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="color" type="int">
+</parameter>
+</method>
 <method name="setColorFilter"
  return="void"
  abstract="false"
@@ -145015,6 +145094,23 @@
 <parameter name="key" type="java.lang.CharSequence">
 </parameter>
 </method>
+<method name="finishPreferencePanel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="caller" type="android.app.Fragment">
+</parameter>
+<parameter name="resultCode" type="int">
+</parameter>
+<parameter name="resultData" type="android.content.Intent">
+</parameter>
+</method>
 <method name="getPreferenceManager"
  return="android.preference.PreferenceManager"
  abstract="false"
@@ -145243,7 +145339,7 @@
 <parameter name="push" type="boolean">
 </parameter>
 </method>
-<method name="startPreferenceFragment"
+<method name="startPreferencePanel"
  return="void"
  abstract="false"
  native="false"
@@ -145253,9 +145349,17 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="fragment" type="android.app.Fragment">
+<parameter name="fragmentClass" type="java.lang.String">
 </parameter>
-<parameter name="ft" type="android.app.FragmentTransaction">
+<parameter name="args" type="android.os.Bundle">
+</parameter>
+<parameter name="titleRes" type="int">
+</parameter>
+<parameter name="titleText" type="java.lang.CharSequence">
+</parameter>
+<parameter name="resultTo" type="android.app.Fragment">
+</parameter>
+<parameter name="resultRequestCode" type="int">
 </parameter>
 </method>
 <method name="startWithFragment"
@@ -145272,6 +145376,10 @@
 </parameter>
 <parameter name="args" type="android.os.Bundle">
 </parameter>
+<parameter name="resultTo" type="android.app.Fragment">
+</parameter>
+<parameter name="resultRequestCode" type="int">
+</parameter>
 </method>
 <method name="switchToHeader"
  return="void"
@@ -175968,6 +176076,28 @@
  visibility="public"
 >
 </field>
+<field name="TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="208"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_TEXT_VARIATION_WEB_PASSWORD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="224"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </interface>
 <class name="Layout"
  extends="java.lang.Object"
@@ -211960,6 +212090,17 @@
  visibility="public"
 >
 </field>
+<field name="SOFT_INPUT_ADJUST_NOTHING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="48"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SOFT_INPUT_ADJUST_PAN"
  type="int"
  transient="false"
@@ -216274,6 +216415,19 @@
 <parameter name="prefix" type="java.lang.String">
 </parameter>
 </method>
+<method name="makeCompatible"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetSdkVersion" type="int">
+</parameter>
+</method>
 <method name="writeToParcel"
  return="void"
  abstract="false"
@@ -216343,6 +216497,17 @@
  visibility="public"
 >
 </field>
+<field name="IME_ACTION_PREVIOUS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="IME_ACTION_SEARCH"
  type="int"
  transient="false"
@@ -216376,6 +216541,28 @@
  visibility="public"
 >
 </field>
+<field name="IME_FLAG_NAVIGATE_NEXT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="134217728"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IME_FLAG_NAVIGATE_PREVIOUS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="67108864"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="IME_FLAG_NO_ACCESSORY_ACTION"
  type="int"
  transient="false"
@@ -216409,6 +216596,17 @@
  visibility="public"
 >
 </field>
+<field name="IME_FLAG_NO_FULLSCREEN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33554432"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="IME_MASK_ACTION"
  type="int"
  transient="false"
@@ -245371,7 +245569,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
 </parameter>
 </method>
 </interface>
@@ -347444,7 +347642,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="toCopyIn" type="E[]">
+<parameter name="array" type="E[]">
 </parameter>
 </constructor>
 <method name="add"
@@ -347472,7 +347670,7 @@
 >
 <parameter name="index" type="int">
 </parameter>
-<parameter name="element" type="E">
+<parameter name="e" type="E">
 </parameter>
 </method>
 <method name="addAll"
@@ -347600,7 +347798,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="o" type="java.lang.Object">
+<parameter name="e" type="E">
+</parameter>
+<parameter name="index" type="int">
 </parameter>
 </method>
 <method name="indexOf"
@@ -347613,9 +347813,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="e" type="E">
-</parameter>
-<parameter name="index" type="int">
+<parameter name="o" type="java.lang.Object">
 </parameter>
 </method>
 <method name="isEmpty"
@@ -347650,7 +347848,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="o" type="java.lang.Object">
+<parameter name="e" type="E">
+</parameter>
+<parameter name="index" type="int">
 </parameter>
 </method>
 <method name="lastIndexOf"
@@ -347663,9 +347863,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="e" type="E">
-</parameter>
-<parameter name="index" type="int">
+<parameter name="o" type="java.lang.Object">
 </parameter>
 </method>
 <method name="listIterator"
@@ -347756,7 +347954,7 @@
 >
 <parameter name="index" type="int">
 </parameter>
-<parameter name="element" type="E">
+<parameter name="e" type="E">
 </parameter>
 </method>
 <method name="size"
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 37c8ad0..b5fddfa 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -389,11 +389,13 @@
             if (err == 0) {
                 observer.waitForCompletion();
                 sets = observer.sets;
-                for (RestoreSet s : sets) {
-                    if (s.token == token) {
-                        System.out.println("Scheduling restore: " + s.name);
-                        didRestore = (mRestore.restoreAll(token, observer) == 0);
-                        break;
+                if (sets != null) {
+                    for (RestoreSet s : sets) {
+                        if (s.token == token) {
+                            System.out.println("Scheduling restore: " + s.name);
+                            didRestore = (mRestore.restoreAll(token, observer) == 0);
+                            break;
+                        }
                     }
                 }
             }
diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java
index 1741e60..2242462 100644
--- a/core/java/android/animation/KeyframeSet.java
+++ b/core/java/android/animation/KeyframeSet.java
@@ -28,12 +28,18 @@
 
     private int mNumKeyframes;
 
-    ArrayList<Keyframe> mKeyframes;
+    Keyframe mFirstKeyframe;
+    Keyframe mLastKeyframe;
+    TimeInterpolator mInterpolator; // only used in the 2-keyframe case
+    ArrayList<Keyframe> mKeyframes; // only used when there are not 2 keyframes
 
     public KeyframeSet(Keyframe... keyframes) {
+        mNumKeyframes = keyframes.length;
         mKeyframes = new ArrayList<Keyframe>();
         mKeyframes.addAll(Arrays.asList(keyframes));
-        mNumKeyframes = mKeyframes.size();
+        mFirstKeyframe = mKeyframes.get(0);
+        mLastKeyframe = mKeyframes.get(mNumKeyframes - 1);
+        mInterpolator = mLastKeyframe.getInterpolator();
     }
 
     public static KeyframeSet ofInt(int... values) {
@@ -125,32 +131,40 @@
      * @return The animated value.
      */
     public Object getValue(float fraction, TypeEvaluator evaluator) {
-        // TODO: special-case 2-keyframe common case
+
+        // Special-case optimization for the common case of only two keyframes
+        if (mNumKeyframes == 2) {
+            if (mInterpolator != null) {
+                fraction = mInterpolator.getInterpolation(fraction);
+            }
+            return evaluator.evaluate(fraction, mFirstKeyframe.getValue(),
+                    mLastKeyframe.getValue());
+        }
 
         if (fraction <= 0f) {
-            final Keyframe prevKeyframe = mKeyframes.get(0);
             final Keyframe nextKeyframe = mKeyframes.get(1);
             final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
             if (interpolator != null) {
                 fraction = interpolator.getInterpolation(fraction);
             }
-            float intervalFraction = (fraction - prevKeyframe.getFraction()) /
-                (nextKeyframe.getFraction() - prevKeyframe.getFraction());
-            return evaluator.evaluate(intervalFraction, prevKeyframe.getValue(),
+            final float prevFraction = mFirstKeyframe.getFraction();
+            float intervalFraction = (fraction - prevFraction) /
+                (nextKeyframe.getFraction() - prevFraction);
+            return evaluator.evaluate(intervalFraction, mFirstKeyframe.getValue(),
                     nextKeyframe.getValue());
         } else if (fraction >= 1f) {
             final Keyframe prevKeyframe = mKeyframes.get(mNumKeyframes - 2);
-            final Keyframe nextKeyframe = mKeyframes.get(mNumKeyframes - 1);
-            final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
+            final TimeInterpolator interpolator = mLastKeyframe.getInterpolator();
             if (interpolator != null) {
                 fraction = interpolator.getInterpolation(fraction);
             }
-            float intervalFraction = (fraction - prevKeyframe.getFraction()) /
-                (nextKeyframe.getFraction() - prevKeyframe.getFraction());
+            final float prevFraction = prevKeyframe.getFraction();
+            float intervalFraction = (fraction - prevFraction) /
+                (mLastKeyframe.getFraction() - prevFraction);
             return evaluator.evaluate(intervalFraction, prevKeyframe.getValue(),
-                    nextKeyframe.getValue());
+                    mLastKeyframe.getValue());
         }
-        Keyframe prevKeyframe = mKeyframes.get(0);
+        Keyframe prevKeyframe = mFirstKeyframe;
         for (int i = 1; i < mNumKeyframes; ++i) {
             Keyframe nextKeyframe = mKeyframes.get(i);
             if (fraction < nextKeyframe.getFraction()) {
@@ -158,14 +172,15 @@
                 if (interpolator != null) {
                     fraction = interpolator.getInterpolation(fraction);
                 }
-                float intervalFraction = (fraction - prevKeyframe.getFraction()) /
-                    (nextKeyframe.getFraction() - prevKeyframe.getFraction());
+                final float prevFraction = prevKeyframe.getFraction();
+                float intervalFraction = (fraction - prevFraction) /
+                    (nextKeyframe.getFraction() - prevFraction);
                 return evaluator.evaluate(intervalFraction, prevKeyframe.getValue(),
                         nextKeyframe.getValue());
             }
             prevKeyframe = nextKeyframe;
         }
-        // shouldn't get here
-        return mKeyframes.get(mNumKeyframes - 1).getValue();
+        // shouldn't reach here
+        return mLastKeyframe.getValue();
     }
 }
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 7427651..5b8c91d 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -376,9 +376,14 @@
      */
     @Override
     public void setTarget(Object target) {
-        mTarget = target;
-        // New property/values/target should cause re-initialization prior to starting
-        mInitialized = false;
+        if (mTarget != target) {
+            mTarget = target;
+            if (mTarget  != null && target != null && mTarget.getClass() == target.getClass()) {
+                return;
+            }
+            // New target type should cause re-initialization prior to starting
+            mInitialized = false;
+        }
     }
 
     @Override
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index ad8c971..a0b70b5 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1142,7 +1142,7 @@
         switch (mPlayingState) {
         case RUNNING:
         case SEEKED:
-            float fraction = (float)(currentTime - mStartTime) / mDuration;
+            float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
             if (fraction >= 1f) {
                 if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
                     // Time to repeat
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 66038d8..b359ce6 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -299,7 +299,7 @@
      * 
      * <p>Example: setDisplayOptions(0, DISPLAY_SHOW_HOME) will disable the
      * {@link #DISPLAY_SHOW_HOME} option.
-     * setDisplayOptions(DISPLAY_SHOW_HOME, DISPLAY_HIDE_HOME | DISPLAY_USE_LOGO)
+     * setDisplayOptions(DISPLAY_SHOW_HOME, DISPLAY_SHOW_HOME | DISPLAY_USE_LOGO)
      * will enable {@link #DISPLAY_SHOW_HOME} and disable {@link #DISPLAY_USE_LOGO}.
      * 
      * @param options A combination of the bits defined by the DISPLAY_ constants
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 45ce860..b9ac848 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -27,6 +27,14 @@
  * AndroidManifest.xml's &lt;application&gt; tag, which will cause that class
  * to be instantiated for you when the process for your application/package is
  * created.
+ * 
+ * <p class="note">There is normally no need to subclass Application.  In
+ * most situation, static singletons can provide the same functionality in a
+ * more modular way.  If your singleton needs a global context (for example
+ * to register broadcast receivers), the function to retrieve it can be
+ * given a {@link android.content.Context} which internally uses
+ * {@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
+ * when first constructing the singleton.</p>
  */
 public class Application extends ContextWrapper implements ComponentCallbacks {
     
@@ -46,12 +54,10 @@
     }
 
     /**
-     * Called when the application is stopping.  There are no more application
-     * objects running and the process will exit.  <em>Note: never depend on
-     * this method being called; in many cases an unneeded application process
-     * will simply be killed by the kernel without executing any application
-     * code.</em>
-     * If you override this method, be sure to call super.onTerminate().
+     * This method is for use in emulated process environments.  It will
+     * never be called on a production Android device, where processes are
+     * removed by simply killing them; no user code (including this callback)
+     * is executed when doing so.
      */
     public void onTerminate() {
     }
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 570e494..592a63b 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -272,6 +272,14 @@
      */
     public static final String EXTRA_DOWNLOAD_ID = "extra_download_id";
 
+    /**
+     * When clicks on multiple notifications are received, the following
+     * provides an array of download ids corresponding to the download notification that was
+     * clicked. It can be retrieved by the receiver of this
+     * Intent using {@link android.content.Intent#getLongArrayExtra(String)}.
+     */
+    public static final String EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS = "extra_click_download_ids";
+
     // this array must contain all public columns
     private static final String[] COLUMNS = new String[] {
         COLUMN_ID,
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index f27a15e..eaf1aee 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1027,6 +1027,16 @@
     }
 
     /**
+     * Called when this fragment's option menu items are no longer being
+     * included in the overall options menu.  Receiving this call means that
+     * the menu needed to be rebuilt, but this fragment's items were not
+     * included in the newly built menu (its {@link #onCreateOptionsMenu(Menu, MenuInflater)}
+     * was not called).
+     */
+    public void onDestroyOptionsMenu() {
+    }
+    
+    /**
      * This hook is called whenever an item in your options menu is selected.
      * The default implementation simply returns false to have the normal
      * processing happen (calling the item's Runnable or sending a message to
diff --git a/core/java/android/app/FragmentBreadCrumbs.java b/core/java/android/app/FragmentBreadCrumbs.java
index 22e0747..e924c1c 100644
--- a/core/java/android/app/FragmentBreadCrumbs.java
+++ b/core/java/android/app/FragmentBreadCrumbs.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.animation.LayoutTransition;
 import android.app.FragmentManager.BackStackEntry;
 import android.content.Context;
 import android.util.AttributeSet;
@@ -69,6 +70,7 @@
         addView(mContainer);
         a.getFragmentManager().addOnBackStackChangedListener(this);
         updateCrumbs();
+        setLayoutTransition(new LayoutTransition());
     }
 
     /**
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 45f9325..512ca16 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -268,6 +268,7 @@
     ArrayList<Fragment> mAdded;
     ArrayList<Integer> mAvailIndices;
     ArrayList<BackStackRecord> mBackStack;
+    ArrayList<Fragment> mCreatedMenus;
     
     // Must be accessed while locked.
     ArrayList<BackStackRecord> mBackStackIndices;
@@ -1325,15 +1326,32 @@
     
     public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         boolean show = false;
+        ArrayList<Fragment> newMenus = null;
         if (mActive != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
                 if (f != null && !f.mHidden && f.mHasMenu) {
                     show = true;
                     f.onCreateOptionsMenu(menu, inflater);
+                    if (newMenus == null) {
+                        newMenus = new ArrayList<Fragment>();
+                    }
+                    newMenus.add(f);
                 }
             }
         }
+        
+        if (mCreatedMenus != null) {
+            for (int i=0; i<mCreatedMenus.size(); i++) {
+                Fragment f = mCreatedMenus.get(i);
+                if (newMenus == null || !newMenus.contains(f)) {
+                    f.onDestroyOptionsMenu();
+                }
+            }
+        }
+        
+        mCreatedMenus = newMenus;
+        
         return show;
     }
     
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index 0c8e4d9..138e7f2 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -773,6 +773,7 @@
 
                 case CONNECT_HFP_INCOMING:
                     transitionTo(mIncomingHandsfree);
+                    break;
                 case CONNECT_A2DP_INCOMING:
                     transitionTo(mIncomingA2dp);
 
diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java
index 72ec469..841c8f4 100644
--- a/core/java/android/content/UriMatcher.java
+++ b/core/java/android/content/UriMatcher.java
@@ -25,8 +25,8 @@
 /**
 Utility class to aid in matching URIs in content providers.
 
-<p>To use this class, build up a tree of UriMatcher objects.
-Typically, it looks something like this:
+<p>To use this class, build up a tree of <code>UriMatcher</code> objects.
+For example:
 <pre>
     private static final int PEOPLE = 1;
     private static final int PEOPLE_ID = 2;
@@ -48,36 +48,35 @@
     private static final int CALLS_ID = 12;
     private static final int CALLS_FILTER = 15;
 
-    private static final UriMatcher sURIMatcher = new UriMatcher();
+    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
 
     static
     {
-        sURIMatcher.addURI("contacts", "/people", PEOPLE);
-        sURIMatcher.addURI("contacts", "/people/#", PEOPLE_ID);
-        sURIMatcher.addURI("contacts", "/people/#/phones", PEOPLE_PHONES);
-        sURIMatcher.addURI("contacts", "/people/#/phones/#", PEOPLE_PHONES_ID);
-        sURIMatcher.addURI("contacts", "/people/#/contact_methods", PEOPLE_CONTACTMETHODS);
-        sURIMatcher.addURI("contacts", "/people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID);
-        sURIMatcher.addURI("contacts", "/deleted_people", DELETED_PEOPLE);
-        sURIMatcher.addURI("contacts", "/phones", PHONES);
-        sURIMatcher.addURI("contacts", "/phones/filter/*", PHONES_FILTER);
-        sURIMatcher.addURI("contacts", "/phones/#", PHONES_ID);
-        sURIMatcher.addURI("contacts", "/contact_methods", CONTACTMETHODS);
-        sURIMatcher.addURI("contacts", "/contact_methods/#", CONTACTMETHODS_ID);
-        sURIMatcher.addURI("call_log", "/calls", CALLS);
-        sURIMatcher.addURI("call_log", "/calls/filter/*", CALLS_FILTER);
-        sURIMatcher.addURI("call_log", "/calls/#", CALLS_ID);
+        sURIMatcher.addURI("contacts", "people", PEOPLE);
+        sURIMatcher.addURI("contacts", "people/#", PEOPLE_ID);
+        sURIMatcher.addURI("contacts", "people/#/phones", PEOPLE_PHONES);
+        sURIMatcher.addURI("contacts", "people/#/phones/#", PEOPLE_PHONES_ID);
+        sURIMatcher.addURI("contacts", "people/#/contact_methods", PEOPLE_CONTACTMETHODS);
+        sURIMatcher.addURI("contacts", "people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID);
+        sURIMatcher.addURI("contacts", "deleted_people", DELETED_PEOPLE);
+        sURIMatcher.addURI("contacts", "phones", PHONES);
+        sURIMatcher.addURI("contacts", "phones/filter/*", PHONES_FILTER);
+        sURIMatcher.addURI("contacts", "phones/#", PHONES_ID);
+        sURIMatcher.addURI("contacts", "contact_methods", CONTACTMETHODS);
+        sURIMatcher.addURI("contacts", "contact_methods/#", CONTACTMETHODS_ID);
+        sURIMatcher.addURI("call_log", "calls", CALLS);
+        sURIMatcher.addURI("call_log", "calls/filter/*", CALLS_FILTER);
+        sURIMatcher.addURI("call_log", "calls/#", CALLS_ID);
     }
 </pre>
-<p>Then when you need to match match against a URI, call {@link #match}, providing
-the tokenized url you've been given, and the value you want if there isn't
-a match.  You can use the result to build a query, return a type, insert or
-delete a row, or whatever you need, without duplicating all of the if-else
-logic you'd otherwise need.  Like this:
+<p>Then when you need to match against a URI, call {@link #match}, providing
+the URL that you have been given.  You can use the result to build a query,
+return a type, insert or delete a row, or whatever you need, without duplicating
+all of the if-else logic that you would otherwise need.  For example:
 <pre>
-    public String getType(String[] url)
+    public String getType(Uri url)
     {
-        int match = sURIMatcher.match(url, NO_MATCH);
+        int match = sURIMatcher.match(url);
         switch (match)
         {
             case PEOPLE:
@@ -93,19 +92,20 @@
         }
     }
 </pre>
-instead of
+instead of:
 <pre>
-    public String getType(String[] url)
+    public String getType(Uri url)
     {
-        if (url.length >= 2) {
-            if (url[1].equals("people")) {
-                if (url.length == 2) {
+        List<String> pathSegments = url.getPathSegments();
+        if (pathSegments.size() >= 2) {
+            if ("people".equals(pathSegments.get(1))) {
+                if (pathSegments.size() == 2) {
                     return "vnd.android.cursor.dir/person";
-                } else if (url.length == 3) {
+                } else if (pathSegments.size() == 3) {
                     return "vnd.android.cursor.item/person";
 ... snip ...
                     return "vnd.android.cursor.dir/snail-mail";
-                } else if (url.length == 3) {
+                } else if (pathSegments.size() == 3) {
                     return "vnd.android.cursor.item/snail-mail";
                 }
             }
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index 44f30f7..01fc010 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -31,7 +31,6 @@
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.InputMethodSession;
-import android.view.inputmethod.EditorInfo;
 
 class IInputMethodSessionWrapper extends IInputMethodSession.Stub
         implements HandlerCaller.Callback {
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 24ea7d2..17c9ee7 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -70,6 +70,7 @@
     final WeakReference<AbstractInputMethodService> mTarget;
     final HandlerCaller mCaller;
     final WeakReference<InputMethod> mInputMethod;
+    final int mTargetSdkVersion;
     
     static class Notifier {
         boolean notified;
@@ -102,6 +103,7 @@
         mTarget = new WeakReference<AbstractInputMethodService>(context);
         mCaller = new HandlerCaller(context.getApplicationContext(), this);
         mInputMethod = new WeakReference<InputMethod>(inputMethod);
+        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
     }
 
     public InputMethod getInternalInputMethod() {
@@ -151,7 +153,9 @@
                 IInputContext inputContext = (IInputContext)args.arg1;
                 InputConnection ic = inputContext != null
                         ? new InputConnectionWrapper(inputContext) : null;
-                inputMethod.startInput(ic, (EditorInfo)args.arg2);
+                EditorInfo info = (EditorInfo)args.arg2;
+                info.makeCompatible(mTargetSdkVersion);
+                inputMethod.startInput(ic, info);
                 return;
             }
             case DO_RESTART_INPUT: {
@@ -159,7 +163,9 @@
                 IInputContext inputContext = (IInputContext)args.arg1;
                 InputConnection ic = inputContext != null
                         ? new InputConnectionWrapper(inputContext) : null;
-                inputMethod.restartInput(ic, (EditorInfo)args.arg2);
+                EditorInfo info = (EditorInfo)args.arg2;
+                info.makeCompatible(mTargetSdkVersion);
+                inputMethod.restartInput(ic, info);
                 return;
             }
             case DO_CREATE_SESSION: {
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index c0743cfe..a1f2b63 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1945,6 +1945,8 @@
                 return getText(com.android.internal.R.string.ime_action_next);
             case EditorInfo.IME_ACTION_DONE:
                 return getText(com.android.internal.R.string.ime_action_done);
+            case EditorInfo.IME_ACTION_PREVIOUS:
+                return getText(com.android.internal.R.string.ime_action_previous);
             default:
                 return getText(com.android.internal.R.string.ime_action_default);
         }
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 0c6a237..97c957d 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -825,7 +825,7 @@
 
     /**
      * Called when the user selects an item in the header list.  The default
-     * implementation will call either {@link #startWithFragment(String, Bundle)}
+     * implementation will call either {@link #startWithFragment(String, Bundle, Fragment, int)}
      * or {@link #switchToHeader(Header)} as appropriate.
      *
      * @param header The header that was selected.
@@ -834,7 +834,7 @@
     public void onHeaderClick(Header header, int position) {
         if (header.fragment != null) {
             if (mSinglePane) {
-                startWithFragment(header.fragment, header.fragmentArguments);
+                startWithFragment(header.fragment, header.fragmentArguments, null, 0);
             } else {
                 switchToHeader(header);
             }
@@ -852,13 +852,18 @@
      * @param fragmentName The name of the fragment to display.
      * @param args Optional arguments to supply to the fragment.
      */
-    public void startWithFragment(String fragmentName, Bundle args) {
+    public void startWithFragment(String fragmentName, Bundle args,
+            Fragment resultTo, int resultRequestCode) {
         Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.setClass(this, getClass());
         intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
         intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
         intent.putExtra(EXTRA_NO_HEADERS, true);
-        startActivity(intent);
+        if (resultTo == null) {
+            startActivity(intent);
+        } else {
+            resultTo.startActivityForResult(intent, resultRequestCode);
+        }
     }
 
     /**
@@ -923,9 +928,15 @@
      * @param header The new header to display.
      */
     public void switchToHeader(Header header) {
-        int direction = mHeaders.indexOf(header) - mHeaders.indexOf(mCurHeader);
-        switchToHeaderInner(header.fragment, header.fragmentArguments, direction);
-        setSelectedHeader(header);
+        if (mCurHeader == header) {
+            // This is the header we are currently displaying.  Just make sure
+            // to pop the stack up to its root state.
+            getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
+        } else {
+            int direction = mHeaders.indexOf(header) - mHeaders.indexOf(mCurHeader);
+            switchToHeaderInner(header.fragment, header.fragmentArguments, direction);
+            setSelectedHeader(header);
+        }
     }
 
     Header findBestMatchingHeader(Header cur, ArrayList<Header> from) {
@@ -982,7 +993,7 @@
      */
     public void startPreferenceFragment(Fragment fragment, boolean push) {
         FragmentTransaction transaction = getFragmentManager().openTransaction();
-        startPreferenceFragment(fragment, transaction);
+        transaction.replace(com.android.internal.R.id.prefs, fragment);
         if (push) {
             transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
             transaction.addToBackStack(BACK_STACK_PREFS);
@@ -993,25 +1004,74 @@
     }
 
     /**
-     * Start a new fragment.
-     *
-     * @param fragment The fragment to start
-     * @param ft The FragmentTransaction in which to perform this operation.
-     * Will not be added to the back stack or committed for you; you use do that.
+     * Start a new fragment containing a preference panel.  If the prefences
+     * are being displayed in multi-pane mode, the given fragment class will
+     * be instantiated and placed in the appropriate pane.  If running in
+     * single-pane mode, a new activity will be launched in which to show the
+     * fragment.
+     * 
+     * @param fragmentClass Full name of the class implementing the fragment.
+     * @param args Any desired arguments to supply to the fragment.
+     * @param titleRes Optional resource identifier of the title of this
+     * fragment.
+     * @param titleText Optional text of the title of this fragment.
+     * @param resultTo Optional fragment that result data should be sent to.
+     * If non-null, resultTo.onActivityResult() will be called when this
+     * preference panel is done.  The launched panel must use
+     * {@link #finishPreferencePanel(Fragment, int, Intent)} when done.
+     * @param resultRequestCode If resultTo is non-null, this is the caller's
+     * request code to be received with the resut.
      */
-    public void startPreferenceFragment(Fragment fragment, FragmentTransaction ft) {
-        ft.replace(com.android.internal.R.id.prefs, fragment);
+    public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
+            CharSequence titleText, Fragment resultTo, int resultRequestCode) {
+        if (mSinglePane) {
+            startWithFragment(fragmentClass, args, resultTo, resultRequestCode);
+        } else {
+            Fragment f = Fragment.instantiate(this, fragmentClass, args);
+            if (resultTo != null) {
+                f.setTargetFragment(resultTo, resultRequestCode);
+            }
+            FragmentTransaction transaction = getFragmentManager().openTransaction();
+            transaction.replace(com.android.internal.R.id.prefs, f);
+            if (titleRes != 0) {
+                transaction.setBreadCrumbTitle(titleRes);
+            } else if (titleText != null) {
+                transaction.setBreadCrumbTitle(titleText);
+            }
+            transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+            transaction.addToBackStack(BACK_STACK_PREFS);
+            transaction.commit();
+        }
     }
-
+    
+    /**
+     * Called by a preference panel fragment to finish itself.
+     * 
+     * @param caller The fragment that is asking to be finished.
+     * @param resultCode Optional result code to send back to the original
+     * launching fragment.
+     * @param resultData Optional result data to send back to the original
+     * launching fragment.
+     */
+    public void finishPreferencePanel(Fragment caller, int resultCode, Intent resultData) {
+        if (mSinglePane) {
+            setResult(resultCode, resultData);
+            finish();
+        } else {
+            if (caller != null) {
+                if (caller.getTargetFragment() != null) {
+                    caller.getTargetFragment().onActivityResult(caller.getTargetRequestCode(),
+                            resultCode, resultData);
+                }
+            }
+            // XXX be smarter about popping the stack.
+            onBackPressed();
+        }
+    }
+    
     @Override
     public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
-        Fragment f = Fragment.instantiate(this, pref.getFragment(), pref.getExtras());
-        FragmentTransaction transaction = getFragmentManager().openTransaction();
-        startPreferenceFragment(f, transaction);
-        transaction.setBreadCrumbTitle(pref.getTitle());
-        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
-        transaction.addToBackStack(BACK_STACK_PREFS);
-        transaction.commit();
+        startPreferencePanel(pref.getFragment(), pref.getExtras(), 0, pref.getTitle(), null, 0);
         return true;
     }
 
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 7289012..ec8f031 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -385,11 +385,23 @@
         // Allow 3 seconds for profiles to gracefully disconnect
         // TODO: Introduce a callback mechanism so that each profile can notify
         // BluetoothService when it is done shutting down
+        disconnectDevices();
+
         mHandler.sendMessageDelayed(
                 mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000);
         return true;
     }
 
+    private synchronized void disconnectDevices() {
+        // Disconnect devices handled by BluetoothService.
+        for (BluetoothDevice device: getConnectedInputDevices()) {
+            disconnectInputDevice(device);
+        }
+
+        for (BluetoothDevice device: getConnectedPanDevices()) {
+            disconnectPanDevice(device);
+        }
+    }
 
     private synchronized void finishDisable(boolean saveSetting) {
         if (mBluetoothState != BluetoothAdapter.STATE_TURNING_OFF) {
diff --git a/core/java/android/text/InputType.java b/core/java/android/text/InputType.java
index 8592221..7b8acd9 100644
--- a/core/java/android/text/InputType.java
+++ b/core/java/android/text/InputType.java
@@ -228,6 +228,28 @@
      */
     public static final int TYPE_TEXT_VARIATION_PHONETIC = 0x000000c0;
     
+    /**
+     * Variation of {@link #TYPE_CLASS_TEXT}: entering e-mail address inside
+     * of a web form.  This was added in
+     * {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An IME must target
+     * this API version or later to see this input type; if it doesn't, a request
+     * for this type will be seen as {@link #TYPE_TEXT_VARIATION_EMAIL_ADDRESS}
+     * when passed through {@link android.view.inputmethod.EditorInfo#makeCompatible(int)
+     * EditorInfo.makeCompatible(int)}.
+     */
+    public static final int TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS = 0x000000d0;
+
+    /**
+     * Variation of {@link #TYPE_CLASS_TEXT}: entering password inside
+     * of a web form.  This was added in
+     * {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An IME must target
+     * this API version or later to see this input type; if it doesn't, a request
+     * for this type will be seen as {@link #TYPE_TEXT_VARIATION_PASSWORD}
+     * when passed through {@link android.view.inputmethod.EditorInfo#makeCompatible(int)
+     * EditorInfo.makeCompatible(int)}.
+     */
+    public static final int TYPE_TEXT_VARIATION_WEB_PASSWORD = 0x000000e0;
+
     // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 87e03cf..ab97569 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6296,8 +6296,14 @@
             if (invalidateCache) {
                 mPrivateFlags &= ~DRAWING_CACHE_VALID;
             }
-            final ViewParent p = mParent;
             final AttachInfo ai = mAttachInfo;
+            final ViewParent p = mParent;
+            if (ai != null && ai.mHardwareAccelerated) {
+                // fast-track for GL-enabled applications; just invalidate the whole hierarchy
+                // with a null dirty rect, which tells the ViewRoot to redraw everything
+                p.invalidateChild(this, null);
+                return;
+            }
             if (p != null && ai != null) {
                 final Rect r = ai.mTmpInvalRect;
                 r.set(0, 0, mRight - mLeft, mBottom - mTop);
@@ -6321,7 +6327,8 @@
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public boolean isOpaque() {
-        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK;
+        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK &&
+                (mAlpha >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD);
     }
 
     private void computeOpaqueFlags() {
@@ -8618,7 +8625,11 @@
      */
     @RemotableViewMethod
     public void setBackgroundColor(int color) {
-        setBackgroundDrawable(new ColorDrawable(color));
+        if (mBGDrawable instanceof ColorDrawable) {
+            ((ColorDrawable) mBGDrawable).setColor(color);
+        } else {
+            setBackgroundDrawable(new ColorDrawable(color));
+        }
     }
 
     /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index b881bdd..aef13ad 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2101,6 +2101,8 @@
         final int cr = child.mRight;
         final int cb = child.mBottom;
 
+        final boolean childHasIdentityMatrix = child.hasIdentityMatrix();
+
         final int flags = mGroupFlags;
 
         if ((flags & FLAG_CLEAR_TRANSFORMATION) == FLAG_CLEAR_TRANSFORMATION) {
@@ -2182,7 +2184,7 @@
             }
         }
 
-        concatMatrix |= !child.hasIdentityMatrix();
+        concatMatrix |= !childHasIdentityMatrix;
 
         // Sets the flag as early as possible to allow draw() implementations
         // to call invalidate() successfully when doing animations
@@ -2231,40 +2233,41 @@
         }
 
         if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) {
-            int transX = 0;
-            int transY = 0;
+            if (transformToApply != null || !childHasIdentityMatrix) {
+                int transX = 0;
+                int transY = 0;
 
-            if (hasNoCache) {
-                transX = -sx;
-                transY = -sy;
-            }
+                if (hasNoCache) {
+                    transX = -sx;
+                    transY = -sy;
+                }
 
-            if (transformToApply != null) {
-                if (concatMatrix) {
-                    // Undo the scroll translation, apply the transformation matrix,
-                    // then redo the scroll translate to get the correct result.
+                if (transformToApply != null) {
+                    if (concatMatrix) {
+                        // Undo the scroll translation, apply the transformation matrix,
+                        // then redo the scroll translate to get the correct result.
+                        canvas.translate(-transX, -transY);
+                        canvas.concat(transformToApply.getMatrix());
+                        canvas.translate(transX, transY);
+                        mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
+                    }
+
+                    float transformAlpha = transformToApply.getAlpha();
+                    if (transformAlpha < 1.0f) {
+                        alpha *= transformToApply.getAlpha();
+                        mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
+                    }
+                }
+
+                if (!childHasIdentityMatrix) {
                     canvas.translate(-transX, -transY);
-                    canvas.concat(transformToApply.getMatrix());
+                    canvas.concat(child.getMatrix());
                     canvas.translate(transX, transY);
-                    mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
                 }
-
-                float transformAlpha = transformToApply.getAlpha();
-                if (transformAlpha < 1.0f) {
-                    alpha *= transformToApply.getAlpha();
-                    mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
-                }
-            }
-
-            if (!child.hasIdentityMatrix()) {
-                canvas.translate(-transX, -transY);
-                canvas.concat(child.getMatrix());
-                canvas.translate(transX, transY);
             }
 
             if (alpha < 1.0f) {
                 mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
-
                 if (hasNoCache) {
                     final int multipliedAlpha = (int) (255 * alpha);
                     if (!child.onSetAlpha(multipliedAlpha)) {
@@ -3209,19 +3212,6 @@
 
         final AttachInfo attachInfo = mAttachInfo;
         if (attachInfo != null) {
-            final int[] location = attachInfo.mInvalidateChildLocation;
-            location[CHILD_LEFT_INDEX] = child.mLeft;
-            location[CHILD_TOP_INDEX] = child.mTop;
-            Matrix childMatrix = child.getMatrix();
-            if (!childMatrix.isIdentity()) {
-                RectF boundingRect = attachInfo.mTmpTransformRect;
-                boundingRect.set(dirty);
-                childMatrix.mapRect(boundingRect);
-                dirty.set((int) boundingRect.left, (int) boundingRect.top,
-                        (int) (boundingRect.right + 0.5f),
-                        (int) (boundingRect.bottom + 0.5f));
-            }
-
             // If the child is drawing an animation, we want to copy this flag onto
             // ourselves and the parent to make sure the invalidate request goes
             // through
@@ -3229,45 +3219,95 @@
 
             // Check whether the child that requests the invalidate is fully opaque
             final boolean isOpaque = child.isOpaque() && !drawAnimation &&
-                    child.getAnimation() != null;
+                    child.getAnimation() == null;
             // Mark the child as dirty, using the appropriate flag
             // Make sure we do not set both flags at the same time
             final int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY;
 
-            do {
-                View view = null;
-                if (parent instanceof View) {
-                    view = (View) parent;
+            if (dirty == null) {
+                do {
+                    View view = null;
+                    if (parent instanceof View) {
+                        view = (View) parent;
+                        if ((view.mPrivateFlags & DIRTY_MASK) != 0) {
+                            // already marked dirty - we're done
+                            break;
+                        }
+                    }
+
+                    if (drawAnimation) {
+                        if (view != null) {
+                            view.mPrivateFlags |= DRAW_ANIMATION;
+                        } else if (parent instanceof ViewRoot) {
+                            ((ViewRoot) parent).mIsAnimating = true;
+                        }
+                    }
+
+                    if (parent instanceof ViewRoot) {
+                        ((ViewRoot) parent).invalidate();
+                        parent = null;
+                    } else if (view != null) {
+                        if ((mPrivateFlags & DRAWN) == DRAWN) {
+                            view.mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                            if (view != null && (view.mPrivateFlags & DIRTY_MASK) != DIRTY) {
+                                view.mPrivateFlags =
+                                        (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag;
+                            }
+                            parent = view.mParent;
+                        } else {
+                            parent = null;
+                        }
+                    }
+                } while (parent != null);
+            } else {
+                final int[] location = attachInfo.mInvalidateChildLocation;
+                location[CHILD_LEFT_INDEX] = child.mLeft;
+                location[CHILD_TOP_INDEX] = child.mTop;
+                Matrix childMatrix = child.getMatrix();
+                if (!childMatrix.isIdentity()) {
+                    RectF boundingRect = attachInfo.mTmpTransformRect;
+                    boundingRect.set(dirty);
+                    childMatrix.mapRect(boundingRect);
+                    dirty.set((int) boundingRect.left, (int) boundingRect.top,
+                            (int) (boundingRect.right + 0.5f),
+                            (int) (boundingRect.bottom + 0.5f));
                 }
 
-                if (drawAnimation) {
+                do {
+                    View view = null;
+                    if (parent instanceof View) {
+                        view = (View) parent;
+                    }
+
+                    if (drawAnimation) {
+                        if (view != null) {
+                            view.mPrivateFlags |= DRAW_ANIMATION;
+                        } else if (parent instanceof ViewRoot) {
+                            ((ViewRoot) parent).mIsAnimating = true;
+                        }
+                    }
+
+                    // If the parent is dirty opaque or not dirty, mark it dirty with the opaque
+                    // flag coming from the child that initiated the invalidate
+                    if (view != null && (view.mPrivateFlags & DIRTY_MASK) != DIRTY) {
+                        view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag;
+                    }
+
+                    parent = parent.invalidateChildInParent(location, dirty);
                     if (view != null) {
-                        view.mPrivateFlags |= DRAW_ANIMATION;
-                    } else if (parent instanceof ViewRoot) {
-                        ((ViewRoot) parent).mIsAnimating = true;
+                        // Account for transform on current parent
+                        Matrix m = view.getMatrix();
+                        if (!m.isIdentity()) {
+                            RectF boundingRect = attachInfo.mTmpTransformRect;
+                            boundingRect.set(dirty);
+                            m.mapRect(boundingRect);
+                            dirty.set((int) boundingRect.left, (int) boundingRect.top,
+                                    (int) (boundingRect.right + 0.5f),
+                                    (int) (boundingRect.bottom + 0.5f));
+                        }
                     }
-                }
-
-                // If the parent is dirty opaque or not dirty, mark it dirty with the opaque
-                // flag coming from the child that initiated the invalidate
-                if (view != null && (view.mPrivateFlags & DIRTY_MASK) != DIRTY) {
-                    view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag;
-                }
-
-                parent = parent.invalidateChildInParent(location, dirty);
-                if (view != null) {
-                    // Account for transform on current parent
-                    Matrix m = view.getMatrix();
-                    if (!m.isIdentity()) {
-                        RectF boundingRect = attachInfo.mTmpTransformRect;
-                        boundingRect.set(dirty);
-                        m.mapRect(boundingRect);
-                        dirty.set((int) boundingRect.left, (int) boundingRect.top,
-                                (int) (boundingRect.right + 0.5f),
-                                (int) (boundingRect.bottom + 0.5f));
-                    }
-                }
-            } while (parent != null);
+                } while (parent != null);
+            }
         }
     }
 
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 06261bb..22a7773 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -543,6 +543,11 @@
     public void invalidateChild(View child, Rect dirty) {
         checkThread();
         if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty);
+        if (dirty == null) {
+            // Fast invalidation for GL-enabled applications; GL must redraw everything
+            invalidate();
+            return;
+        }
         if (mCurScrollY != 0 || mTranslator != null) {
             mTempRect.set(dirty);
             dirty = mTempRect;
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 0b2d0f6..c657a1c 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -762,6 +762,12 @@
          */
         public static final int SOFT_INPUT_ADJUST_PAN = 0x20;
         
+        /** Adjustment option for {@link #softInputMode}: set to have a window
+         * not adjust for a shown input method.  The window will not be resized,
+         * and it will not be panned to make its focus visible.
+         */
+        public static final int SOFT_INPUT_ADJUST_NOTHING = 0x30;
+
         /**
          * Bit for {@link #softInputMode}: set when the user has navigated
          * forward to the window.  This is normally set automatically for
@@ -772,27 +778,6 @@
         public static final int SOFT_INPUT_IS_FORWARD_NAVIGATION = 0x100;
 
         /**
-         * Default value for {@link #screenBrightness} and {@link #buttonBrightness}
-         * indicating that the brightness value is not overridden for this window
-         * and normal brightness policy should be used.
-         */
-        public static final float BRIGHTNESS_OVERRIDE_NONE = -1.0f;
-
-        /**
-         * Value for {@link #screenBrightness} and {@link #buttonBrightness}
-         * indicating that the screen or button backlight brightness should be set
-         * to the lowest value when this window is in front.
-         */
-        public static final float BRIGHTNESS_OVERRIDE_OFF = 0.0f;
-
-        /**
-         * Value for {@link #screenBrightness} and {@link #buttonBrightness}
-         * indicating that the screen or button backlight brightness should be set
-         * to the hightest value when this window is in front.
-         */
-        public static final float BRIGHTNESS_OVERRIDE_FULL = 1.0f;
-
-        /**
          * Desired operating mode for any soft input area.  May any combination
          * of:
          * 
@@ -809,7 +794,17 @@
         public int softInputMode;
         
         /**
-         * Placement of window within the screen as per {@link Gravity}
+         * Placement of window within the screen as per {@link Gravity}.  Both
+         * {@link Gravity#apply(int, int, int, android.graphics.Rect, int, int,
+         * android.graphics.Rect) Gravity.apply} and
+         * {@link Gravity#applyDisplay(int, android.graphics.Rect, android.graphics.Rect)
+         * Gravity.applyDisplay} are used during window layout, with this value
+         * given as the desired gravity.  For example you can specify
+         * {@link Gravity#DISPLAY_CLIP_HORIZONTAL Gravity.DISPLAY_CLIP_HORIZONTAL} and
+         * {@link Gravity#DISPLAY_CLIP_VERTICAL Gravity.DISPLAY_CLIP_VERTICAL} here
+         * to control the behavior of
+         * {@link Gravity#applyDisplay(int, android.graphics.Rect, android.graphics.Rect)
+         * Gravity.applyDisplay}.
          *
          * @see Gravity
          */
@@ -817,13 +812,19 @@
     
         /**
          * The horizontal margin, as a percentage of the container's width,
-         * between the container and the widget.
+         * between the container and the widget.  See
+         * {@link Gravity#apply(int, int, int, android.graphics.Rect, int, int,
+         * android.graphics.Rect) Gravity.apply} for how this is used.  This
+         * field is added with {@link #x} to supply the <var>xAdj</var> parameter.
          */
         public float horizontalMargin;
     
         /**
          * The vertical margin, as a percentage of the container's height,
-         * between the container and the widget.
+         * between the container and the widget.  See
+         * {@link Gravity#apply(int, int, int, android.graphics.Rect, int, int,
+         * android.graphics.Rect) Gravity.apply} for how this is used.  This
+         * field is added with {@link #y} to supply the <var>yAdj</var> parameter.
          */
         public float verticalMargin;
     
@@ -852,6 +853,27 @@
          * dim.
          */
         public float dimAmount = 1.0f;
+
+        /**
+         * Default value for {@link #screenBrightness} and {@link #buttonBrightness}
+         * indicating that the brightness value is not overridden for this window
+         * and normal brightness policy should be used.
+         */
+        public static final float BRIGHTNESS_OVERRIDE_NONE = -1.0f;
+
+        /**
+         * Value for {@link #screenBrightness} and {@link #buttonBrightness}
+         * indicating that the screen or button backlight brightness should be set
+         * to the lowest value when this window is in front.
+         */
+        public static final float BRIGHTNESS_OVERRIDE_OFF = 0.0f;
+
+        /**
+         * Value for {@link #screenBrightness} and {@link #buttonBrightness}
+         * indicating that the screen or button backlight brightness should be set
+         * to the hightest value when this window is in front.
+         */
+        public static final float BRIGHTNESS_OVERRIDE_FULL = 1.0f;
     
         /**
          * This can be used to override the user's preferred brightness of
@@ -1162,14 +1184,22 @@
             sb.append('x');
             sb.append((height== MATCH_PARENT ?"fill":(height==WRAP_CONTENT?"wrap":height)));
             sb.append(")");
-            if (softInputMode != 0) {
-                sb.append(" sim=#");
-                sb.append(Integer.toHexString(softInputMode));
+            if (horizontalMargin != 0) {
+                sb.append(" hm=");
+                sb.append(horizontalMargin);
+            }
+            if (verticalMargin != 0) {
+                sb.append(" vm=");
+                sb.append(verticalMargin);
             }
             if (gravity != 0) {
                 sb.append(" gr=#");
                 sb.append(Integer.toHexString(gravity));
             }
+            if (softInputMode != 0) {
+                sb.append(" sim=#");
+                sb.append(Integer.toHexString(softInputMode));
+            }
             sb.append(" ty=");
             sb.append(type);
             sb.append(" fl=#");
@@ -1184,6 +1214,18 @@
                 sb.append(" or=");
                 sb.append(screenOrientation);
             }
+            if (alpha != 1.0f) {
+                sb.append(" alpha=");
+                sb.append(alpha);
+            }
+            if (screenBrightness != BRIGHTNESS_OVERRIDE_NONE) {
+                sb.append(" sbrt=");
+                sb.append(screenBrightness);
+            }
+            if (buttonBrightness != BRIGHTNESS_OVERRIDE_NONE) {
+                sb.append(" bbrt=");
+                sb.append(buttonBrightness);
+            }
             if ((flags & FLAG_COMPATIBLE_WINDOW) != 0) {
                 sb.append(" compatible=true");
             }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 1fd31a3..1a341e1 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -544,16 +544,18 @@
      * Generally, it's best to keep as little as possible in the queue thread
      * because it's the most fragile.
      * @param whenNanos The event time in uptime nanoseconds.
+     * @param action The key event action.
+     * @param flags The key event flags.
      * @param keyCode The key code.
-     * @param down True if the key is down.
+     * @param scanCode The key's scan code.
      * @param policyFlags The policy flags associated with the key.
      * @param isScreenOn True if the screen is already on
      *
      * @return The bitwise or of the {@link #ACTION_PASS_TO_USER},
      *          {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
      */
-    public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, int policyFlags,
-            boolean isScreenOn);
+    public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags,
+            int keyCode, int scanCode, int policyFlags, boolean isScreenOn);
     
     /**
      * Called from the input dispatcher thread before a key is dispatched to a window.
@@ -571,6 +573,7 @@
      * @param action The key event action.
      * @param flags The key event flags.
      * @param keyCode The key code.
+     * @param scanCode The key's scan code.
      * @param metaState bit mask of meta keys that are held.
      * @param repeatCount Number of times a key down has repeated.
      * @param policyFlags The policy flags associated with the key.
@@ -578,7 +581,7 @@
      * not be further dispatched.
      */
     public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
-            int keyCode, int metaState, int repeatCount, int policyFlags);
+            int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags);
 
     /**
      * Called when layout of the windows is about to start.
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index b98dcd2..300e5d6 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -94,6 +94,45 @@
     public static final int IME_ACTION_DONE = 0x00000006;
     
     /**
+     * Bits of {@link #IME_MASK_ACTION}: Like {@link #IME_ACTION_NEXT}, but
+     * for moving to the previous field.  This will normally not be used to
+     * specify an action (since it precludes {@link #IME_ACTION_NEXT}, but
+     * can be returned to the app if it sets {@link #IME_FLAG_NAVIGATE_PREVIOUS}.
+     */
+    public static final int IME_ACTION_PREVIOUS = 0x00000007;
+
+    /**
+     * Flag of {@link #imeOptions}: used to request that the IME never go
+     * into fullscreen mode.  Applications need to be aware that the flag is not
+     * a guarantee, and not all IMEs will respect it.
+     */
+    public static final int IME_FLAG_NO_FULLSCREEN = 0x2000000;
+
+    /**
+     * Flag of {@link #imeOptions}: like {@link #IME_FLAG_NAVIGATE_NEXT}, but
+     * specifies there is something interesting that a backward navigation
+     * can focus on.  If the user selects the IME's facility to backward
+     * navigate, this will show up in the application as an {@link #IME_ACTION_PREVIOUS}
+     * at {@link InputConnection#performEditorAction(int)
+     * InputConnection.performEditorAction(int)}.
+     */
+    public static final int IME_FLAG_NAVIGATE_PREVIOUS = 0x4000000;
+
+    /**
+     * Flag of {@link #imeOptions}: used to specify that there is something
+     * interesting that a forward navigation can focus on. This is like using
+     * {@link #IME_ACTION_NEXT}, except allows the IME to be multiline (with
+     * an enter key) as well as provide forward navigation.  Note that some
+     * IMEs may not be able to do this, especially when running on a small
+     * screen where there is little space.  In that case it does not need to
+     * present a UI for this option.  Like {@link #IME_ACTION_NEXT}, if the
+     * user selects the IME's facility to forward navigate, this will show up
+     * in the application at {@link InputConnection#performEditorAction(int)
+     * InputConnection.performEditorAction(int)}.
+     */
+    public static final int IME_FLAG_NAVIGATE_NEXT = 0x8000000;
+
+    /**
      * Flag of {@link #imeOptions}: used to specify that the IME does not need
      * to show its extracted text UI.  For input methods that may be fullscreen,
      * often when in landscape mode, this allows them to be smaller and let part
@@ -129,14 +168,6 @@
     public static final int IME_FLAG_NO_ENTER_ACTION = 0x40000000;
 
     /**
-     * Flag of {@link #imeOptions}: used to request that the IME never go
-     * into fullscreen mode.  Applications need to be aware that the flag is not
-     * a guarantee, and not all IMEs will respect it.
-     * @hide
-     */
-    public static final int IME_FLAG_NO_FULLSCREEN = 0x80000000;
-
-    /**
      * Generic unspecified type for {@link #imeOptions}.
      */
     public static final int IME_NULL = 0x00000000;
@@ -240,6 +271,34 @@
     public Bundle extras;
     
     /**
+     * Ensure that the data in this EditorInfo is compatible with an application
+     * that was developed against the given target API version.  This can
+     * impact the following input types:
+     * {@link InputType#TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS},
+     * {@link InputType#TYPE_TEXT_VARIATION_WEB_PASSWORD}.
+     *
+     * <p>This is called by the framework for input method implementations;
+     * you should not generally need to call it yourself.
+     *
+     * @param targetSdkVersion The API version number that the compatible
+     * application was developed against.
+     */
+    public final void makeCompatible(int targetSdkVersion) {
+        if (targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
+            switch (inputType&(TYPE_MASK_CLASS|TYPE_MASK_VARIATION)) {
+                case TYPE_CLASS_TEXT|TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS:
+                    inputType = TYPE_CLASS_TEXT|TYPE_TEXT_VARIATION_EMAIL_ADDRESS
+                            | (inputType&(~TYPE_MASK_FLAGS));
+                    break;
+                case TYPE_CLASS_TEXT|TYPE_TEXT_VARIATION_WEB_PASSWORD:
+                    inputType = TYPE_CLASS_TEXT|TYPE_TEXT_VARIATION_PASSWORD
+                            | (inputType&(~TYPE_MASK_FLAGS));
+                    break;
+            }
+        }
+    }
+
+    /**
      * Write debug output of this object.
      */
     public void dump(Printer pw, String prefix) {
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 3bcd483a4..14dc61d 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -370,6 +370,7 @@
             int candEnd = EditableInputConnection.getComposingSpanEnd(sp);
             imm.updateSelection(this, selStart, selEnd, candStart, candEnd);
         }
+        updateCursorControllerPositions();
     }
 
     @Override
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 72b4e36..f5affe5 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3477,7 +3477,9 @@
         if (AUTO_REDRAW_HACK && mAutoRedraw) {
             invalidate();
         }
-        if (inEditingMode()) mWebTextView.onDrawSubstitute();
+        if (inEditingMode()) {
+            mWebTextView.onDrawSubstitute();
+        }
         mWebViewCore.signalRepaintDone();
 
         // paint the highlight in the end
diff --git a/core/java/android/widget/AbsoluteLayout.java b/core/java/android/widget/AbsoluteLayout.java
index b829655..970cbe3 100644
--- a/core/java/android/widget/AbsoluteLayout.java
+++ b/core/java/android/widget/AbsoluteLayout.java
@@ -187,7 +187,7 @@
          * </ul>
          *
          * @param c the application environment
-         * @param attrs the set of attributes fom which to extract the layout
+         * @param attrs the set of attributes from which to extract the layout
          *              parameters values
          */
         public LayoutParams(Context c, AttributeSet attrs) {
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 39b1377..be1234d 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -413,33 +413,46 @@
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
         int keyCode = event.getKeyCode();
-        if (event.getRepeatCount() == 0 && event.isDown() && (
-                keyCode ==  KeyEvent.KEYCODE_HEADSETHOOK ||
-                keyCode ==  KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
-                keyCode ==  KeyEvent.KEYCODE_SPACE)) {
-            doPauseResume();
-            show(sDefaultTimeout);
-            if (mPauseButton != null) {
-                mPauseButton.requestFocus();
+        final boolean uniqueDown = event.getRepeatCount() == 0
+                && event.getAction() == KeyEvent.ACTION_DOWN;
+        if (keyCode ==  KeyEvent.KEYCODE_HEADSETHOOK
+                || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
+                || keyCode == KeyEvent.KEYCODE_SPACE) {
+            if (uniqueDown) {
+                doPauseResume();
+                show(sDefaultTimeout);
+                if (mPauseButton != null) {
+                    mPauseButton.requestFocus();
+                }
             }
             return true;
-        } else if (keyCode ==  KeyEvent.KEYCODE_MEDIA_STOP) {
-            if (mPlayer.isPlaying()) {
+        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
+            if (uniqueDown && !mPlayer.isPlaying()) {
+                mPlayer.start();
+                updatePausePlay();
+                show(sDefaultTimeout);
+            }
+            return true;
+        } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
+                || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
+            if (uniqueDown && mPlayer.isPlaying()) {
                 mPlayer.pause();
                 updatePausePlay();
+                show(sDefaultTimeout);
             }
             return true;
-        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
-                keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
+        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
+                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
             // don't show the controls for volume adjustment
             return super.dispatchKeyEvent(event);
         } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) {
-            hide();
-
+            if (uniqueDown) {
+                hide();
+            }
             return true;
-        } else {
-            show(sDefaultTimeout);
         }
+
+        show(sDefaultTimeout);
         return super.dispatchKeyEvent(event);
     }
 
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 9d214fc..6ba7b44 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -132,6 +132,25 @@
             // here
             return;
         }
+
+        protected boolean startIntentSafely(Context context, PendingIntent pendingIntent,
+                Intent fillInIntent) {
+            try {
+                // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
+                context.startIntentSender(
+                        pendingIntent.getIntentSender(), fillInIntent,
+                        Intent.FLAG_ACTIVITY_NEW_TASK,
+                        Intent.FLAG_ACTIVITY_NEW_TASK, 0);
+            } catch (IntentSender.SendIntentException e) {
+                android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e);
+                return false;
+            } catch (Exception e) {
+                android.util.Log.e(LOG_TAG, "Cannot send pending intent due to " +
+                        "unknown exception: ", e);
+                return false;
+            }
+            return true;
+        }
     }
 
     private class SetEmptyView extends Action {
@@ -190,6 +209,7 @@
         @Override
         public void apply(View root) {
             final View target = root.findViewById(viewId);
+            if (target == null) return;
 
             if (!mIsWidgetCollectionChild) {
                 Log.e("RemoteViews", "The method setOnClickFillInIntent is available " +
@@ -235,15 +255,7 @@
                         rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
 
                         fillInIntent.setSourceBounds(rect);
-                        try {
-                            // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
-                            v.getContext().startIntentSender(
-                                    pendingIntent.getIntentSender(), fillInIntent,
-                                    Intent.FLAG_ACTIVITY_NEW_TASK,
-                                    Intent.FLAG_ACTIVITY_NEW_TASK, 0);
-                        } catch (IntentSender.SendIntentException e) {
-                            android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e);
-                        }
+                        startIntentSafely(v.getContext(), pendingIntent, fillInIntent);
                     }
 
                 };
@@ -277,6 +289,7 @@
         @Override
         public void apply(View root) {
             final View target = root.findViewById(viewId);
+            if (target == null) return;
 
             if (!mIsWidgetCollectionChild) {
                 Log.e("RemoteViews", "The method setOnClickExtras is available " +
@@ -324,16 +337,7 @@
                         final Intent intent = new Intent();
                         intent.setSourceBounds(rect);
                         intent.putExtras(extras);
-
-                        try {
-                            // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
-                            v.getContext().startIntentSender(
-                                    pendingIntent.getIntentSender(), intent,
-                                    Intent.FLAG_ACTIVITY_NEW_TASK,
-                                    Intent.FLAG_ACTIVITY_NEW_TASK, 0);
-                        } catch (IntentSender.SendIntentException e) {
-                            android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e);
-                        }
+                        startIntentSafely(v.getContext(), pendingIntent, intent);
                     }
 
                 };
@@ -367,6 +371,7 @@
         @Override
         public void apply(View root) {
             final View target = root.findViewById(viewId);
+            if (target == null) return;
 
             // If the view isn't an AdapterView, setting a PendingIntent template doesn't make sense
             if (target instanceof AdapterView<?>) {
@@ -410,6 +415,7 @@
         @Override
         public void apply(View root) {
             final View target = root.findViewById(viewId);
+            if (target == null) return;
 
             // If the view is an AdapterView, setting a PendingIntent on click doesn't make much
             // sense, do they mean to set a PendingIntent template for the AdapterView's children?
@@ -437,15 +443,7 @@
 
                         final Intent intent = new Intent();
                         intent.setSourceBounds(rect);
-                        try {
-                            // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
-                            v.getContext().startIntentSender(
-                                    pendingIntent.getIntentSender(), intent,
-                                    Intent.FLAG_ACTIVITY_NEW_TASK,
-                                    Intent.FLAG_ACTIVITY_NEW_TASK, 0);
-                        } catch (IntentSender.SendIntentException e) {
-                            android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e);
-                        }
+                        startIntentSafely(v.getContext(), pendingIntent, intent);
                     }
                 };
                 target.setOnClickListener(listener);
@@ -513,9 +511,7 @@
         @Override
         public void apply(View root) {
             final View target = root.findViewById(viewId);
-            if (target == null) {
-                return;
-            }
+            if (target == null) return;
             
             // Pick the correct drawable to modify for this view
             Drawable targetDrawable = null;
@@ -575,9 +571,7 @@
         @Override
         public void apply(View root) {
             final View view = root.findViewById(viewId);
-            if (view == null) {
-                throw new ActionException("can't find view: 0x" + Integer.toHexString(viewId));
-            }
+            if (view == null) return;
 
             Class klass = view.getClass();
             Method method;
@@ -793,9 +787,7 @@
         @Override
         public void apply(View root) {
             final View view = root.findViewById(viewId);
-            if (view == null) {
-                throw new ActionException("can't find view: 0x" + Integer.toHexString(viewId));
-            }
+            if (view == null) return;
 
             Class param = getParameterType();
             if (param == null) {
@@ -888,10 +880,11 @@
         public void apply(View root) {
             final Context context = root.getContext();
             final ViewGroup target = (ViewGroup) root.findViewById(viewId);
+            if (target == null) return;
             if (nestedViews != null) {
                 // Inflate nested views and add as children
                 target.addView(nestedViews.apply(context, target));
-            } else if (target != null) {
+            } else {
                 // Clear all children when nested views omitted
                 target.removeAllViews();
             }
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 40ac76c..5c3561f 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -470,7 +470,9 @@
             int mem = 0;
             for (Integer i : mIndexRemoteViews.keySet()) {
                 final RemoteViews v = mIndexRemoteViews.get(i);
-                mem += v.estimateBitmapMemoryUsage();
+                if (v != null) {
+                    mem += v.estimateBitmapMemoryUsage();
+                }
             }
             return mem;
         }
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 36adacd..ce4e8e5 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -115,7 +115,6 @@
     }
 
     private void initTabWidget() {
-        setOrientation(LinearLayout.HORIZONTAL);
         mGroupFlags |= FLAG_USE_CHILD_DRAWING_ORDER;
 
         final Context context = mContext;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index ef15f6f..2fcae1c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3229,7 +3229,8 @@
      * for this text view.  The default implementation will call your action
      * listener supplied to {@link #setOnEditorActionListener}, or perform
      * a standard operation for {@link EditorInfo#IME_ACTION_NEXT
-     * EditorInfo.IME_ACTION_NEXT} or {@link EditorInfo#IME_ACTION_DONE
+     * EditorInfo.IME_ACTION_NEXT}, {@link EditorInfo#IME_ACTION_PREVIOUS
+     * EditorInfo.IME_ACTION_PREVIOUS}, or {@link EditorInfo#IME_ACTION_DONE
      * EditorInfo.IME_ACTION_DONE}.
      * 
      * <p>For backwards compatibility, if no IME options have been set and the
@@ -3266,6 +3267,16 @@
                 }
                 return;
                 
+            } else if (actionCode == EditorInfo.IME_ACTION_PREVIOUS) {
+                View v = focusSearch(FOCUS_UP);
+                if (v != null) {
+                    if (!v.requestFocus(FOCUS_UP)) {
+                        throw new IllegalStateException("focus search returned a view " +
+                                "that wasn't able to take focus!");
+                    }
+                }
+                return;
+
             } else if (actionCode == EditorInfo.IME_ACTION_DONE) {
                 InputMethodManager imm = InputMethodManager.peekInstance();
                 if (imm != null) {
@@ -4266,6 +4277,15 @@
 
         canvas.restore();
 
+        updateCursorControllerPositions();
+    }
+
+    /**
+     * Update the positions of the CursorControllers.  Needed by WebTextView,
+     * which does not draw.
+     * @hide
+     */
+    protected void updateCursorControllerPositions() {
         if (mInsertionPointCursorController != null &&
                 mInsertionPointCursorController.isShowing()) {
             mInsertionPointCursorController.updatePosition();
@@ -4680,9 +4700,15 @@
             } else {
                 outAttrs.imeOptions = EditorInfo.IME_NULL;
             }
+            if (focusSearch(FOCUS_DOWN) != null) {
+                outAttrs.imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_NEXT;
+            }
+            if (focusSearch(FOCUS_UP) != null) {
+                outAttrs.imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS;
+            }
             if ((outAttrs.imeOptions&EditorInfo.IME_MASK_ACTION)
                     == EditorInfo.IME_ACTION_UNSPECIFIED) {
-                if (focusSearch(FOCUS_DOWN) != null) {
+                if ((outAttrs.imeOptions&EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0) {
                     // An action has not been set, but the enter key will move to
                     // the next focus, so set the action to that.
                     outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT;
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 3d9cde4..2be7bca 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -529,10 +529,19 @@
                     mMediaController.hide();
                 }
                 return true;
+            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
+                if (mMediaPlayer.isPlaying()) {
+                    start();
+                    mMediaController.hide();
+                }
+                return true;
             } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
-                    && mMediaPlayer.isPlaying()) {
-                pause();
-                mMediaController.show();
+                    || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
+                if (!mMediaPlayer.isPlaying()) {
+                    pause();
+                    mMediaController.show();
+                }
+                return true;
             } else {
                 toggleMediaControlsVisiblity();
             }
diff --git a/core/java/com/android/internal/os/SamplingProfilerIntegration.java b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
index b87ac90..6d2bcae 100644
--- a/core/java/com/android/internal/os/SamplingProfilerIntegration.java
+++ b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
@@ -82,8 +82,8 @@
         }
         ThreadGroup group = Thread.currentThread().getThreadGroup();
         SamplingProfiler.ThreadSet threadSet = SamplingProfiler.newThreadGroupTheadSet(group);
-        INSTANCE = new SamplingProfiler(4, threadSet);
-        INSTANCE.start(samplingProfilerHz);
+        INSTANCE = new SamplingProfiler(4, threadSet); // TODO parameter for depth
+        INSTANCE.start(1000/samplingProfilerHz);
     }
 
     /**
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index d5ae1f0..19666fd 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -38,7 +38,7 @@
     // You need the STATUS_BAR_SERVICE permission
     void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList,
             out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications,
-            out boolean[] switches);
+            out int[] switches);
     void onPanelRevealed();
     void onNotificationClick(String pkg, String tag, int id);
     void onNotificationError(String pkg, String tag, int id,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2444fce..3635fab 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -532,6 +532,13 @@
         android:description="@string/permdesc_sdcardWrite"
         android:protectionLevel="dangerous" />
 
+    <!-- Allows an application to write to internal media storage -->
+    <permission android:name="android.permission.WRITE_MEDIA_STORAGE"
+        android:permissionGroup="android.permission-group.STORAGE"
+        android:label="@string/permlab_mediaStorageWrite"
+        android:description="@string/permdesc_mediaStorageWrite"
+        android:protectionLevel="signatureOrSystem" />
+
     <!-- ============================================ -->
     <!-- Permissions for low-level system interaction -->
     <!-- ============================================ -->
diff --git a/core/res/res/anim/fragment_close_enter.xml b/core/res/res/anim/fragment_close_enter.xml
index 7a9a3b9..edf1948 100644
--- a/core/res/res/anim/fragment_close_enter.xml
+++ b/core/res/res/anim/fragment_close_enter.xml
@@ -26,7 +26,7 @@
         android:duration="@android:integer/config_mediumAnimTime"/>
     <objectAnimator
         android:interpolator="@anim/decelerate_interpolator"
-        android:valueFrom="-400"
+        android:valueFrom="-100"
         android:valueTo="0"
         android:valueType="floatType"
         android:propertyName="translationX"
diff --git a/core/res/res/anim/fragment_close_exit.xml b/core/res/res/anim/fragment_close_exit.xml
index 0743577..fbba476 100644
--- a/core/res/res/anim/fragment_close_exit.xml
+++ b/core/res/res/anim/fragment_close_exit.xml
@@ -27,7 +27,7 @@
     <objectAnimator
         android:interpolator="@anim/accelerate_interpolator"
         android:valueFrom="0"
-        android:valueTo="400"
+        android:valueTo="100"
         android:valueType="floatType"
         android:propertyName="translationX"
         android:duration="@android:integer/config_mediumAnimTime"/>
diff --git a/core/res/res/anim/fragment_open_enter.xml b/core/res/res/anim/fragment_open_enter.xml
index ac60494..334f4ef 100644
--- a/core/res/res/anim/fragment_open_enter.xml
+++ b/core/res/res/anim/fragment_open_enter.xml
@@ -24,7 +24,7 @@
         android:propertyName="alpha"
         android:duration="@android:integer/config_mediumAnimTime"/>
     <objectAnimator
-        android:valueFrom="400"
+        android:valueFrom="100"
         android:valueTo="0"
         android:valueType="floatType"
         android:propertyName="translationX"
diff --git a/core/res/res/anim/fragment_open_exit.xml b/core/res/res/anim/fragment_open_exit.xml
index 3bf1ad4..764fc39 100644
--- a/core/res/res/anim/fragment_open_exit.xml
+++ b/core/res/res/anim/fragment_open_exit.xml
@@ -25,7 +25,7 @@
         android:duration="@android:integer/config_mediumAnimTime"/>
     <objectAnimator
         android:valueFrom="0"
-        android:valueTo="-400"
+        android:valueTo="-100"
         android:valueType="floatType"
         android:propertyName="translationX"
         android:duration="@android:integer/config_mediumAnimTime"/>
diff --git a/core/res/res/layout/tab_content.xml b/core/res/res/layout/tab_content.xml
index 0ee87ce..79147fb 100644
--- a/core/res/res/layout/tab_content.xml
+++ b/core/res/res/layout/tab_content.xml
@@ -22,8 +22,9 @@
 	android:layout_width="match_parent" android:layout_height="match_parent">
 	<LinearLayout android:orientation="vertical"
     	android:layout_width="match_parent" android:layout_height="match_parent">
-        <TabWidget android:id="@android:id/tabs" android:layout_width="match_parent"
-        	android:layout_height="wrap_content" android:layout_weight="0" />
+    <TabWidget android:id="@android:id/tabs"
+        android:orientation="horizontal" android:layout_width="match_parent"
+        android:layout_height="wrap_content" android:layout_weight="0" />
         <FrameLayout android:id="@android:id/tabcontent"
         	android:layout_width="match_parent" android:layout_height="0dip"
             android:layout_weight="1"/>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 0cac7eb..79131ba 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -326,6 +326,9 @@
                  need to close the input area to get at and interact with
                  parts of the window. -->
             <flag name="adjustPan" value="0x20" />
+            <!-- Don't resize <em>or</em> pan the window to make room for the
+                 soft input area; the window is never adjusted for it. -->
+            <flag name="adjustNothing" value="0x30" />
         </attr>
 
         <!-- Flag allowing you to disable the preview animation for a window.
@@ -737,6 +740,14 @@
              {@link android.text.InputType#TYPE_CLASS_TEXT} |
              {@link android.text.InputType#TYPE_TEXT_VARIATION_PHONETIC}. -->
         <flag name="textPhonetic" value="0x000000c1" />
+        <!-- Text that will be used as an e-mail address on a web form.  Corresponds to
+             {@link android.text.InputType#TYPE_CLASS_TEXT} |
+             {@link android.text.InputType#TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS}. -->
+        <flag name="textWebEmailAddress" value="0x000000d1" />
+        <!-- Text that will be used as a password on a web form.  Corresponds to
+             {@link android.text.InputType#TYPE_CLASS_TEXT} |
+             {@link android.text.InputType#TYPE_TEXT_VARIATION_WEB_PASSWORD}. -->
+        <flag name="textWebPassword" value="0x000000e1" />
         <!-- A numeric only field.  Corresponds to
              {@link android.text.InputType#TYPE_CLASS_NUMBER}. -->
         <flag name="number" value="0x00000002" />
@@ -811,6 +822,40 @@
              Corresponds to
              {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE}. -->
         <flag name="actionDone" value="0x00000006" />
+        <!-- The action key performs a "previous"
+             operation, taking the user to the previous field that will accept text.
+             Corresponds to
+             {@link android.view.inputmethod.EditorInfo#IME_ACTION_PREVIOUS}. -->
+        <flag name="actionPrevious" value="0x00000007" />
+        <!-- Used to request that the IME never go
+             into fullscreen mode.  Applications need to be aware that the flag is not
+             a guarantee, and not all IMEs will respect it.
+             <p>Corresponds to
+             {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_FULLSCREEN}. -->
+        <flag name="flagNoFullscreen" value="0x2000000" />
+        <!-- Like flagNavigateNext, but
+             specifies there is something interesting that a backward navigation
+             can focus on.  If the user selects the IME's facility to backward
+             navigate, this will show up in the application as an actionPrevious
+             at {@link android.view.inputmethod.InputConnection#performEditorAction(int)
+             InputConnection.performEditorAction(int)}.
+             <p>Corresponds to
+             {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_FULLSCREEN}. -->
+        <flag name="flagNavigatePrevious" value="0x4000000" />
+        <!-- Used to specify that there is something
+             interesting that a forward navigation can focus on. This is like using
+             actionNext, except allows the IME to be multiline (with
+             an enter key) as well as provide forward navigation.  Note that some
+             IMEs may not be able to do this, especially when running on a small
+             screen where there is little space.  In that case it does not need to
+             present a UI for this option.  Like actionNext, if the
+             user selects the IME's facility to forward navigate, this will show up
+             in the application at
+             {@link android.view.inputmethod.InputConnection#performEditorAction(int)
+             InputConnection.performEditorAction(int)}.
+             <p>Corresponds to
+             {@link android.view.inputmethod.EditorInfo#IME_FLAG_NAVIGATE_NEXT}. -->
+        <flag name="flagNavigateNext" value="0x8000000" />
         <!-- Used to specify that the IME does not need
              to show its extracted text UI.  For input methods that may be fullscreen,
              often when in landscape mode, this allows them to be smaller and let part
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d704366..f905725 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1402,6 +1402,8 @@
   <public type="style" name="Theme.Holo.Light" />
   <public type="style" name="Theme.Holo.Dialog" />
   <public type="style" name="Theme.Holo.Light.Dialog" />
+  <public type="style" name="Theme.Holo.Extended" />
+  <public type="style" name="Theme.Holo.Light.Extended" />
 
   <public type="style" name="Widget.ListPopupWindow" />
   <public type="style" name="Widget.PopupMenu" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8a5af7d..f8c7b69 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1231,6 +1231,11 @@
     <string name="permdesc_sdcardWrite" product="default">Allows an application to write to the SD card.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_mediaStorageWrite" product="default">modify/delete internal media storage contents</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_mediaStorageWrite" product="default">Allows an application to modify the contents of the internal media storage.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_cache_filesystem">access the cache filesystem</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_cache_filesystem">Allows an application to read and write the cache filesystem.</string>
@@ -2321,6 +2326,9 @@
     <!-- Long label for a button on a full-screen input method for the "Done" action. -->
     <string name="ime_action_done">Done</string>
 
+    <!-- [CHAR LIMIT=6] Long label for a button on a full-screen input method for the "Previous" action. -->
+    <string name="ime_action_previous">Prev</string>
+
     <!-- Long label for a button on a full-screen input method for an unknown action. -->
     <string name="ime_action_default">Execute</string>
 
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index eeefa9e..80072f4 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -572,7 +572,7 @@
     <style name="Theme.IconMenu">
         <!-- Menu/item attributes -->
         <item name="android:itemTextAppearance">@android:style/TextAppearance.Widget.IconMenu.Item</item>
-        <item name="android:selectableItemBackground">@android:drawable/menu_selector</item>
+        <item name="android:itemBackground">@android:drawable/menu_selector</item>
         <item name="android:itemIconDisabledAlpha">?android:attr/disabledAlpha</item>
         <item name="android:horizontalDivider">@android:drawable/divider_horizontal_dark</item>
         <item name="android:verticalDivider">@android:drawable/divider_vertical_dark</item>
@@ -641,7 +641,7 @@
         <item name="colorForeground">@android:color/bright_foreground_holo_dark</item>
         <item name="colorForegroundInverse">@android:color/bright_foreground_inverse_holo_dark</item>
         <item name="colorBackground">@android:color/background_holo_dark</item>
-        <item name="colorBackgroundCacheHint">@android:color/transparent</item>
+        <item name="colorBackgroundCacheHint">?android:attr/colorBackground</item>
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
 
@@ -734,7 +734,7 @@
         <item name="galleryItemBackground">@android:drawable/gallery_item_background</item>
         
         <!-- Window attributes -->
-        <item name="windowBackground">@android:drawable/background_holo_dark</item>
+        <item name="windowBackground">?android:attr/colorBackground</item>
         <item name="windowFrame">@null</item>
         <item name="windowNoTitle">false</item>
         <item name="windowFullscreen">false</item>
@@ -875,7 +875,7 @@
         <item name="colorForeground">@android:color/bright_foreground_holo_light</item>
         <item name="colorForegroundInverse">@android:color/bright_foreground_inverse_holo_light</item>
         <item name="colorBackground">@android:color/background_holo_light</item>
-        <item name="colorBackgroundCacheHint">@android:color/transparent</item>
+        <item name="colorBackgroundCacheHint">?android:attr/colorBackground</item>
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
 
@@ -968,7 +968,7 @@
         <item name="galleryItemBackground">@android:drawable/gallery_item_background</item>
         
         <!-- Window attributes -->
-        <item name="windowBackground">@android:drawable/background_holo_light</item>
+        <item name="windowBackground">?android:attr/colorBackground</item>
         <item name="windowFrame">@null</item>
         <item name="windowNoTitle">false</item>
         <item name="windowFullscreen">false</item>
@@ -1129,6 +1129,20 @@
         <item name="android:windowFullscreen">true</item>
         <item name="android:windowContentOverlay">@null</item>
     </style>
+
+    <!-- Variant of the holographic dark theme that includes extra decorations
+         appropriate for when hardware acceleration is in use. -->
+    <style name="Theme.Holo.Extended">
+        <item name="windowBackground">@android:drawable/background_holo_dark</item>
+        <item name="colorBackgroundCacheHint">@android:color/transparent</item>
+    </style>
+
+    <!-- Variant of the holographic light theme that includes extra decorations
+         appropriate for when hardware acceleration is in use. -->
+    <style name="Theme.Holo.Light.Extended">
+        <item name="windowBackground">@android:drawable/background_holo_light</item>
+        <item name="colorBackgroundCacheHint">@android:color/transparent</item>
+    </style>
  
     <!-- Dialog themes for Holo -->
 
diff --git a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
index 37fc6c7..340137c 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
@@ -132,14 +132,34 @@
          */
         @Override
         public void onReceive(Context context, Intent intent) {
-            Log.i(LOG_TAG, "Received Notification:");
             if (intent.getAction().equalsIgnoreCase(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
                 synchronized(this) {
-                    ++mNumDownloadsCompleted;
-                    Log.i(LOG_TAG, "MultipleDownloadsCompletedReceiver got intent: " +
-                            intent.getAction() + " --> total count: " + mNumDownloadsCompleted);
-                    Bundle extras = intent.getExtras();
-                    downloadIds.add(new Long(extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID)));
+                    long id = intent.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
+                    Log.i(LOG_TAG, "Received Notification for download: " + id);
+                    if (!downloadIds.contains(id)) {
+                        ++mNumDownloadsCompleted;
+                        Log.i(LOG_TAG, "MultipleDownloadsCompletedReceiver got intent: " +
+                                intent.getAction() + " --> total count: " + mNumDownloadsCompleted);
+                        downloadIds.add(id);
+
+                        DownloadManager dm = (DownloadManager)context.getSystemService(
+                                Context.DOWNLOAD_SERVICE);
+
+                        Cursor cursor = dm.query(new Query().setFilterById(id));
+                        try {
+                            if (cursor.moveToFirst()) {
+                                int status = cursor.getInt(cursor.getColumnIndex(
+                                        DownloadManager.COLUMN_STATUS));
+                                Log.i(LOG_TAG, "Download status is: " + status);
+                            } else {
+                                fail("No status found for completed download!");
+                            }
+                        } finally {
+                            cursor.close();
+                        }
+                    } else {
+                        Log.i(LOG_TAG, "Notification for id: " + id + " has already been made.");
+                    }
                 }
             }
         }
@@ -621,9 +641,11 @@
     /**
      * Helper to wait for a particular download to finish, or else a timeout to occur
      *
+     * Does not wait for a receiver notification of the download.
+     *
      * @param id The download id to query on (wait for)
      */
-    protected void waitForDownloadOrTimeout(long id) throws TimeoutException,
+    protected void waitForDownloadOrTimeout_skipNotification(long id) throws TimeoutException,
             InterruptedException {
         waitForDownloadOrTimeout(id, WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME);
     }
@@ -631,6 +653,21 @@
     /**
      * Helper to wait for a particular download to finish, or else a timeout to occur
      *
+     * Also guarantees a notification has been posted for the download.
+     *
+     * @param id The download id to query on (wait for)
+     */
+    protected void waitForDownloadOrTimeout(long id) throws TimeoutException,
+            InterruptedException {
+        waitForDownloadOrTimeout_skipNotification(id);
+        waitForReceiverNotifications(1);
+    }
+
+    /**
+     * Helper to wait for a particular download to finish, or else a timeout to occur
+     *
+     * Also guarantees a notification has been posted for the download.
+     *
      * @param id The download id to query on (wait for)
      * @param poll The amount of time to wait
      * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
@@ -638,11 +675,14 @@
     protected void waitForDownloadOrTimeout(long id, long poll, long timeoutMillis)
             throws TimeoutException, InterruptedException {
         doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis);
+        waitForReceiverNotifications(1);
     }
 
     /**
      * Helper to wait for all downloads to finish, or else a specified timeout to occur
      *
+     * Makes no guaranee that notifications have been posted for all downloads.
+     *
      * @param poll The amount of time to wait
      * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
      */
@@ -654,6 +694,8 @@
     /**
      * Helper to wait for all downloads to finish, or else a timeout to occur, but does not throw
      *
+     * Also guarantees a notification has been posted for the download.
+     *
      * @param id The id of the download to query against
      * @param poll The amount of time to wait
      * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
@@ -662,6 +704,7 @@
     protected boolean waitForDownloadOrTimeoutNoThrow(long id, long poll, long timeoutMillis) {
         try {
             doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis);
+            waitForReceiverNotifications(1);
         } catch (TimeoutException e) {
             return false;
         }
@@ -717,9 +760,8 @@
             Cursor cursor = mDownloadManager.query(query);
 
             try {
-                // @TODO: there may be a little cleaner way to check for success, perhaps
-                // via STATUS_SUCCESSFUL and/or STATUS_FAILED
-                if (cursor.getCount() == 0 && mReceiver.numDownloadsCompleted() > 0) {
+                if (cursor.getCount() == 0) {
+                    Log.i(LOG_TAG, "All downloads should be done...");
                     break;
                 }
                 currentWaitTime = timeoutWait(currentWaitTime, poll, timeoutMillis,
@@ -779,6 +821,36 @@
     }
 
     /**
+     * Convenience function to wait for just 1 notification of a download.
+     *
+     * @throws Exception if timed out while waiting
+     */
+    protected void waitForReceiverNotification() throws Exception {
+        waitForReceiverNotifications(1);
+    }
+
+    /**
+     * Synchronously waits for our receiver to receive notification for a given number of
+     * downloads.
+     *
+     * @param targetNumber The number of notifications for unique downloads to wait for; pass in
+     *         -1 to not wait for notification.
+     * @throws Exception if timed out while waiting
+     */
+    protected void waitForReceiverNotifications(int targetNumber) throws TimeoutException {
+        int count = mReceiver.numDownloadsCompleted();
+        int currentWaitTime = 0;
+
+        while (count < targetNumber) {
+            Log.i(LOG_TAG, "Waiting for notification of downloads...");
+            currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
+                    MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for download notifications!"
+                    + " Received " + count + "notifications.");
+            count = mReceiver.numDownloadsCompleted();
+        }
+    }
+
+    /**
      * Synchronously waits for a file to increase in size (such as to monitor that a download is
      * progressing).
      *
diff --git a/core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java b/core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java
index cb7c2d2..4f79108 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java
@@ -197,7 +197,7 @@
     public void testMultipleDownloads() throws Exception {
         // need to be sure all current downloads have stopped first
         removeAllCurrentDownloads();
-        int NUM_FILES = 50;
+        int NUM_FILES = 10;
         int MAX_FILE_SIZE = 500 * 1024; // 500 kb
 
         Random r = new LoggingRng();
@@ -205,15 +205,15 @@
             int size = r.nextInt(MAX_FILE_SIZE);
             byte[] blobData = generateData(size, DataType.TEXT);
 
-            Uri uri = getServerUri(DEFAULT_FILENAME);
+            Uri uri = getServerUri(DEFAULT_FILENAME + i);
             Request request = new Request(uri);
-            request.setTitle(String.format("%s--%d", DEFAULT_FILENAME, i));
+            request.setTitle(String.format("%s--%d", DEFAULT_FILENAME + i, i));
 
             // Prepare the mock server with a standard response
             enqueueResponse(HTTP_OK, blobData);
 
-            Log.i(LOG_TAG, "request: " + i);
-            mDownloadManager.enqueue(request);
+            long requestID = mDownloadManager.enqueue(request);
+            Log.i(LOG_TAG, "request: " + i + " -- requestID: " + requestID);
         }
 
         waitForDownloadsOrTimeout(WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME);
@@ -236,6 +236,8 @@
 
             assertEquals(NUM_FILES, mReceiver.numDownloadsCompleted());
         } finally {
+            Log.i(LOG_TAG, "All download IDs: " + mReceiver.getDownloadIds().toString());
+            Log.i(LOG_TAG, "Total downloads completed: " + mReceiver.getDownloadIds().size());
             cursor.close();
         }
     }
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
index c0f670b..e1d7b4c 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
@@ -53,6 +53,8 @@
     protected static long DOWNLOAD_500K_FILESIZE = 570927;
     protected static String DOWNLOAD_1MB_FILENAME = "External1mb.apk";
     protected static long DOWNLOAD_1MB_FILESIZE = 1041262;
+    protected static String DOWNLOAD_5MB_FILENAME = "External5mb.apk";
+    protected static long DOWNLOAD_5MB_FILESIZE = 5138700;
     protected static String DOWNLOAD_10MB_FILENAME = "External10mb.apk";
     protected static long DOWNLOAD_10MB_FILESIZE = 10258741;
 
@@ -135,7 +137,7 @@
      * @throws Exception if unsuccessful
      */
     public void initiateDownload() throws Exception {
-        String filename = DOWNLOAD_1MB_FILENAME;
+        String filename = DOWNLOAD_5MB_FILENAME;
         mContext.deleteFile(DOWNLOAD_STARTED_FLAG);
         FileOutputStream fileOutput = mContext.openFileOutput(DOWNLOAD_STARTED_FLAG, 0);
         DataOutputStream outputFile = null;
@@ -171,8 +173,8 @@
      * @throws Exception if unsuccessful
      */
     public void verifyFileDownloadSucceeded() throws Exception {
-        String filename = DOWNLOAD_1MB_FILENAME;
-        long filesize = DOWNLOAD_1MB_FILESIZE;
+        String filename = DOWNLOAD_5MB_FILENAME;
+        long filesize = DOWNLOAD_5MB_FILESIZE;
         long dlRequest = -1;
         boolean rebootMarkerValid = false;
         DataInputStream dataInputFile = null;
@@ -205,7 +207,8 @@
             int status = cursor.getInt(columnIndex);
             int currentWaitTime = 0;
 
-            // Wait until the download finishes
+            // Wait until the download finishes; don't wait for a notification b/c
+            // the download may well have been completed before the last reboot.
             waitForDownloadOrTimeout(dlRequest);
 
             Log.i(LOG_TAG, "Verifying download information...");
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 439fc90..f458576 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -58,6 +58,10 @@
         <group gid="sdcard_rw" />
     </permission>
 
+    <permission name="android.permission.WRITE_MEDIA_STORAGE" >
+        <group gid="media_rw" />
+    </permission>
+
     <permission name="android.permission.ACCESS_USB" >
         <group gid="usb" />
     </permission>
diff --git a/docs/html/guide/developing/tools/MonkeyDevice.jd b/docs/html/guide/developing/tools/MonkeyDevice.jd
new file mode 100644
index 0000000..34bbba9
--- /dev/null
+++ b/docs/html/guide/developing/tools/MonkeyDevice.jd
@@ -0,0 +1,1353 @@
+page.title=MonkeyDevice
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+<p>
+    A monkeyrunner class that represents a device or emulator accessible by the workstation running
+<code><a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">monkeyrunner</a></code>.
+</p>
+<p>
+    This class is used to control an Android device or emulator. The methods send UI events,
+    retrieve information, install and remove applications, and run applications.
+</p>
+<p>
+    You normally do not have to create an instance of <code>MonkeyDevice</code>. Instead, you
+    use
+<code><a href="{@docRoot}guide/developing/tools/MonkeyRunner.html#waitForConnection">
+MonkeyRunner.waitForConnection()</a></code> to create a new object from a connection to a device or
+emulator. For example, instead of
+using:</p>
+<pre>
+newdevice = MonkeyDevice()
+</pre>
+<p>
+    you would use:
+</p>
+<pre>
+newdevice = MonkeyRunner.waitForConnection()
+</pre>
+<h2>Summary</h2>
+    <table id="constants" class="jd-sumtable" style="background-color: white;">
+       <tr>
+            <th colspan="12" style="background-color: #E2E2E2">Constants</th>
+       </tr>
+        <tr class="api" style="background-color: white;">
+            <td class="jd-typecol"><em>string</em></td>
+            <td class="jd-linkcol"><a href="#ACTION_DOWN">DOWN</a></td>
+            <td class="jd-descrcol" width="100%">
+                Use this with the <code>type</code> argument of
+                <code><a href="#press">press()</a></code> or <code><a href="#touch">touch()</a>
+                </code>
+                to send a DOWN event.
+            </td>
+        </tr>
+        <tr class="api" style="background-color: white;">
+            <td class="jd-typecol"><em>string</em></td>
+            <td class="jd-linkcol"><a href="#ACTION_UP">UP</a></td>
+            <td class="jd-descrcol" width="100%">
+                Use this with the <code>type</code> argument of
+                <code><a href="#press">press()</a></code> or <code><a href="#touch">touch()</a>
+                </code>
+                to send an UP event.
+            </td>
+        </tr>
+        <tr class="api" style="background-color: white;">
+            <td class="jd-typecol"><em>string</em></td>
+            <td class="jd-linkcol"><a href="#ACTION_DOWN_AND_UP">DOWN_AND_UP</a></td>
+            <td class="jd-descrcol" width="100%">
+                Use this with the <code>type</code> argument of
+                <code><a href="#press">press()</a></code> or <code><a href="#touch">touch()</a>
+                </code>
+                to send a DOWN event immediately followed by an UP event.
+            </td>
+        </tr>
+    </table>
+<table id="pubmethods" class="jd-sumtable">
+    <tr>
+        <th colspan="12" style="background-color: #E2E2E2">Methods</th>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#broadcastIntent">broadcastIntent</a>
+                </span>
+                (<em>string</em> uri,
+                <em>string</em> action,
+                <em>string</em> data,
+                <em>string</em> mimetype,
+                <em>iterable</em> categories
+                <em>dictionary</em> extras,
+                <em>component</em> component,
+                <em>iterable</em> flags)
+            </nobr>
+            <div class="jd-descrdiv">
+                Broadcasts an Intent to this device, as if the Intent were coming from an
+                application.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#drag">drag</a>
+                </span>
+                (<em>tuple</em> start,
+                <em>tuple</em> end,
+                <em>float</em> duration,
+                <em>integer</em> steps)
+            </nobr>
+            <div class="jd-descrdiv">
+                Simulates a drag gesture (touch, hold, and move) on this device's screen.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <em>object</em>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#getProperty">getProperty</a>
+                </span>
+                (<em>string</em> key)
+            </nobr>
+            <div class="jd-descrdiv">
+                Given the name of a system environment variable, returns its value for this device.
+                The available variable names are listed in the <a href="#getProperty">
+                detailed description</a> of this method.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <em>object</em>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#getSystemProperty">getSystemProperty</a>
+                </span>
+                (<em>string</em> key)
+            </nobr>
+            <div class="jd-descrdiv">
+.               The API equivalent of <code>adb shell getprop &lt;key&gt;. This is provided for use
+                by platform developers.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#installPackage">installPackage</a>
+                </span>
+                (<em>string</em> path)
+            </nobr>
+            <div class="jd-descrdiv">
+                Installs the Android application or test package contained in packageFile onto this
+                device. If the application or test package is already installed, it is replaced.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <em>dictionary</em>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#instrument">instrument</a>
+                </span>
+                (<em>string</em> className,
+                <em>dictionary</em> args)
+            </nobr>
+            <div class="jd-descrdiv">
+                Runs the specified component under Android instrumentation, and returns the results
+                in a dictionary whose exact format is dictated by the component being run. The
+                component must already be present on this device.
+            </div>
+        </td>
+    </tr>
+    <tr class="api">
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#press">press</a>
+                </span>
+                (<em>string</em> name,
+                <em>dictionary</em> type)
+            </nobr>
+            <div class="jd-descrdiv">
+                Sends the key event specified by type to the key specified by
+                keycode.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#reboot">reboot</a>
+                </span>
+                (<em>string</em> into)
+            </nobr>
+            <div class="jd-descrdiv">
+                Reboots this device into the bootloader specified by bootloadType.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#removePackage">removePackage</a>
+                </span>
+                (<em>string</em> package)
+            </nobr>
+            <div class="jd-descrdiv">
+                Deletes the specified package from this device, including its data and cache.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <em>object</em>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#shell">shell</a>
+                </span>
+                (<em>string</em> cmd)
+            </nobr>
+            <div class="jd-descrdiv">
+                Executes an <code>adb</code> shell command and returns the result, if any.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#startActivity">startActivity</a>
+                </span>
+                (<em>string</em> uri,
+                <em>string</em> action,
+                <em>string</em> data,
+                <em>string</em> mimetype,
+                <em>iterable</em> categories
+                <em>dictionary</em> extras,
+                <em>component</em> component,
+                <em>flags</em>)
+            </nobr>
+            <div class="jd-descrdiv">
+                Starts an Activity on this device by sending an Intent constructed from the
+                supplied arguments.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <code>
+                <a href="{@docRoot}guide/developing/tools/MonkeyImage.html">
+                        MonkeyImage
+                    </a>
+                </code>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#takeSnapshot">takeSnapshot</a>()
+                </span>
+            </nobr>
+            <div class="jd-descrdiv">
+                Captures the entire screen buffer of this device, yielding a
+                <code>
+                <a href="{@docRoot}guide/developing/tools/MonkeyImage.html">
+                        MonkeyImage
+                </a>
+                </code> object containing a screen capture of the current display.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#touch">touch</a>
+                </span>
+               (<em>integer</em> x,
+                 <em>integer</em> y,
+                 <em>integer</em> type)
+            </nobr>
+            <div class="jd-descrdiv">
+                Sends a touch event specified by type to the screen location specified
+                by x and y.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#touch">type</a>
+                </span>
+                   (<em>string</em> message)
+            </nobr>
+            <div class="jd-descrdiv">
+                Sends the characters contained in message to this device, as if they
+                had been typed on the device's keyboard. This is equivalent to calling
+                <code><a href="#press">press()</a></code> for each keycode in <code>message</code>
+                using the key event type <code><a href="#ACTION_DOWN_AND_UP"></a>DOWN_AND_UP</code>.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#touch">wake</a>
+                </span>
+                   ()
+            </nobr>
+            <div class="jd-descrdiv">
+                Wakes the screen of this device.
+            </div>
+        </td>
+    </tr>
+</table>
+<!-- ========= ENUM CONSTANTS DETAIL ======== -->
+<h2>Constants</h2>
+<A NAME="ACTION_DOWN"></a>
+<div class="jd-details api">
+    <h4 class="jd-details-title">
+        <span class="normal">
+            <em>string</em>
+        </span>
+            DOWN
+    </h4>
+    <div class="jd-details-descr">
+        <div class="jd-tagdata jd-tagdescr">
+            <p>
+                <code><a href="#press">press()</a></code> or
+                <code><a href="#press">touch()</a></code> value.
+                Specifies that a DOWN event type should be sent to the device, corresponding to
+                pressing down on a key or touching the screen.
+            </p>
+        </div>
+    </div>
+</div>
+<A NAME="ACTION_UP"></A>
+<div class="jd-details api">
+    <h4 class="jd-details-title">
+        <span class="normal">
+            <em>string</em>
+        </span>
+            UP
+    </h4>
+    <div class="jd-details-descr">
+        <div class="jd-tagdata jd-tagdescr">
+            <p>
+                <code><a href="#press">press()</a></code> or
+                <code><a href="#press">touch()</a></code> value.
+                Specifies that an UP event type should be sent to the device, corresponding to
+                releasing a key or lifting up from the screen.
+            </p>
+        </div>
+    </div>
+</div>
+<A NAME="ACTION_DOWN_AND_UP"></A>
+
+<div class="jd-details api">
+    <h4 class="jd-details-title">
+        <span class="normal">
+            <em>string</em>
+        </span>
+            DOWN_AND_UP
+    </h4>
+    <div class="jd-details-descr">
+        <div class="jd-tagdata jd-tagdescr">
+            <p>
+                <code><a href="#press">press()</a></code>,
+                <code><a href="#press">touch()</a></code> or
+                <code><a href="#type">type()</a></code> value.
+                Specifies that a DOWN event type followed by an UP event type should be sent to the
+                device, corresponding to typing a key or clicking the screen.
+            </p>
+        </div>
+    </div>
+</div>
+<!-- ========= METHOD DETAIL ======== -->
+<!-- Public methods -->
+<h2>Public Methods</h2>
+<A NAME="broadcastIntent"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">broadcastIntent</span>
+      <span class="normal">
+      (
+            <em>string</em> uri,
+            <em>string</em> action,
+            <em>string</em> data,
+            <em>string</em> mimetype,
+            <em>iterable</em> categories
+            <em>dictionary</em> extras,
+            <em>component</em> component,
+            <em>iterable</em> flags)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Broadcasts an Intent to this device, as if the Intent were coming from an
+            application. See {@link android.content.Intent Intent} for more information about the
+            arguments.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>uri</th>
+            <td>
+                The URI for the Intent.
+                (see {@link android.content.Intent#setData(android.net.Uri) Intent.setData()}).
+            </td>
+        </tr>
+        <tr>
+            <th>action</th>
+            <td>
+                The action for this Intent
+                (see {@link android.content.Intent#setAction(java.lang.String) Intent.setAction()}).
+            </td>
+        </tr>
+        <tr>
+            <th>data</th>
+            <td>
+                The data URI for this Intent
+                (see {@link android.content.Intent#setData(android.net.Uri) Intent.setData()}).
+            </td>
+        </tr>
+        <tr>
+            <th>mimetype</th>
+            <td>
+                The MIME type for the Intent
+                (see {@link android.content.Intent#setType(java.lang.String) Intent.setType()}).
+            </td>
+        </tr>
+        <tr>
+            <th>categories</th>
+            <td>
+                An iterable data structure containing strings that define categories for this
+                Intent
+                (see
+                {@link android.content.Intent#addCategory(java.lang.String) Intent.addCategory()}).
+            </td>
+        </tr>
+        <tr>
+            <th>extras</th>
+            <td>
+                A dictionary of extra data for this Intent
+                (see {@link android.content.Intent#putExtra(java.lang.String,java.lang.String)
+                Intent.putExtra()}
+                for an example).
+                <p>
+                    The key for each dictionary item should be a <em>string</em>. The item's value
+                    can be any simple or structured data type.
+                </p>
+            </td>
+        </tr>
+        <tr>
+            <th>component</th>
+            <td>
+                The component for this Intent (see {@link android.content.ComponentName}).
+                Using this argument will direct the Intent to a specific class within a specific
+                Android package.
+            </td>
+        </tr>
+        <tr>
+            <th>flags</th>
+            <td>
+                An iterable data structure containing flags that control how the Intent is handled
+                (see {@link android.content.Intent#setFlags(int) Intent.setFlags()}).
+            </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>
+<A NAME="drag"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">drag</span>
+      <span class="normal">
+      (
+            <em>tuple</em> start,
+            <em>tuple</em> end,
+            <em>float</em> duration,
+            <em>integer</em> steps)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Simulates a drag gesture (touch, hold, and move) on this device's screen.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>start</th>
+          <td>
+            The starting point of the drag gesture, in the form of a <em>tuple</em>
+            (x,y) where x and y are <em>integers</em>.
+          </td>
+        </tr>
+        <tr>
+          <th>end</th>
+          <td>
+            The end point of the drag gesture, in the form of a <em>tuple</em> (x,y)
+            where x and y are <em>integers</em>.
+          </td>
+        </tr>
+        <tr>
+            <th>duration</th>
+            <td>The duration of the drag gesture in seconds. The default is 1.0 seconds.</td>
+        </tr>
+        <tr>
+            <th>steps</th>
+            <td>The number of steps to take when interpolating points. The default is 10.</td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>
+<A NAME="getProperty"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <em>object</em>
+      </span>
+      <span class="sympad">getProperty</span>
+      <span class="normal">
+        (<em>string</em> key)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Given the name of a system environment variable, returns its value for this device.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>key</th>
+          <td>
+            The name of the system environment variable. The available variable names are listed in
+            <a href="#table1">Table 1. Property variable names</a> at the end of this topic.
+          </td>
+        </tr>
+      </table>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist">
+        <li>
+            The value of the variable. The data format varies according to the variable requested.
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
+<A NAME="getSystemProperty"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <em>object</em>
+      </span>
+      <span class="sympad">getSystemProperty</span>
+      <span class="normal">
+      (<em>string</em> key)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Synonym for <code><a href="#getProperty">getProperty()</a></code>.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>key</th>
+          <td>
+            The name of the system environment variable. The available variable names are listed in
+            <a href="#table1">Table 1. Property Variable Names</a>.
+          </td>
+        </tr>
+      </table>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist">
+        <li>
+            The value of the variable. The data format varies according to the variable requested.
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
+<A NAME="installPackage"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">installPackage</span>
+      <span class="normal">
+      (<em>string</em> path)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Installs the Android application or test package contained in packageFile
+            onto this device. If the application or test package is already installed, it is
+            replaced.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>path</th>
+          <td>
+            The fully-qualified path and filename of the <code>.apk</code> file to install.
+          </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>
+<A NAME="instrument"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <em>dictionary</em>
+      </span>
+      <span class="sympad">instrument</span>
+      <span class="normal">
+      (
+            <em>string</em> className,
+            <em>dictionary</em> args)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Runs the specified component with Android instrumentation, and returns the results
+            in a dictionary whose exact format is dictated by the component being run. The
+            component must already be present on this device.
+        </p>
+        <p>
+            Use this method to start a test case that uses one of Android's test case classes.
+            See <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing
+            Fundamentals</a> to learn more about unit testing with the Android testing
+            framework.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>className</th>
+          <td>
+            The name of an Android component that is already installed on this device, in the
+            standard form packagename/classname, where packagename is the
+            Android package name of a <code>.apk</code> file on this device, and
+            classname is the class name of an Android component (Activity,
+            ContentProvider, Service, or BroadcastReceiver) in that file. Both
+            packagename and classname must be fully qualified. See
+            {@link android.content.ComponentName} for more details.
+          </td>
+        </tr>
+        <tr>
+          <th>args</th>
+          <td>
+            A dictionary containing flags and their values. These are passed to the component as it
+            is started. If the flag does not take a value, set its dictionary value to an empty
+            string.
+          </td>
+        </tr>
+      </table>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+        <ul class="nolist">
+            <li>
+                <p>
+                    A dictionary containing the component's output. The contents of the dictionary
+                    are defined by the component itself.
+                </p>
+                <p>
+                    If you use {@link android.test.InstrumentationTestRunner} as the class name in
+                    the componentName argument, then the result dictionary contains
+                    the single key "stream". The value of "stream" is a <em>string</em> containing
+                    the test output, as if <code>InstrumentationTestRunner</code> was run from the
+                    command line. The format of this output is described in
+                    <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
+                    Testing in Other IDEs</a>.
+                </p>
+            </li>
+        </ul>
+    </div>
+    </div>
+  </div>
+</div>
+<A NAME="press"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">press</span>
+      <span class="normal">
+      (<em>string</em> name,
+      <em>integer</em> type)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Sends the key event specified by <code>type</code> to the key specified by
+            <code>keycode</code>.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>name</th>
+          <td>
+            The name of the keycode to send. See {@link android.view.KeyEvent} for a list of
+            keycode names. Use the keycode name, not its integer value.
+          </td>
+        </tr>
+        <tr>
+          <th>type</th>
+          <td>
+            The type of key event to send. The allowed values are <code><a href="#ACTION_DOWN">
+            DOWN</a></code>, <code><a href="#ACTION_UP">UP</a></code>, and
+            <code><a href="#ACTION_DOWN_AND_UP">DOWN_AND_UP</a></code>.
+          </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>
+<A NAME="reboot"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">reboot</span>
+      <span class="normal">
+      (<em>string</em> bootloadType)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+                Reboots this device into the bootloader specified by <code>bootloadType</code>.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>into</th>
+          <td>
+            The type of bootloader to reboot into. The allowed values are
+            "bootloader", "recovery", or "None".
+          </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>
+<A NAME="removePackage"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">removePackage</span>
+      <span class="normal">
+      (<em>string</em> package)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Deletes the specified package from this device, including its data and cache.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>package</th>
+          <td>
+            The Android package name of an <code>.apk</code> file on this device.
+          </td>
+      </table>
+    </div>
+  </div>
+</div>
+<A NAME="shell"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <em>object</em>
+      </span>
+      <span class="sympad">shell</span>
+      <span class="normal">
+      (<em>string</em> cmd)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Executes an <code>adb</code> shell command and returns the result, if any.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>cmd</th>
+          <td>
+            The command to execute in the <code>adb</code> shell. The form of these commands is
+            described in the topic <a href="{@docRoot}guide/developing/tools/adb.html">Android
+            Debug Bridge</a>.
+          </td>
+        </tr>
+      </table>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist">
+        <li>
+            The results of the command, if any. The format of the results is determined by the
+            command.
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
+<A NAME="startActivity"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">startActivity</span>
+      <span class="normal">
+      (
+            <em>string</em> uri,
+            <em>string</em> action,
+            <em>string</em> data,
+            <em>string</em> mimetype,
+            <em>iterable</em> categories
+            <em>dictionary</em> extras,
+            <em>component</em> component,
+            <em>iterable</em> flags)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+           Starts an Activity on this device by sending an Intent constructed from the
+           supplied arguments.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>uri</th>
+          <td>
+            The URI for the Intent.
+            (see {@link android.content.Intent#setData(android.net.Uri) Intent.setData()}).
+          </td>
+        </tr>
+        <tr>
+            <th>action</th>
+            <td>
+                The action for the Intent
+                (see {@link android.content.Intent#setAction(java.lang.String) Intent.setAction()}).
+            </td>
+        </tr>
+        <tr>
+            <th>data</th>
+            <td>
+                The data URI for the Intent
+                (see {@link android.content.Intent#setData(android.net.Uri) Intent.setData()}).
+            </td>
+        </tr>
+        <tr>
+            <th>mimetype</th>
+            <td>
+                The MIME type for the Intent
+                (see {@link android.content.Intent#setType(java.lang.String) Intent.setType()}).
+            </td>
+        </tr>
+        <tr>
+            <th>categories</th>
+            <td>
+                An iterable data structure containing strings that define categories for the
+                Intent
+                (see
+                {@link android.content.Intent#addCategory(java.lang.String) Intent.addCategory()}).
+            </td>
+        </tr>
+        <tr>
+            <th>extras</th>
+            <td>
+                A dictionary of extra data for the Intent
+                (see
+                {@link android.content.Intent#putExtra(java.lang.String,java.lang.String)
+                Intent.putExtra()}
+                for an example).
+                <p>
+                    The key for each dictionary item should be a <em>string</em>. The item's value
+                    can be any simple or structured data type.
+                </p>
+            </td>
+        </tr>
+        <tr>
+            <th>component</th>
+            <td>
+                The component for the Intent
+                (see {@link android.content.ComponentName}). Using this argument will direct the
+                Intent to a specific class within a specific Android package.
+            </td>
+        </tr>
+        <tr>
+            <th>flags</th>
+            <td>
+                An iterable data structure containing flags that control how the Intent is handled
+                (see {@link android.content.Intent#setFlags(int) Intent.setFlags()}).
+            </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>
+<A NAME="takeSnapshot"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <code>
+            <a href="{@docRoot}guide/developing/tools/MonkeyImage.html">
+                MonkeyImage
+            </a>
+        </code>
+      </span>
+      <span class="sympad">takeSnapshot</span>
+      <span class="normal">
+      ()
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Captures the entire screen buffer of this device, yielding a
+            screen capture of the current display.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist">
+        <li>
+            A <a href="{@docRoot}guide/developing/tools/MonkeyImage.html">
+            MonkeyImage</a> object containing the image of the current display.
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
+<A NAME="touch"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">touch</span>
+      <span class="normal">
+      (
+            <em>integer</em> x,
+            <em>integer</em> y,
+            <em>string</em> type)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Sends a touch event specified by type to the screen location specified
+            by x and y.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>x</th>
+          <td>
+            The horizontal position of the touch in actual device pixels, starting from the left of
+            the screen in its current orientation.
+          </td>
+        </tr>
+        <tr>
+          <th>y</th>
+          <td>
+            The vertical position of the touch in actual device pixels, starting from the top of
+            the screen in its current orientation.
+          </td>
+        </tr>
+        <tr>
+            <th>type</th>
+            <td>
+                The type of key event to send. The allowed values are <code><a href="#ACTION_DOWN">
+                DOWN</a></code>, <code><a href="#ACTION_UP">UP</a></code>, and
+                <code><a href="#ACTION_DOWN_AND_UP">DOWN_AND_UP</a></code>.
+            </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>
+<A NAME="type"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">type</span>
+      <span class="normal">
+      (<em>string</em> message)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Sends the characters contained in message to this device, as if they
+            had been typed on the device's keyboard. This is equivalent to calling
+            <code><a href="#press">press()</a></code> for each keycode in <code>message</code>
+            using the key event type <code><a href="#ACTION_DOWN_AND_UP">DOWN_AND_UP</a></code>.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>message</th>
+          <td>
+              A string containing the characters to send.
+          </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>
+<A NAME="wake"></A>
+<div class="jd-details api">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">wake</span>
+      <span class="normal">
+      ()
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Wakes the screen of this device.
+        </p>
+    </div>
+  </div>
+</div>
+<hr></hr>
+<h2>Appendix</h2>
+    <p class="table-caption" id="table1">
+        <strong>Table 1.</strong>Property variable names used with
+        <span class="sympad"><a href="#getProperty">getProperty()</a></span> and
+        <span class="sympad"><a href="#getSystemProperty">getSystemProperty()</a></span>.
+    </p>
+    <table>
+        <tr>
+            <th>
+                Property Group
+            </th>
+            <th>
+                Property
+            </th>
+            <th>
+                Description
+            </th>
+            <th>
+                Notes
+            </th>
+        </tr>
+        <tr>
+            <td rowspan="17"><code>build</code></td>
+            <td><code>board</code></td>
+            <td>Code name for the device's system board</td>
+            <td rowspan="17">
+                See {@link android.os.Build}
+            </td>
+        </tr>
+        <tr>
+            <td><code>brand</code></td>
+            <td>The carrier or provider for which the OS is customized.</td>
+        </tr>
+            <tr>
+            <td><code>device</code></td>
+            <td>The device design name.</td>
+        </tr>
+            <tr>
+            <td><code>fingerprint</code></td>
+            <td>A unique identifier for the currently-running build.</td>
+        </tr>
+            <tr>
+            <td><code>host</code></td>
+            <td></td>
+        </tr>
+            <tr>
+            <td><code>ID</code></td>
+            <td>A changelist number or label.</td>
+        </tr>
+            <tr>
+            <td><code>model</code></td>
+            <td>The end-user-visible name for the device.</td>
+        </tr>
+            <tr>
+            <td><code>product</code></td>
+            <td>The overall product name.</td>
+        </tr>
+            <tr>
+            <td><code>tags</code></td>
+            <td>Comma-separated tags that describe the build, such as "unsigned" and "debug".</td>
+        </tr>
+            <tr>
+            <td><code>type</code></td>
+            <td>The build type, such as "user" or "eng".</td>
+        </tr>
+        <tr>
+            <td><code>user</code></td>
+            <td></td>
+        </tr>
+        <tr>
+            <td><code>CPU_ABI</code></td>
+            <td>
+                The name of the native code instruction set, in the form CPU type plus
+                ABI convention.
+            </td>
+        </tr>
+        <tr>
+            <td><code>manufacturer</code></td>
+            <td>The product/hardware manufacturer.</td>
+        </tr>
+        <tr>
+            <td><code>version.incremental</code></td>
+            <td>
+                The internal code used by the source control system to represent this version
+                of the software.
+            </td>
+        </tr>
+        <tr>
+            <td><code>version.release</code></td>
+            <td>The user-visible name of this version of the software.</td>
+        </tr>
+        <tr>
+            <td><code>version.sdk</code></td>
+            <td>The user-visible SDK version associated with this version of the OS.</td>
+        </tr>
+        <tr>
+            <td><code>version.codename</code></td>
+            <td>
+                The current development codename, or "REL" if this version of the software has been
+                released.
+            </td>
+        </tr>
+        <tr>
+            <td rowspan="3"><code>display</code></td>
+            <td><code>width</code></td>
+            <td>The device's display width in pixels.</td>
+            <td rowspan="3">
+                See
+                {@link android.util.DisplayMetrics} for details.
+            </td>
+        </tr>
+        <tr>
+            <td><code>height</code></td>
+            <td>The device's display height in pixels.</td>
+        </tr>
+        <tr>
+            <td><code>density</code></td>
+            <td>
+                The logical density of the display. This is a factor that scales
+                DIP (Density-Independent Pixel) units to the device's resolution. DIP is adjusted so
+                that 1 DIP is equivalent to one pixel on a 160 pixel-per-inch display. For example,
+                on a 160-dpi screen, density = 1.0, while on a 120-dpi screen, density = .75.
+                <p>
+                    The value does not exactly follow the real screen size, but is adjusted to
+                    conform to large changes in the display DPI. See
+                    {@link android.util.DisplayMetrics#density} for more details.
+                </p>
+            </td>
+        </tr>
+        <tr>
+            <td rowspan="6"><code>am.current</code></td>
+            <td><code>package</code></td>
+            <td>The Android package name of the currently running package.</td>
+            <td rowspan="6">
+                The <code>am.current</code> keys return information about the currently-running
+                Activity.
+            </td>
+        </tr>
+        <tr>
+            <td><code>action</code></td>
+            <td>
+                The current activity's action. This has the same format as the <code>name</code>
+                attribute of the <code>action</code> element in a package manifest.
+            </td>
+        </tr>
+        <tr>
+            <td><code>comp.class</code></td>
+            <td>
+                The class name of the component that started the current Activity. See
+                <code><a href="#comppackage">comp.package</a></code> for more details.</td>
+        </tr>
+        <tr>
+            <td><a name="comppackage"><code>comp.package</code></a></td>
+            <td>
+                The package name of the component that started the current Activity. A component
+                is specified by a package name and the name of class that the package contains.
+            </td>
+        </tr>
+        <tr>
+            <td><code>data</code></td>
+            <td>The data (if any) contained in the Intent that started the current Activity.</td>
+        </tr>
+        <tr>
+            <td><code>categories</code></td>
+            <td>The categories specified by the Intent that started the current Activity.</td>
+        </tr>
+        <tr>
+            <td rowspan="3"><code>clock</code></td>
+            <td><code>realtime</code></td>
+            <td>
+                The number of milliseconds since the device rebooted, including deep-sleep
+                time.
+            </td>
+            <td rowspan="3">
+                See {@link android.os.SystemClock} for more information.
+            </td>
+        </tr>
+        <tr>
+            <td><code>uptime</code></td>
+            <td>
+                The number of milliseconds since the device rebooted, <em>not</em> including
+                deep-sleep time
+            </td>
+        </tr>
+        <tr>
+            <td><code>millis</code></td>
+            <td>current time since the UNIX epoch, in milliseconds.</td>
+        </tr>
+    </table>
diff --git a/docs/html/guide/developing/tools/MonkeyImage.jd b/docs/html/guide/developing/tools/MonkeyImage.jd
new file mode 100644
index 0000000..ae85cb5
--- /dev/null
+++ b/docs/html/guide/developing/tools/MonkeyImage.jd
@@ -0,0 +1,435 @@
+page.title=MonkeyImage
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+
+<p>
+    A monkeyrunner class to hold an image of the device or emulator's screen. The image is
+    copied from the screen buffer during a screenshot. This object's methods allow you to
+    convert the image into various storage formats, write the image to a file, copy parts of
+    the image, and compare this object to other <code>MonkeyImage</code> objects.
+</p>
+<p>
+    You do not need to create new instances of <code>MonkeyImage</code>. Instead, use
+<code><a href="{@docRoot}guide/developing/tools/MonkeyDevice.html#takeSnapshot">
+MonkeyDevice.takeSnapshot()</a></code> to create a new instance from a screenshot. For example, use:
+</p>
+<pre>
+newimage = MonkeyDevice.takeSnapshot()
+</pre>
+<h2>Summary</h2>
+<table id="pubmethods" class="jd-sumtable">
+    <tr>
+        <th colspan="12" style="background-color: #E2E2E2">Methods</th>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <em>string</em>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#convertToBytes">convertToBytes</a>
+                </span>
+                (<em>string</em> format)
+            </nobr>
+            <div class="jd-descrdiv">
+                Converts the current image to a particular format and returns it as a
+                <em>string</em> that you can then access as an <em>iterable</em> of binary bytes.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <em>tuple</em>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#getRawPixel">getRawPixel</a>
+                </span>
+                (<em>integer</em> x,
+                <em>integer</em> y)
+            </nobr>
+            <div class="jd-descrdiv">
+                Returns the single pixel at the image location (x,y), as an
+                a <em>tuple</em> of <em>integer</em>, in the form (a,r,g,b).
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <em>integer</em>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#getRawPixelInt">getRawPixelInt</a>
+                </span>
+                (<em>integer</em> x,
+                 <em>integer</em> y)
+            </nobr>
+            <div class="jd-descrdiv">
+                Returns the single pixel at the image location (x,y), as
+                a 32-bit <em>integer</em>.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <code>
+                    <a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a>
+                </code>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#getSubImage">getSubImage</a>
+                </span>
+                (<em>tuple</em> rect)
+            </nobr>
+            <div class="jd-descrdiv">
+                Creates a new <code>MonkeyImage</code> object from a rectangular selection of the
+                current image.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <em>boolean</em>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#sameAs">sameAs</a>
+                </span>
+         (<code><a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a></code>
+            other,
+            <em>float</em> percent)
+            </nobr>
+            <div class="jd-descrdiv">
+                Compares this <code>MonkeyImage</code> object to another and returns the result of
+                the comparison. The <code>percent</code> argument specifies the percentage
+                difference that is allowed for the two images to be "equal".
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <em>void</em>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#writeToFile">writeToFile</a>
+                </span>
+                (<em>string</em> path,
+                <em>string</em> format)
+            </nobr>
+            <div class="jd-descrdiv">
+                Writes the current image to the file specified by <code>filename</code>, in the
+                format specified by <code>format</code>.
+            </div>
+        </td>
+    </tr>
+</table>
+<!-- ========= METHOD DETAIL ======== -->
+<!-- Public methods -->
+<h2>Public Methods</h2>
+<A NAME="convertToBytes"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <em>string</em>
+      </span>
+      <span class="sympad">convertToBytes</span>
+      <span class="normal">
+      (
+            <em>string</em> format)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Converts the current image to a particular format and returns it as a <em>string</em>
+            that you can then access as an <em>iterable</em> of binary bytes.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>format</th>
+            <td>
+                The desired output format. All of the common raster output formats are supported.
+                The default value is "png" (Portable Network Graphics).
+            </td>
+        </tr>
+        </table>
+    </div>
+</div>
+</div>
+<A NAME="getRawPixel"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <em>tuple</em>
+      </span>
+      <span class="sympad">getRawPixel</span>
+      <span class="normal">
+        (<em>integer</em> x,
+         <em>integer</em> y)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Returns the single pixel at the image location (x,y), as an
+            a <em>tuple</em> of <em>integer</em>, in the form (a,r,g,b).
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>x</th>
+          <td>
+            The horizontal position of the pixel, starting with 0 at the left of the screen in the
+            orientation it had when the screenshot was taken.
+          </td>
+        </tr>
+        <tr>
+          <th>y</th>
+          <td>
+            The vertical position of the pixel, starting with 0 at the top of the screen in the
+            orientation it had when the screenshot was taken.
+          </td>
+        </tr>
+      </table>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist">
+        <li>
+            A tuple of integers representing the pixel, in the form (a,r,g,b) where
+            a is the alpha channel value, and r, g, and b are the red, green, and blue values,
+            respectively.
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
+<A NAME="getRawPixelInt"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <em>tuple</em>
+      </span>
+      <span class="sympad">getRawPixelInt</span>
+      <span class="normal">
+        (<em>integer</em> x,
+         <em>integer</em> y)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Returns the single pixel at the image location (x,y), as an
+            an <em>integer</em>. Use this method to economize on memory.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>x</th>
+          <td>
+            The horizontal position of the pixel, starting with 0 at the left of the screen in the
+            orientation it had when the screenshot was taken.
+          </td>
+        </tr>
+        <tr>
+          <th>y</th>
+          <td>
+            The vertical position of the pixel, starting with 0 at the top of the screen in the
+            orientation it had when the screenshot was taken.
+          </td>
+        </tr>
+      </table>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist">
+        <li>
+            The a,r,g, and b values of the pixel as 8-bit values combined into a 32-bit
+            integer, with a as the leftmost 8 bits, r the next rightmost, and so forth.
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
+<A NAME="getSubImage"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+          <code>
+              <a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a>
+          </code>
+      </span>
+      <span class="sympad">getSubImage</span>
+      <span class="normal">
+        (<em>tuple</em> rect)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+           Creates a new <code>MonkeyImage</code> object from a rectangular selection of the
+           current image.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>rect</th>
+          <td>
+            A tuple (x, y, w, h) specifying the selection. x and y specify the 0-based pixel
+            position of the upper left-hand corner of the selection. w specifies the width of the
+            region, and h specifies its height, both in units of pixels.
+            <p>
+                The image's orientation is the same as the screen orientation at the time the
+                screenshot was made.
+            </p>
+          </td>
+        </tr>
+      </table>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist">
+        <li>
+            A new <code>MonkeyImage</code> object containing the selection.
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
+<A NAME="sameAs"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <em>boolean</em>
+      </span>
+      <span class="sympad">sameAs</span>
+      <span class="normal">
+      (
+       <code>
+           <a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a>
+       </code> otherImage,
+       <em>float</em> percent
+      )
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+           Compares this <code>MonkeyImage</code> object to another and returns the result of
+           the comparison. The <code>percent</code> argument specifies the percentage
+           difference that is allowed for the two images to be "equal".
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>other</th>
+          <td>
+            Another <code>MonkeyImage</code> object to compare to this one.
+          </td>
+        </tr>
+        <tr>
+          <th>
+            percent
+          </th>
+          <td>
+            A float in the range 0.0 to 1.0, inclusive, indicating
+            the percentage of pixels that need to be the same for the method to return
+            <code>true</code>. The default is 1.0, indicating that all the pixels
+            must match.
+          </td>
+        </tr>
+      </table>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist">
+        <li>
+            Boolean <code>true</code> if the images match, or boolean <code>false</code> otherwise.
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
+<A NAME="writeToFile"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">writeToFile</span>
+      <span class="normal">
+      (<em>string</em> filename,
+       <em>string</em> format)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+           Writes the current image to the file specified by <code>filename</code>, in the
+           format specified by <code>format</code>.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>path</th>
+          <td>
+            The fully-qualified filename and extension of the output file.
+          </td>
+        </tr>
+        <tr>
+            <th>
+                format
+            </th>
+            <td>
+                The output format to use for the file. If no format is provided, then the
+                method tries to guess the format from the filename's extension. If no
+                extension is provided and no format is specified, then the default format of
+                "png" (Portable Network Graphics) is used.
+            </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>
diff --git a/docs/html/guide/developing/tools/MonkeyRunner.jd b/docs/html/guide/developing/tools/MonkeyRunner.jd
new file mode 100644
index 0000000..871e06d
--- /dev/null
+++ b/docs/html/guide/developing/tools/MonkeyRunner.jd
@@ -0,0 +1,445 @@
+page.title=MonkeyRunner
+@jd:body
+<style>
+    h4.jd-details-title {background-color: #DEE8F1;}
+</style>
+<p>
+    A monkeyrunner class that contains static utility methods.
+</p>
+<h2>Summary</h2>
+<table id="pubmethods" class="jd-sumtable">
+    <tr>
+        <th colspan="12" style="background-color: #E2E2E2">Methods</th>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#alert">alert</a>
+                </span>
+                (<em>string</em> message,
+                 <em>string</em> title,
+                 <em>string</em> okTitle)
+            </nobr>
+            <div class="jd-descrdiv">
+                Displays an alert dialog to the process running the current
+                program.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <em>integer</em>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#choice">choice</a>
+                </span>
+                (<em>string</em> message,
+                 <em>iterable</em> choices,
+                 <em>string</em> title)
+            </nobr>
+            <div class="jd-descrdiv">
+                Displays a dialog with a list of choices to the process running the current program.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#help">help</a>
+                </span>
+                (<em>string</em> format)
+            </nobr>
+            <div class="jd-descrdiv">
+                Displays the monkeyrunner API reference in a style similar to that of Python's
+                <code>pydoc</code> tool, using the specified format.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <em>string</em>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#input">input</a>
+                </span>
+                (<em>string</em> message,
+                 <em>string</em> initialValue,
+                 <em>string</em> title,
+                 <em>string</em> okTitle,
+                 <em>string</em> cancelTitle)
+            </nobr>
+            <div class="jd-descrdiv">
+                Displays a dialog that accepts input.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                void
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#sleep">sleep</a>
+                </span>
+                (<em>float</em> seconds)
+            </nobr>
+            <div class="jd-descrdiv">
+                Pauses the current program for the specified number of seconds.
+            </div>
+        </td>
+    </tr>
+    <tr class="api" >
+        <td class="jd-typecol">
+            <nobr>
+                <code>
+                    <a href="{@docRoot}guide/developing/tools/MonkeyDevice.html">MonkeyDevice</a>
+                </code>
+            </nobr>
+        </td>
+        <td class="jd-linkcol" width="100%">
+            <nobr>
+                <span class="sympad">
+                    <a href="#waitForConnection">waitForConnection</a>
+                </span>
+                (<em>float</em> timeout,
+                <em>string</em> deviceId)
+            </nobr>
+            <div class="jd-descrdiv">
+                Tries to make a connection between the <code>monkeyrunner</code> backend and the
+                specified device or emulator.
+            </div>
+        </td>
+    </tr>
+</table>
+<!-- ========= METHOD DETAIL ======== -->
+<!-- Public methods -->
+<h2>Public Methods</h2>
+<A NAME="alert"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <em>string</em>
+      </span>
+      <span class="sympad">alert</span>
+      <span class="normal">
+      (
+            <em>string</em> message,
+            <em>string</em> title,
+            <em>string</em> okTitle)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Displays an alert dialog to the process running the current
+            program. The dialog is modal, so the program pauses until the user clicks the dialog's
+            button.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>message</th>
+            <td>
+                The message to display in the dialog.
+            </td>
+        </tr>
+        <tr>
+            <th>title</th>
+            <td>
+                The dialog's title. The default value is "Alert".
+            </td>
+        </tr>
+        <tr>
+            <th>okTitle</th>
+            <td>
+                The text displayed in the dialog button. The default value is "OK".
+            </td>
+        </tr>
+        </table>
+    </div>
+</div>
+</div>
+<A NAME="choice"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <em>integer</em>
+      </span>
+      <span class="sympad">choice</span>
+      <span class="normal">
+        (<em>string</em> message,
+         <em>iterable</em> choices,
+         <em>string</em> title)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Displays a dialog with a list of choices to the process running the current program. The
+            dialog is modal, so the program pauses until the user clicks one of the dialog's
+            buttons.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>message</th>
+          <td>
+            The prompt message displayed in the dialog.
+          </td>
+        </tr>
+        <tr>
+          <th>choices</th>
+          <td>
+            A Python iterable containing one or more objects that are displayed as strings. The
+            recommended form is an array of strings.
+          </td>
+        </tr>
+        <tr>
+            <th>
+                title
+            </th>
+            <td>
+               The dialog's title. The default is "Input".
+            </td>
+        </tr>
+      </table>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist">
+        <li>
+            If the user makes a selection and clicks the "OK" button, the method returns
+            the 0-based index of the selection within the iterable.
+            If the user clicks the "Cancel" button, the method returns -1.
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
+<A NAME="help"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">help</span>
+      <span class="normal">
+        (<em>string</em> format)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Displays the monkeyrunner API reference in a style similar to that of Python's
+            <code>pydoc</code> tool, using the specified format.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>format</th>
+          <td>
+            The markup format to use in the output. The possible values are "text" for plain text
+            or "html" for HTML.
+          </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>
+<A NAME="input"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        <em>string</em>
+      </span>
+      <span class="sympad">input</span>
+      <span class="normal">
+        (<em>string</em> message
+         <em>string</em> initialValue,
+         <em>string</em> title,
+         <em>string</em> okTitle,
+         <em>string</em> cancelTitle)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Displays a dialog that accepts input and returns it to the program. The dialog is
+            modal, so the program pauses until the user clicks one of the dialog's buttons.
+        </p>
+        <p>
+            The dialog contains two buttons, one of which displays the okTitle value
+            and the other the cancelTitle value. If the user clicks the okTitle button,
+            the current value of the input box is returned. If the user clicks the cancelTitle
+            button, an empty string is returned.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>message</th>
+          <td>
+            The prompt message displayed in the dialog.
+          </td>
+        </tr>
+        <tr>
+          <th>initialValue</th>
+          <td>
+            The initial value to display in the dialog. The default is an empty string.
+          </td>
+        </tr>
+        <tr>
+          <th>title</th>
+          <td>
+            The dialog's title. The default is "Input".
+          </td>
+        </tr>
+        <tr>
+          <th>okTitle</th>
+          <td>
+            The text displayed in the okTitle button. The default is "OK".
+          </td>
+        </tr>
+        <tr>
+          <th>cancelTitle</th>
+          <td>
+            The text displayed in the cancelTitle button. The default is "Cancel".
+          </td>
+        </tr>
+      </table>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist">
+        <li>
+            If the user clicks the okTitle button, then the method returns the current value of
+            the dialog's input box. If the user clicks the cancelTitle button, the method returns
+            an empty string.
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
+<A NAME="sleep"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+        void
+      </span>
+      <span class="sympad">sleep</span>
+      <span class="normal">
+      (
+       <em>float</em> seconds
+      )
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Pauses the current program for the specified number of seconds.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>seconds</th>
+          <td>
+            The number of seconds to pause.
+          </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+</div>
+<A NAME="waitForConnection"></A>
+<div class="jd-details api ">
+    <h4 class="jd-details-title">
+      <span class="normal">
+          <code>
+              <a href="{@docRoot}guide/developing/tools/MonkeyDevice.html">MonkeyDevice</a>
+          </code>
+      </span>
+      <span class="sympad">waitForConnection</span>
+      <span class="normal">
+      (<em>float</em> timeout,
+       <em>string</em> deviceId)
+      </span>
+    </h4>
+  <div class="jd-details-descr">
+
+    <div class="jd-tagdata jd-tagdescr">
+        <p>
+            Tries to make a connection between the <code>monkeyrunner</code> backend and the
+            specified device or emulator.
+        </p>
+    </div>
+    <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Arguments</h5>
+      <table class="jd-tagtable">
+        <tr>
+          <th>timeout</th>
+          <td>
+            The number of seconds to wait for a connection. The default is to wait forever.
+          </td>
+        </tr>
+        <tr>
+            <th>
+                deviceId
+            </th>
+            <td>
+                A regular expression that specifies the serial number of the device or emulator. See
+                the topic
+                <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a>
+                for a description of device and emulator serial numbers.
+            </td>
+        </tr>
+      </table>
+    </div>
+        <div class="jd-tagdata">
+      <h5 class="jd-tagtitle">Returns</h5>
+      <ul class="nolist">
+        <li>
+          A <code><a href="{@docRoot}guide/developing/tools/MonkeyDevice.html">MonkeyDevice</a></code>
+          instance for the device or emulator. Use this object to control and communicate with the
+          device or emulator.
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
diff --git a/docs/html/guide/developing/tools/index.jd b/docs/html/guide/developing/tools/index.jd
index 6e9fde1..0e10377 100644
--- a/docs/html/guide/developing/tools/index.jd
+++ b/docs/html/guide/developing/tools/index.jd
@@ -3,27 +3,27 @@
 
 <img src="{@docRoot}assets/images/android_wrench.png" alt="" align="right">
 
-<p>The Android SDK includes a variety of custom tools that help you develop mobile 
-applications on the Android platform. The most important of these are the Android 
-Emulator and the Android Development Tools plugin for Eclipse, but the SDK also 
-includes a variety of other tools for debugging, packaging, and installing your 
+<p>The Android SDK includes a variety of custom tools that help you develop mobile
+applications on the Android platform. The most important of these are the Android
+Emulator and the Android Development Tools plugin for Eclipse, but the SDK also
+includes a variety of other tools for debugging, packaging, and installing your
 applications on the emulator. </p>
-    
+
  <dl>
   <dt><a href="adt.html">Android Development Tools Plugin</a> (for the Eclipse IDE)</dt>
-          <dd>The ADT plugin adds powerful extensions to the Eclipse integrated environment, 
-          making creating and debugging your Android applications easier and faster. If you 
-          use Eclipse, the ADT plugin gives you an incredible boost in developing Android 
+          <dd>The ADT plugin adds powerful extensions to the Eclipse integrated environment,
+          making creating and debugging your Android applications easier and faster. If you
+          use Eclipse, the ADT plugin gives you an incredible boost in developing Android
           applications.</dd>
   <dt><a href="emulator.html">Android Emulator</a></dt>
-    <dd>A QEMU-based device-emulation tool that you can use to design, 
+    <dd>A QEMU-based device-emulation tool that you can use to design,
     debug, and test your applications in an actual Android run-time environment. </dd>
 
   <dt><a href="avd.html">Android Virtual Devices (AVDs)</a></dt>
     <dd>Virtual device configurations that you create, to model device
         characteristics in the Android Emulator. In each configuration, you can
         specify the Android platform to run, the hardware options, and the
-        emulator skin to use. Each AVD functions as an independent device with 
+        emulator skin to use. Each AVD functions as an independent device with
         it's own storage for user data, SD card, and so on. </dd>
 
  <dt><a href="hierarchy-viewer.html">Hierarchy Viewer</a></dt>
@@ -37,53 +37,53 @@
 efficiency.
     </dd>
 
-	  <dt><a href="draw9patch.html">Draw 9-patch</a></dt>
-	    <dd>The Draw 9-patch tool allows you to easily create a 
-	    {@link android.graphics.NinePatch} graphic using a WYSIWYG editor. It also previews stretched 
-	     versions of the image, and highlights the area in which content is allowed.
-	    </dd>
+      <dt><a href="draw9patch.html">Draw 9-patch</a></dt>
+        <dd>The Draw 9-patch tool allows you to easily create a
+        {@link android.graphics.NinePatch} graphic using a WYSIWYG editor. It also previews stretched
+         versions of the image, and highlights the area in which content is allowed.
+        </dd>
 
-  <dt><a href="ddms.html" >Dalvik Debug Monitor 
+  <dt><a href="ddms.html" >Dalvik Debug Monitor
       Service</a> (ddms)</dt>
-	    <dd>Integrated with Dalvik, the Android platform's custom VM, this tool 
-	    lets you manage processes on an emulator or device and assists in debugging. 
-	    You can use it to kill processes, select a specific process to debug, 
-	    generate trace data, view heap and thread information, take screenshots 
-	    of the emulator or device, and more. </dd>
-			
+        <dd>Integrated with Dalvik, the Android platform's custom VM, this tool
+        lets you manage processes on an emulator or device and assists in debugging.
+        You can use it to kill processes, select a specific process to debug,
+        generate trace data, view heap and thread information, take screenshots
+        of the emulator or device, and more. </dd>
+
   <dt><a href="adb.html" >Android Debug Bridge</a> (adb)</dt>
-                  <dd>The adb tool lets you install your application's .apk files on an 
-                  emulator or device and access the emulator or device from a command line. 
-                  You can also use it to link a standard debugger to application code running 
+                  <dd>The adb tool lets you install your application's .apk files on an
+                  emulator or device and access the emulator or device from a command line.
+                  You can also use it to link a standard debugger to application code running
                   on an Android emulator or device.</dd>
 
-  <dt><a href="aapt.html">Android Asset 
+  <dt><a href="aapt.html">Android Asset
           Packaging Tool</a> (aapt)</dt>
-                  <dd>The aapt tool lets you create .apk files containing the binaries and 
+                  <dd>The aapt tool lets you create .apk files containing the binaries and
                   resources of Android applications.</dd>
 
-  <dt><a href="aidl.html" >Android Interface 
+  <dt><a href="aidl.html" >Android Interface
   Description Language</a> (aidl)</dt>
             <dd>Lets you generate code for an interprocess interface, such as what
             a service might use.</dd>
 
   <dt><a href="adb.html#sqlite">sqlite3</a></dt>
-      <dd>Included as a convenience, this tool lets you access the SQLite data 
+      <dd>Included as a convenience, this tool lets you access the SQLite data
       files created and used by Android applications.</dd>
 
   <dt><a href="traceview.html" >Traceview</a></dt>
-            <dd> This tool produces graphical analysis views of trace log data that you 
+            <dd> This tool produces graphical analysis views of trace log data that you
             can generate from your Android application. </dd>
 
   <dt><a href="othertools.html#mksdcard">mksdcard</a></dt>
-            <dd>Helps you create a disk image that you can use with the emulator, 
+            <dd>Helps you create a disk image that you can use with the emulator,
                       to simulate the presence of an external storage card (such as an SD card).</dd>
 
   <dt><a href="othertools.html#dx">dx</a></dt>
-                  <dd>The dx tool rewrites .class bytecode into Android bytecode 
+                  <dd>The dx tool rewrites .class bytecode into Android bytecode
                                           (stored in .dex files.)</dd>
 
-  <dt><a href="monkey.html">UI/Application 
+  <dt><a href="monkey.html">UI/Application
   Exerciser Monkey</a></dt>
       <dd>The Monkey is a program that runs on your emulator or device and generates pseudo-random
       streams of user events such as clicks, touches, or gestures, as well as a number of system-
@@ -92,9 +92,9 @@
 
   <dt><a  href="othertools.html#android">android</a></dt>
             <dd>A script that lets you manage AVDs and generate <a
-                        href="http://ant.apache.org/" title="Ant">Ant</a> build files that 
+                        href="http://ant.apache.org/" title="Ant">Ant</a> build files that
                         you can use to compile your Android applications. </dd>
-                        
+
   <dt><a  href="zipalign.html">zipalign</a></dt>
             <dd>An important .apk optimization tool. This tool ensures that all uncompressed data starts
             with a particular alignment relative to the start of the file. This should always be used
diff --git a/docs/html/guide/developing/tools/monkeyrunner_concepts.jd b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd
new file mode 100644
index 0000000..1838905
--- /dev/null
+++ b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd
@@ -0,0 +1,308 @@
+page.title=monkeyrunner
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li>
+        <a href="#SampleProgram">A Simple monkeyrunner Program</a>
+    </li>
+    <li>
+        <a href="#APIClasses">The monkeyrunner API</a>
+    </li>
+    <li>
+        <a href="#RunningMonkeyRunner">Running monkeyrunner</a>
+    </li>
+    <li>
+        <a href="#Help">monkeyrunner Built-in Help</a>
+    </li>
+    <li>
+        <a href="#Plugins">Extending monkeyrunner with Plugins</a>
+    </li>
+  </ol>
+  <h2>See Also</h2>
+      <ol>
+        <li>
+            <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>
+        </li>
+      </ol>
+  </div>
+</div>
+<p>
+    The monkeyrunner tool provides an API for writing programs that control an Android device
+    or emulator from outside of Android code. With monkeyrunner, you can write a Python program
+    that installs an Android application or test package, runs it, sends keystrokes to it,
+    takes screenshots of its user interface, and stores screenshots on the workstation. The
+    monkeyrunner tool is primarily designed to test applications and devices at the
+    functional/framework level and for running unit test suites, but you are free to use it for
+    other purposes.
+</p>
+<p>
+    The monkeyrunner tool is not related to the
+    <a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>,
+    also known as the <code>monkey</code> tool. The <code>monkey</code> tool runs in an
+    <code><a href="{@docRoot}guide/developing/tools/adb.html">adb</a></code> shell directly on the
+    device or emulator and generates pseudo-random streams of user and system events. In comparison,
+    the monkeyrunner tool controls devices and emulators from a workstation by sending specific
+    commands and events from an API.
+</p>
+<p>
+    The monkeyrunner tool provides these unique features for Android testing:
+</p>
+<ul>
+    <li>
+        Multiple device control: The monkeyrunner API can apply one or more
+        test suites across multiple devices or emulators. You can physically attach all the devices
+        or start up all the emulators (or both) at once, connect to each one in turn
+        programmatically, and then run one or more tests. You can also start up an emulator
+        configuration programmatically, run one or more tests, and then shut down the emulator.
+    </li>
+    <li>
+        Functional testing: monkeyrunner can run an automated start-to-finish test of an Android
+        application. You provide input values with keystrokes or touch events, and view the results
+        as screenshots.
+    </li>
+    <li>
+        Regression testing - monkeyrunner can test application stability by running an application
+        and comparing its output screenshots to a set of screenshots that are known to be correct.
+    </li>
+    <li>
+        Extensible automation - Since monkeyrunner is an API toolkit, you can develop an entire
+        system of Python-based modules and programs for controlling Android devices. Besides using
+        the monkeyrunner API itself, you can use the standard Python
+        <code><a href="http://docs.python.org/library/os.html">os</a></code> and
+        <code><a href="http://docs.python.org/library/subprocess.html">subprocess</a></code>
+        modules to call Android tools such as
+        <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a>.
+        <p>
+            You can also add your own classes to the monkeyrunner API. This is described
+            in more detail in the section
+            <a href="#Plugins">Extending monkeyrunner with plugins</a>.
+        </p>
+    </li>
+</ul>
+<p>
+    The monkeyrunner tool uses <a href="http://www.jython.org/">Jython</a>, a
+    implementation of Python that uses the Java programming language. Jython allows the
+    monkeyrunner API to interact easily with the Android framework. With Jython you can
+    use Python syntax to access the constants, classes, and methods of the API.
+</p>
+
+<h2 id="SampleProgram">A Simple monkeyrunner Program</h2>
+<p>
+    Here is a simple monkeyrunner program that connects to a device, creating a
+    <code><a href="{@docRoot}guide/developing/tools/MonkeyDevice.html">MonkeyDevice</a></code>
+    object. Using the <code>MonkeyDevice</code> object, the program installs an Android application
+    package, runs one of its activities, and sends key events to the activity.
+    The program then takes a screenshot of the result, creating a
+    <code><a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a></code> object.
+    From this object, the program writes out a <code>.png</code> file containing the screenshot.
+</p>
+<pre>
+# Imports the monkeyrunner modules used by this program
+from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
+
+# Connects to the current device, returning a MonkeyDevice object
+device = MonkeyRunner.waitForConnection()
+
+# Installs the Android package. Notice that this method returns a boolean, so you can test
+# to see if the installation worked.
+device.installPackage('myproject/bin/MyApplication.apk')
+
+# Runs an activity in the application
+device.startActivity(component='com.example.android.myapplication.MainActivity')
+
+# Presses the Menu button
+device.press('KEYCODE_MENU','DOWN_AND_UP')
+
+# Takes a screenshot
+result = device.takeSnapShot
+
+# Writes the screenshot to a file
+result.writeToFile('myproject/shot1.png','png')
+</pre>
+
+<h2 id="APIClasses">The monkeyrunner API</h2>
+<p>
+    The monkeyrunner API is contained in three modules in the package
+    <code>com.android.monkeyrunner</code>:
+</p>
+<ul>
+    <li>
+        <code><a href="{@docRoot}guide/developing/tools/MonkeyRunner.html">MonkeyRunner</a></code>:
+        A class of utility methods for monkeyrunner programs. This class provides a method for
+        connecting monkeyrunner to a device or emulator. It also provides methods for
+        creating UIs for a monkeyrunner program and for displaying the built-in help.
+    </li>
+    <li>
+        <code><a href="{@docRoot}guide/developing/tools/MonkeyDevice.html">MonkeyDevice</a></code>:
+        Represents a device or emulator. This class provides methods for installing and
+        uninstalling packages, starting an Activity, and sending keyboard or touch events to an
+        application. You also use this class to run test packages.
+    </li>
+    <li>
+        <code><a href="{@docRoot}guide/developing/tools/MonkeyImage.html">MonkeyImage</a></code>:
+        Represents a screen capture image. This class provides methods for capturing screens,
+        converting bitmap images to various formats, comparing two MonkeyImage objects, and
+        writing an image to a file.
+    </li>
+</ul>
+<p>
+    In a Python program, you access each class as a Python module. The monkeyrunner tool
+    does not import these modules automatically. To import a module, use the
+    Python <code>from</code> statement:
+</p>
+<pre>
+from com.android.monkeyrunner import &lt;module&gt;
+</pre>
+<p>
+    where <code>&lt;module&gt;</code> is the class name you want to import. You can import more
+    than one module in the same <code>from</code> statement by separating the module names with
+    commas.
+</p>
+<h2 id="RunningMonkeyRunner">Running monkeyrunner</h2>
+<p>
+    You can either run monkeyrunner programs from a file, or enter monkeyrunner statements in
+    an interactive session. You do both by invoking the <code>monkeyrunner</code> command
+    which is found in the <code>tools/</code> subdirectory of your SDK directory.
+    If you provide a filename as an argument, the <code>monkeyrunner</code> command
+    runs the file's contents as a Python program; otherwise, it starts an interactive session.
+</p>
+<p>
+    The syntax of the <code>monkeyrunner</code> command is
+</p>
+<pre>
+monkeyrunner -plugin &lt;plugin_jar&gt; &lt;program_filename&gt; &lt;program_options&gt;
+</pre>
+<p>
+Table 1 explains the flags and arguments.
+</p>
+<p class="table-caption" id="table1">
+  <strong>Table 1.</strong> <code>monkeyrunner</code> flags and arguments.</p>
+
+<table>
+    <tr>
+        <th>Argument</th>
+        <th>Description</th>
+    </tr>
+    <tr>
+        <td>
+            <nobr>
+                <code>-plugin &lt;plugin_jar&gt;</code>
+            </nobr>
+        </td>
+        <td>
+            (Optional) Specifies a <code>.jar</code> file containing a plugin for monkeyrunner.
+            To learn more about monkeyrunner plugins, see
+            <a href="#Plugins">Extending monkeyrunner with plugins</a>. To specify more than one
+            file, include the argument multiple times.
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <nobr>
+                <code>&lt;program_filename&gt;</code>
+            </nobr>
+        </td>
+        <td>
+            If you provide this argument, the <code>monkeyrunner</code> command runs the contents
+            of the file as a Python program. If the argument is not provided, the command starts an
+            interactive session.
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <code>&lt;program_options&gt;</code>
+        </td>
+        <td>
+            (Optional) Flags and arguments for the program in &lt;program_file&gt;.
+        </td>
+    </tr>
+</table>
+<h2 id="Help">monkeyrunner Built-in Help</h2>
+<p>
+    You can generate an API reference for monkeyrunner by running:
+</p>
+<pre>
+monkeyrunner &lt;format&gt; help.py &lt;outfile&gt;
+</pre>
+<p>
+The arguments are:
+</p>
+    <ul>
+        <li>
+            <code>&lt;format&gt;</code> is either <code>text</code> for plain text output
+            or <code>html</code> for HTML output.
+        </li>
+        <li>
+            <code>&lt;outfile&gt;</code> is a path-qualified name for the output file.
+        </li>
+    </ul>
+<h2 id="Plugins">Extending monkeyrunner with Plugins</h2>
+<p>
+    You can extend the monkeyrunner API with classes you write in the Java programming language
+    and build into one or more <code>.jar</code> files. You can use this feature to extend the
+    monkeyrunner API with your own classes or to extend the existing classes. You can also use this
+    feature to initialize the monkeyrunner environment.
+</p>
+<p>
+    To provide a plugin to monkeyrunner, invoke the <code>monkeyrunner</code> command with the
+    <code>-plugin &lt;plugin_jar&gt;</code> argument described in
+    <a href="#table1">table 1</a>.
+</p>
+<p>
+    In your plugin code, you can import and extend the the main monkeyrunner classes
+    <code>MonkeyDevice</code>, <code>MonkeyImage</code>, and <code>MonkeyRunner</code> in
+    <code>com.android.monkeyrunner</code> (see <a href="#APIClasses">The monkeyrunner API</a>).
+</p>
+<p>
+    Note that plugins do not give you access to the Android SDK. You can't import packages
+    such as <code>com.android.app</code>. This is because monkeyrunner interacts with the
+    device or emulator below the level of the framework APIs.
+</p>
+<h3>The plugin startup class</h3>
+<p>
+    The <code>.jar</code> file for a plugin can specify a class that is instantiated before
+    script processing starts. To specify this class, add the key
+    <code>MonkeyRunnerStartupRunner</code> to the <code>.jar</code> file's
+    manifest. The value should be the name of the class to run at startup. The following
+    snippet shows how you would do this within an <code>ant</code> build script:
+</p>
+<pre>
+&lt;jar jarfile=&quot;myplugin&quot; basedir="&#36;&#123;build.dir&#125;&quot;&gt;
+&lt;manifest&gt;
+&lt;attribute name=&quot;MonkeyRunnerStartupRunner&quot; value=&quot;com.myapp.myplugin&quot;/&gt;
+&lt;/manifest&gt;
+&lt;/jar&gt;
+
+
+</pre>
+<p>
+    To get access to monkeyrunner's runtime environment, the startup class can implement
+    <code>com.google.common.base.Predicate&lt;PythonInterpreter&gt;</code>. For example, this
+    class sets up some variables in the default namespace:
+</p>
+<pre>
+package com.android.example;
+
+import com.google.common.base.Predicate;
+import org.python.util.PythonInterpreter;
+
+public class Main implements Predicate&lt;PythonInterpreter&gt; {
+    &#64;Override
+    public boolean apply(PythonInterpreter anInterpreter) {
+
+        /*
+        * Examples of creating and initializing variables in the monkeyrunner environment's
+        * namespace. During execution, the monkeyrunner program can refer to the variables "newtest"
+        * and "use_emulator"
+        *
+        */
+        anInterpreter.set("newtest", "enabled");
+        anInterpreter.set("use_emulator", 1);
+
+        return true;
+    }
+}
+</pre>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 2b803424..a43e334 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -254,34 +254,45 @@
             <li><a href="<?cs var:toroot?>guide/topics/search/searchable-config.html">Searchable Configuration</a></li>
           </ul>
       </li>
-      <li class="toggle-list">
-           <div>
-                <a href="<?cs var:toroot ?>guide/topics/testing/index.html">
-                   <span class="en">Testing</span>
-               </a> <span class="new">new!</span>
-           </div>
-           <ul>
-              <li><a href="<?cs var:toroot?>guide/topics/testing/testing_android.html">
-                <span class="en">Testing Fundamentals</span></a>
-              </li>
-              <li><a href="<?cs var:toroot?>guide/topics/testing/activity_testing.html">
-                <span class="en">Activity Testing</span></a>
-              </li>
-              <li><a href="<?cs var:toroot ?>guide/topics/testing/contentprovider_testing.html">
-                <span class="en">Content Provider Testing</span></a>
-              </li>
-              <li><a href="<?cs var:toroot ?>guide/topics/testing/service_testing.html">
-                <span class="en">Service Testing</span></a>
-              </li>
-              <li><a href="<?cs var:toroot ?>guide/topics/testing/what_to_test.html">
-                <span class="en">What To Test</span></a>
-              </li>
-           </ul>
-      </li>
-     <li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html">
+      <li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html">
             <span class="en">Device Administration</span>
          </a> <span class="new">new!</span>
-    </li>
+      </li>
+      <li class="toggle-list">
+           <div>
+                <a href="<?cs var:toroot?>guide/topics/testing/index.html">
+                   <span class="en">Testing</span>
+               </a>
+           </div>
+           <ul>
+              <li>
+                <a href="<?cs var:toroot?>guide/topics/testing/testing_android.html">
+                <span class="en">Testing Fundamentals</span></a>
+                <span class="new">new!</span>
+              </li>
+              <li>
+                <a href="<?cs var:toroot?>guide/topics/testing/activity_testing.html">
+                <span class="en">Activity Testing</span></a>
+                <span class="new">new!</span>
+              </li>
+              <li>
+                <a href="<?cs var:toroot?>guide/topics/testing/contentprovider_testing.html">
+                <span class="en">Content Provider Testing</span></a>
+                <span class="new">new!</span>
+              </li>
+              <li>
+                <a href="<?cs var:toroot?>guide/topics/testing/service_testing.html">
+                <span class="en">Service Testing</span></a>
+                <span class="new">new!</span>
+              </li>
+              <li>
+                <a href="<?cs var:toroot ?>guide/topics/testing/what_to_test.html">
+                <span class="en">What To Test</span></a>
+                <span class="new">new!</span>
+              </li>
+
+           </ul>
+      </li>
     </ul>
   </li>
 
@@ -336,6 +347,7 @@
                   <span class="en">Testing in Eclipse, with ADT</span>
                 </a>
               </li>
+
               <li>
                 <a href="<?cs var:toroot ?>guide/developing/testing/testing_otheride.html">
                   <span class="en">Testing in Other IDEs</span>
@@ -363,6 +375,34 @@
               <li><a href="<?cs var:toroot ?>guide/developing/tools/layoutopt.html">layoutopt</a></li>
               <li><a href="<?cs var:toroot ?>guide/developing/tools/othertools.html#mksdcard">mksdcard</a></li>
               <li><a href="<?cs var:toroot ?>guide/developing/tools/monkey.html">Monkey</a></li>
+                            <li class="toggle-list">
+                 <div>
+                     <a href="<?cs var:toroot?>guide/developing/tools/monkeyrunner_concepts.html">
+                     <span class="en">monkeyrunner</span>
+                  </a>
+                      <span class="new">new!</span>
+                  </div>
+                  <ul>
+                      <li>
+                          <a href="<?cs var:toroot?>guide/developing/tools/MonkeyDevice.html">
+                                <span class="en">MonkeyDevice</span>
+                        </a>
+                        <span class="new">new!</span>
+                    </li>
+                    <li>
+                        <a href="<?cs var:toroot?>guide/developing/tools/MonkeyImage.html">
+                            <span class="en">MonkeyImage</span>
+                        </a>
+                        <span class="new">new!</span>
+                    </li>
+                    <li>
+                        <a href="<?cs var:toroot?>guide/developing/tools/MonkeyRunner.html">
+                            <span class="en">MonkeyRunner</span>
+                        </a>
+                        <span class="new">new!</span>
+                    </li>
+                  </ul>
+              </li>
               <li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html#sqlite">sqlite3</a></li>
               <li><a href="<?cs var:toroot ?>guide/developing/tools/traceview.html" >Traceview</a></li>
               <li><a href="<?cs var:toroot ?>guide/developing/tools/zipalign.html" >zipalign</a></li>
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index 1d6ab25..d868599 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -129,9 +129,8 @@
 
   <tr>
     <td><code>raw/</code></td>
-    <td><p>Arbitrary files to save in their raw form. Files in here are not compressed by the
-system. To open these resources with a raw {@link java.io.InputStream}, call {@link
-android.content.res.Resources#openRawResource(int)
+    <td><p>Arbitrary files to save in their raw form. To open these resources with a raw
+{@link java.io.InputStream}, call {@link android.content.res.Resources#openRawResource(int)
 Resources.openRawResource()} with the resource ID, which is {@code R.raw.<em>filename</em>}.</p>
       <p>However, if you need access to original file names and file hierarchy, you might consider
 saving some resources in the {@code
diff --git a/docs/html/guide/topics/testing/index.jd b/docs/html/guide/topics/testing/index.jd
index b75656f..762a897 100644
--- a/docs/html/guide/topics/testing/index.jd
+++ b/docs/html/guide/topics/testing/index.jd
@@ -59,6 +59,20 @@
         which guides you through a more complex testing scenario.
     </li>
 </ul>
+<h4>Tools</h4>
+<ul>
+    <li>
+        The
+        <a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>,
+        usually called Monkey, is a command-line tool that sends pseudo-random
+        streams of keystrokes, touches, and gestures to a device.
+    </li>
+    <li>
+     The <a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">monkeyrunner</a> tool
+        is an API and execution environment. You use monkeyrunner with Python programs
+        to test applications and devices.
+    </li>
+</ul>
 <h4>Samples</h4>
 <ul>
     <li>
diff --git a/docs/html/guide/topics/testing/testing_android.jd b/docs/html/guide/topics/testing/testing_android.jd
index 2a4c949..d4b0dcc 100755
--- a/docs/html/guide/topics/testing/testing_android.jd
+++ b/docs/html/guide/topics/testing/testing_android.jd
@@ -38,7 +38,7 @@
         <a href="#TestResults">Seeing Test Results</a>
     </li>
     <li>
-        <a href="#Monkeys">Monkey and MonkeyRunner</a>
+        <a href="#Monkeys">monkey and monkeyrunner</a>
     </li>
     <li>
        <a href="#PackageNames">Working With Package Names</a>
@@ -77,6 +77,13 @@
           <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
           Testing in Other IDEs</a>
         </li>
+        <li>
+          <a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">
+          monkeyrunner</a>
+        </li>
+        <li>
+     <a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>
+        </li>
       </ol>
   </div>
 </div>
@@ -112,10 +119,10 @@
     </li>
     <li>
         The SDK also provides
-        <a href="{@docRoot}guide/topics/testing/monkeyrunner.html">MonkeyRunner</a>, an API for
-        testing devices with Jython scripts, and <a
-        href="{@docRoot}guide/developing/tools/monkey.html">Monkey</a>, a command-line tool for
-        stress-testing UIs by sending pseudo-random events to a device.
+  <a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">monkeyrunner</a>, an API
+        testing devices with Python programs, and <a
+        href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>,
+        a command-line tool for stress-testing UIs by sending pseudo-random events to a device.
     </li>
 </ul>
 <p>
@@ -540,25 +547,28 @@
     <a href="{@docRoot}guide/developing/testing/testing_otheride.html#RunTestsCommand">
     Testing in Other IDEs</a>.
 </p>
-<h2 id="Monkeys">Monkey and MonkeyRunner</h2>
+<h2 id="Monkeys">monkey and monkeyrunner</h2>
 <p>
     The SDK provides two tools for functional-level application testing:
 </p>
     <ul>
         <li>
-            <a href="{@docRoot}guide/developing/tools/monkey.html">Monkey</a> is a command-line
-            tool that sends pseudo-random streams of keystrokes, touches, and gestures to a
-            device. You run it with the <a href="{@docRoot}guide/developing/tools/adb.html">
-            Android Debug Bridge</a> (adb) tool. You use it to stress-test your application and
-            report back errors that are encountered. You can repeat a stream of events by
-            running the tool each time with the same random number seed.
+The <a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>,
+            usually called "monkey", is a command-line tool that sends pseudo-random streams of
+            keystrokes, touches, and gestures to a device. You run it with the
+            <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> (adb) tool.
+            You use it to stress-test your application and report back errors that are encountered.
+            You can repeat a stream of events by running the tool each time with the same random
+            number seed.
         </li>
         <li>
-            <a href="{@docRoot}guide/topics/testing/monkeyrunner.html">MonkeyRunner</a> is a
-            Jython API that you use in test programs written in Python. The API includes functions
-            for connecting to a device, installing and uninstalling packages, taking screenshots,
-            comparing two images, and running a test package against an application. Using the API
-            with Python, you can write a wide range of large, powerful, and complex tests.
+    The <a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">monkeyrunner</a> tool
+            is an API and execution environment for test programs written in Python. The API
+            includes functions for connecting to a device, installing and uninstalling packages,
+            taking screenshots, comparing two images, and running a test package against an
+            application. Using the API, you can write a wide range of large, powerful, and complex
+            tests. You run programs that use the API with the <code>monkeyrunner</code> command-line
+            tool.
         </li>
     </ul>
 <h2 id="PackageNames">Working With Package names</h2>
diff --git a/docs/html/resources/dashboard/platform-versions.jd b/docs/html/resources/dashboard/platform-versions.jd
index 3b4ccb0e..cef057e 100644
--- a/docs/html/resources/dashboard/platform-versions.jd
+++ b/docs/html/resources/dashboard/platform-versions.jd
@@ -52,7 +52,7 @@
 <div class="dashboard-panel">
 
 <img alt="" height="250" width="460"
-src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:9.7,16.4,0.1,40.4,33.4&chl=
+src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:7.9,15.0,0.1,40.8,36.2&chl=
 Android%201.5|Android%201.6|Other*|Android%202.1|Android%202.2&chco=c4df9b,
 6fad0c" />
 
@@ -62,13 +62,13 @@
   <th>API Level</th>
   <th>Distribution</th>
 </tr>
-<tr><td>Android 1.5</td><td>3</td><td>9.7%</td></tr>
-<tr><td>Android 1.6</td><td>4</td><td>16.4%</td></tr>
-<tr><td>Android 2.1</td><td>7</td><td>40.4%</td></tr>
-<tr><td>Android 2.2</td><td>8</td><td>33.4%</td></tr>
+<tr><td>Android 1.5</td><td>3</td><td>7.9%</td></tr>
+<tr><td>Android 1.6</td><td>4</td><td>15.0%</td></tr>
+<tr><td>Android 2.1</td><td>7</td><td>40.8%</td></tr>
+<tr><td>Android 2.2</td><td>8</td><td>36.2%</td></tr>
 </table>
 
-<p><em>Data collected during two weeks ending on October 1, 2010</em></p>
+<p><em>Data collected during two weeks ending on November 1, 2010</em></p>
 <p style="font-size:.9em">* <em>Other: 0.1% of devices running obsolete versions</em></p>
 
 </div><!-- end dashboard-panel -->
@@ -96,19 +96,18 @@
 <div class="dashboard-panel">
 
 <img alt="" height="250" width="660" style="padding:5px;background:#fff"
-src="http://chart.apis.google.com/chart?cht=lc&chs=660x250&chxt=x,y,r&chxr=0,0,12|1,0,100|2,0,100&
-chxl=0:|2010/04/01|04/15|05/01|05/15|06/01|06/15|07/01|07/15|08/01|08/15|09/01|09/15|2010/10/01|1:|0
-%25|25%25|50%25|75%25|100%25|2:|0%25|25%25|50%25|75%25|100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&
-chxtc=0,5&chd=t:99.6,99.6,99.6,99.7,100.6,101.1,99.9,100.0,100.0,99.8,99.9,100.0,100.0|61.5,61.7,62.
-3,63.5,73.0,76.4,78.6,81.1,84.5,86.6,88.0,89.3,90.3|29.4,30.2,32.7,35.3,46.2,51.3,55.1,59.0,64.1,68.
-2,70.4,72.2,73.9|4.0,28.3,32.0,34.9,45.9,51.0,54.9,58.8,64.0,68.1,70.3,72.1,73.8|0.0,0.0,0.0,0.0,0.8
-,1.2,1.8,3.3,4.3,11.3,27.8,32.1,33.4&chm=tAndroid+1.5,7caa36,0,0,15,,t::-5|b,c3df9b,0,1,0|tAndroid+1
-.6,638d23,1,0,15,,t::-5|b,b0db6e,1,2,0|tAndroid+2.0.1,496c13,2,0,15,,t::-5|b,9ddb3d,2,3,0|tAndroid+2
-.1,2f4708,3,1,15,,t:-30:-40|b,89cf19,3,4,0|tAndroid+2.2,131d02,4,9,15,,t::-5|B,6fad0c,4,5,0&chg=7,25
-&chdl=Android+1.5|Android+1.6|Android+2.0.1|Android+2.1|Android+2.2&chco=add274,9ad145,84c323,6ba213
-,507d08" />
+src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,y,r&chxr=0,0,12|1,0,100|2,0,100&
+chxl=0%3A%7C2010/05/01%7C05/15%7C06/01%7C06/15%7C07/01%7C07/15%7C08/01%7C08/15%7C09/01%7C09/15%7C10/
+01%7C10/15%7C2010/11/01%7C1%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C2%3A%7C0%25%7C25%25%7C50%25
+%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:98.9,99.3,100.3,100.8,99.7,99.
+8,99.8,99.7,99.8,99.9,99.9,99.9,99.9|61.6,63.1,72.7,76.1,78.4,80.9,84.3,86.5,87.9,89.2,90.2,91.1,92.
+0|32.0,34.9,45.9,51.0,54.9,58.8,64.0,68.1,70.3,72.1,73.8,75.3,77.0|0.0,0.0,0.8,1.2,1.8,3.3,4.3,11.3,
+27.8,32.1,33.4,34.5,36.2&chm=tAndroid%201.5,7caa36,0,0,15,,t::-5|b,c3df9b,0,1,0|tAndroid%201.6,
+5b831d,1,0,15,,t::-5|b,aadb5e,1,2,0|tAndroid%202.1,38540b,2,0,15,,t::-5|b,91da1e,2,3,0|tAndroid%202.
+2,131d02,3,7,15,,t::-5|B,6fad0c,3,4,0&chg=7,25&chdl=Android%201.5|Android%201.6|Android%202.1|
+Android%202.2&chco=add274,94d134,73ad18,507d08" />
 
-<p><em>Last historical dataset collected during two weeks ending on October 1, 2010</em></p>
+<p><em>Last historical dataset collected during two weeks ending on November 1, 2010</em></p>
 
 
 </div><!-- end dashboard-panel -->
diff --git a/docs/html/resources/faq/framework.jd b/docs/html/resources/faq/framework.jd
index f4b8db0..4a7a3fc 100644
--- a/docs/html/resources/faq/framework.jd
+++ b/docs/html/resources/faq/framework.jd
@@ -68,12 +68,17 @@
 <p>For sharing complex non-persistent user-defined objects for short
 duration, the following approaches are recommended:
 </p>
-  <h4>The android.app.Application class</h4>
-  <p>The android.app.Application is a base class for those who need to
-maintain global application state. It can be accessed via
-getApplication() from any Activity or Service. It has a couple of
-life-cycle methods and will be instantiated by Android automatically if
-your register it in AndroidManifest.xml.</p>
+  <h4>Singleton class</h4>
+  <p>You can take advantage of the fact that your application
+components run in the same process through the use of a singleton.
+This is a class that is designed to have only one instance.  It
+has a static method with a name such as <code>getInstance()</code>
+that returns the instance; the first time this method is called,
+it creates the global instance.  Because all callers get the same
+instance, they can use this as a point of interaction.  For
+example activity A may retrieve the instance and call setValue(3);
+later activity B may retrieve the instance and call getValue() to
+retrieve the last set value.</p>
 
   <h4>A public static field/method</h4>
   <p>An alternate way to make data accessible across Activities/Services is to use <em>public static</em>
@@ -90,18 +95,6 @@
 intent extras. The recipient activity retrieves the object using this
 key.</p>
 
-  <h4>A Singleton class</h4>
-  <p>There are advantages to using a static Singleton, such as you can
-refer to them without casting getApplication() to an
-application-specific class, or going to the trouble of hanging an
-interface on all your Application subclasses so that your various
-modules can refer to that interface instead. </p>
-<p>But, the life cycle of a static is not well under your control; so
-to abide by the life-cycle model, the application class should initiate and
-tear down these static objects in the onCreate() and onTerminate() methods
-of the Application Class</p>
-</p>
-
 <h3>Persistent Objects</h3>
 
 <p>Even while an application appears to continue running, the system
@@ -146,15 +139,11 @@
 <h2>If an Activity starts a remote service, is there any way for the
 Service to pass a message back to the Activity?</h2>
 
-<p>The remote service can define a callback interface and register it with the
-clients to callback into the clients. The 
-{@link android.os.RemoteCallbackList RemoteCallbackList} class provides methods to
-register and unregister clients with the service, and send and receive
-messages.</p>
-
-<p>The sample code for remote service callbacks is given in <a
-href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">ApiDemos/RemoteService</a></p>
-
+<p>See the {@link android.app.Service} documentation's for examples of
+how clients can interact with a service.  You can take advantage of the
+fact that your components run in the same process to greatly simplify
+service interaction from the generic remote case, as shown by the "Local
+Service Sample".  In some cases techniques like singletons may also make sense.
 
 
 <a name="6" id="6"></a>
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index d202b50..7b9a5a2 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -101,7 +101,7 @@
       <span style="display:none" class="ja"></span>
       <span style="display:none" class="zh-CN"></span>
       <span style="display:none" class="zh-TW"></span></a>
-      <span class="new">new!</span></li>
+      </li>
     </ul>
   </li>
   <li>
diff --git a/drm/libdrmframework/plugins/widevine/Android.mk b/drm/libdrmframework/plugins/widevine/Android.mk
new file mode 100644
index 0000000..2c388da
--- /dev/null
+++ b/drm/libdrmframework/plugins/widevine/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libdrmwvmplugin
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/drm/plugins/native
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index a25fad4..289348a 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -51,7 +51,7 @@
      */
     public ColorDrawable(int color) {
         this(null);
-        mState.mBaseColor = mState.mUseColor = color;
+        setColor(color);
     }
 
     private ColorDrawable(ColorState state) {
@@ -72,6 +72,25 @@
     }
 
     /**
+     * Gets the drawable's color value.
+     *
+     * @return int The color to draw.
+     */
+    public int getColor() {
+        return mState.mUseColor;
+    }
+
+    /**
+     * Sets the drawable's color value. This action will clobber the results of prior calls to
+     * {@link #setAlpha(int)} on this object, which side-affected the underlying color.
+     *
+     * @param color The color to draw.
+     */
+    public void setColor(int color) {
+        mState.mBaseColor = mState.mUseColor = color;
+    }
+
+    /**
      * Returns the alpha value of this drawable's color.
      *
      * @return A value between 0 and 255.
@@ -131,7 +150,7 @@
     }
 
     final static class ColorState extends ConstantState {
-        int mBaseColor; // initial color. never changes
+        int mBaseColor; // base color, independent of setAlpha()
         int mUseColor;  // basecolor modulated by setAlpha()
         int mChangingConfigurations;
 
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
index c5765a9..1758cdd 100644
--- a/include/drm/drm_framework_common.h
+++ b/include/drm/drm_framework_common.h
@@ -217,6 +217,10 @@
      * POSIX based Decrypt API set for container based DRM
      */
     static const int CONTAINER_BASED = 0x02;
+    /**
+     * Decrypt API for Widevine streams
+     */
+    static const int WV_BASED = 0x3;
 };
 
 /**
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index b936c4d..58d4c56 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -1408,8 +1408,13 @@
 
 void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
     int32_t eventType = POWER_MANAGER_BUTTON_EVENT;
-    if (eventEntry->type == EventEntry::TYPE_MOTION) {
+    switch (eventEntry->type) {
+    case EventEntry::TYPE_MOTION: {
         const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
+        if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
+            return;
+        }
+
         if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
             switch (motionEntry->action) {
             case AMOTION_EVENT_ACTION_DOWN:
@@ -1427,6 +1432,15 @@
                 break;
             }
         }
+        break;
+    }
+    case EventEntry::TYPE_KEY: {
+        const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
+        if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
+            return;
+        }
+        break;
+    }
     }
 
     CommandEntry* commandEntry = postCommandLocked(
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 381b77a..532a2df 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -83,6 +83,11 @@
     private static final int FIRST_PLAYLIST_FILE_TYPE = FILE_TYPE_M3U;
     private static final int LAST_PLAYLIST_FILE_TYPE = FILE_TYPE_WPL;
 
+    // Drm file types
+    public static final int FILE_TYPE_FL      = 51;
+    private static final int FIRST_DRM_FILE_TYPE = FILE_TYPE_FL;
+    private static final int LAST_DRM_FILE_TYPE = FILE_TYPE_FL;
+
     // Other popular file types
     public static final int FILE_TYPE_TEXT          = 100;
     public static final int FILE_TYPE_HTML          = 101;
@@ -189,6 +194,8 @@
         addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls", MtpConstants.FORMAT_PLS_PLAYLIST);
         addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl", MtpConstants.FORMAT_WPL_PLAYLIST);
 
+        addFileType("FL", FILE_TYPE_FL, "application/x-android-drm-fl");
+
         addFileType("TXT", FILE_TYPE_TEXT, "text/plain", MtpConstants.FORMAT_TEXT);
         addFileType("HTM", FILE_TYPE_HTML, "text/html", MtpConstants.FORMAT_HTML);
         addFileType("HTML", FILE_TYPE_HTML, "text/html", MtpConstants.FORMAT_HTML);
@@ -222,6 +229,11 @@
                 fileType <= LAST_PLAYLIST_FILE_TYPE);
     }
 
+    public static boolean isDrmFileType(int fileType) {
+        return (fileType >= FIRST_DRM_FILE_TYPE &&
+                fileType <= LAST_DRM_FILE_TYPE);
+    }
+
     public static MediaFileType getFileType(String path) {
         int lastDot = path.lastIndexOf(".");
         if (lastDot < 0)
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index e5fa0f8..5aabddf 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -26,6 +26,7 @@
 import android.content.IContentProvider;
 import android.database.Cursor;
 import android.database.SQLException;
+import android.drm.DrmManagerClient;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.os.Process;
@@ -360,6 +361,7 @@
     private ArrayList<FileCacheEntry> mPlayLists;
     private HashMap<String, Uri> mGenreCache;
 
+    private DrmManagerClient mDrmManagerClient = null;
 
     public MediaScanner(Context c) {
         native_setup();
@@ -447,6 +449,11 @@
                 }
             }
 
+            if (System.getProperty("drm.service.enabled").equals("true")
+                    && MediaFile.isDrmFileType(mFileType)) {
+                mFileType = getFileTypeFromDrm(path);
+            }
+
             String key = path;
             if (mCaseInsensitivePaths) {
                 key = path.toLowerCase();
@@ -874,6 +881,27 @@
             }
         }
 
+        private int getFileTypeFromDrm(String path) {
+            if (!System.getProperty("drm.service.enabled").equals("true")) {
+                return 0;
+            }
+
+            int resultFileType = 0;
+
+            if (mDrmManagerClient == null) {
+                mDrmManagerClient = new DrmManagerClient(mContext);
+            }
+
+            if (mDrmManagerClient.canHandle(path, null)) {
+                String drmMimetype = mDrmManagerClient.getOriginalMimeType(path);
+                if (drmMimetype != null) {
+                    mMimeType = drmMimetype;
+                    resultFileType = MediaFile.getFileTypeForMimeType(drmMimetype);
+                }
+            }
+            return resultFileType;
+        }
+
     }; // end of anonymous MediaScannerClient instance
 
     private void prescan(String filePath, boolean prescanFiles) throws RemoteException {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 60a41bf..6954e36 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1298,6 +1298,7 @@
         mVideoTimeUs = timeUs;
     }
 
+    bool wasSeeking = mSeeking;
     finishSeekIfNecessary(timeUs);
 
     TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
@@ -1318,6 +1319,11 @@
 
     int64_t latenessUs = nowUs - timeUs;
 
+    if (wasSeeking) {
+        // Let's display the first frame after seeking right away.
+        latenessUs = 0;
+    }
+
     if (mRTPSession != NULL) {
         // We'll completely ignore timestamps for gtalk videochat
         // and we'll play incoming video as fast as we get it.
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 1629e9f..6c05e03 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -39,7 +39,7 @@
         ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
         ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
         ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
-        ".mkv", ".mka", ".webm", ".ts"
+        ".mkv", ".mka", ".webm", ".ts", ".fl"
     };
     static const size_t kNumValidExtensions =
         sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index aeb8d3c..9dfc9c3 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -248,7 +248,7 @@
 
         AlertDialog.Builder b = new AlertDialog.Builder(mContext);
             b.setCancelable(true);
-            b.setMessage(mContext.getString(R.string.invalid_charger));
+            b.setMessage(R.string.invalid_charger);
             b.setIcon(android.R.drawable.ic_dialog_alert);
             b.setPositiveButton(android.R.string.ok, null);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
index 2f94af6..64ec063 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
@@ -23,22 +23,11 @@
 import android.widget.FrameLayout;
 
 public class LatestItemView extends FrameLayout {
-    private boolean mDispatchTorches;
-
     public LatestItemView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
-    public boolean dispatchTouchEvent(MotionEvent ev) {
-        if (mDispatchTorches) {
-            return super.dispatchTouchEvent(ev);
-        } else {
-            return onTouchEvent(ev);
-        }
-    }
-
     public void setOnClickListener(OnClickListener l) {
-        mDispatchTorches = l == null;
         super.setOnClickListener(l);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index 256386b..00b39c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -65,7 +65,7 @@
         mCommandQueue = new CommandQueue(this, iconList);
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
-        boolean[] switches = new boolean[3];
+        int[] switches = new int[4];
         try {
             mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
                     switches);
@@ -73,9 +73,10 @@
             // If the system process isn't there we're doomed anyway.
         }
 
-        setLightsOn(switches[0]);
-        setMenuKeyVisible(switches[1]);
-        setIMEButtonVisible(switches[2]);
+        disable(switches[0]);
+        setLightsOn(switches[1] != 0);
+        setMenuKeyVisible(switches[2] != 0);
+        setIMEButtonVisible(switches[3] != 0);
 
         // Set up the initial icon state
         int N = iconList.size();
@@ -118,9 +119,10 @@
         if (SPEW) {
             Slog.d(TAG, "Added status bar view: gravity=0x" + Integer.toHexString(lp.gravity) 
                    + " icons=" + iconList.size()
-                   + " lights=" + (switches[0]?"on":"off")
-                   + " menu=" + (switches[1]?"visible":"invisible")
-                   + " imeButton=" + (switches[2]?"visible":"invisible")
+                   + " disabled=0x" + Integer.toHexString(switches[0])
+                   + " lights=" + switches[1]
+                   + " menu=" + switches[2]
+                   + " imeButton=" + switches[3]
                    );
         }
     }
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index 91dc2b2..0f1aa4e 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -145,7 +145,7 @@
                 case KeyEvent.KEYCODE_MEDIA_PLAY:
                 case KeyEvent.KEYCODE_MEDIA_PAUSE:
                 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-                    /* Suppress PLAYPAUSE toggle when phone is ringing or
+                    /* Suppress PLAY/PAUSE toggle when phone is ringing or
                      * in-call to avoid music playback */
                     if (mTelephonyManager == null) {
                         mTelephonyManager = (TelephonyManager) getContext().getSystemService(
@@ -155,11 +155,13 @@
                             mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
                         return true;  // suppress key event
                     }
-                case KeyEvent.KEYCODE_HEADSETHOOK: 
-                case KeyEvent.KEYCODE_MEDIA_STOP: 
-                case KeyEvent.KEYCODE_MEDIA_NEXT: 
-                case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 
-                case KeyEvent.KEYCODE_MEDIA_REWIND: 
+                case KeyEvent.KEYCODE_MUTE:
+                case KeyEvent.KEYCODE_HEADSETHOOK:
+                case KeyEvent.KEYCODE_MEDIA_STOP:
+                case KeyEvent.KEYCODE_MEDIA_NEXT:
+                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+                case KeyEvent.KEYCODE_MEDIA_REWIND:
+                case KeyEvent.KEYCODE_MEDIA_RECORD:
                 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
                     Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
                     intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
@@ -191,12 +193,15 @@
         } else if (event.getAction() == KeyEvent.ACTION_UP) {
             switch (keyCode) {
                 case KeyEvent.KEYCODE_MUTE:
-                case KeyEvent.KEYCODE_HEADSETHOOK: 
-                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 
-                case KeyEvent.KEYCODE_MEDIA_STOP: 
-                case KeyEvent.KEYCODE_MEDIA_NEXT: 
-                case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 
-                case KeyEvent.KEYCODE_MEDIA_REWIND: 
+                case KeyEvent.KEYCODE_HEADSETHOOK:
+                case KeyEvent.KEYCODE_MEDIA_PLAY:
+                case KeyEvent.KEYCODE_MEDIA_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_STOP:
+                case KeyEvent.KEYCODE_MEDIA_NEXT:
+                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+                case KeyEvent.KEYCODE_MEDIA_REWIND:
+                case KeyEvent.KEYCODE_MEDIA_RECORD:
                 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
                     Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
                     intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index c034ec9..c870503 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -795,6 +795,7 @@
             case KeyEvent.KEYCODE_MEDIA_NEXT:
             case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
             case KeyEvent.KEYCODE_MEDIA_REWIND:
+            case KeyEvent.KEYCODE_MEDIA_RECORD:
             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
             case KeyEvent.KEYCODE_CAMERA:
                 return false;
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 1383354..4644a7c 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -209,7 +209,12 @@
                 mSlidingTab.setRightHintText(mSilentMode ? R.string.lockscreen_sound_on_label
                         : R.string.lockscreen_sound_off_label);
             }
-            mCallback.pokeWakelock();
+            // Don't poke the wake lock when returning to a state where the handle is
+            // not grabbed since that can happen when the system (instead of the user)
+            // cancels the grab.
+            if (grabbedState != SlidingTab.OnTriggerListener.NO_HANDLE) {
+                mCallback.pokeWakelock();
+            }
         }
     }
 
@@ -231,10 +236,11 @@
 
         /** {@inheritDoc} */
         public void onGrabbedStateChange(View v, int grabbedState) {
+            // Don't poke the wake lock when returning to a state where the handle is
+            // not grabbed since that can happen when the system (instead of the user)
+            // cancels the grab.
             if (grabbedState == WaveView.OnTriggerListener.CENTER_HANDLE) {
                 mCallback.pokeWakelock(STAY_ON_WHILE_GRABBED_TIMEOUT);
-            } else {
-                mCallback.pokeWakelock();
             }
         }
     }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 3691d97..e944f9d 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -627,13 +627,6 @@
             // should be executed...  do it!
             mPanelChordingKey = 0;
             mPanelMayLongPress = false;
-            InputMethodManager imm = (InputMethodManager)
-                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-            if (imm != null) {
-                mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-                imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
-            }
-            
         }
 
         return false;
@@ -1259,7 +1252,7 @@
             case KeyEvent.KEYCODE_MEDIA_PLAY:
             case KeyEvent.KEYCODE_MEDIA_PAUSE:
             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-                /* Suppress PLAYPAUSE toggle when phone is ringing or in-call
+                /* Suppress PLAY/PAUSE toggle when phone is ringing or in-call
                  * to avoid music playback */
                 if (mTelephonyManager == null) {
                     mTelephonyManager = (TelephonyManager) getContext().getSystemService(
@@ -1275,6 +1268,7 @@
             case KeyEvent.KEYCODE_MEDIA_NEXT:
             case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
             case KeyEvent.KEYCODE_MEDIA_REWIND:
+            case KeyEvent.KEYCODE_MEDIA_RECORD:
             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
                 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
                 intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
@@ -1455,6 +1449,7 @@
             }
 
             case KeyEvent.KEYCODE_HEADSETHOOK:
+            case KeyEvent.KEYCODE_MUTE:
             case KeyEvent.KEYCODE_MEDIA_PLAY:
             case KeyEvent.KEYCODE_MEDIA_PAUSE:
             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
@@ -1462,6 +1457,7 @@
             case KeyEvent.KEYCODE_MEDIA_NEXT:
             case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
             case KeyEvent.KEYCODE_MEDIA_REWIND:
+            case KeyEvent.KEYCODE_MEDIA_RECORD:
             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
                 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
                 intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index cd1ad4c..e950ae5 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -54,6 +54,7 @@
 import com.android.internal.view.BaseInputHandler;
 import com.android.internal.widget.PointerLocationView;
 
+import android.telephony.TelephonyManager;
 import android.util.Config;
 import android.util.EventLog;
 import android.util.Log;
@@ -63,6 +64,7 @@
 import android.view.HapticFeedbackConstants;
 import android.view.IWindowManager;
 import android.view.InputChannel;
+import android.view.InputDevice;
 import android.view.InputQueue;
 import android.view.InputHandler;
 import android.view.KeyEvent;
@@ -84,6 +86,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
@@ -216,7 +219,7 @@
     WindowState mKeyguard = null;
     KeyguardViewMediator mKeyguardMediator;
     GlobalActions mGlobalActions;
-    boolean mShouldTurnOffOnKeyUp;
+    volatile boolean mPowerKeyHandled;
     RecentApplicationsDialog mRecentAppsDialog;
     Handler mHandler;
     
@@ -476,28 +479,47 @@
         }
     }
 
-    Runnable mPowerLongPress = new Runnable() {
+    private void interceptPowerKeyDown(boolean handled) {
+        mPowerKeyHandled = handled;
+        if (!handled) {
+            mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
+        }
+    }
+
+    private boolean interceptPowerKeyUp(boolean canceled) {
+        if (!mPowerKeyHandled) {
+            mHandler.removeCallbacks(mPowerLongPress);
+            return !canceled;
+        } else {
+            mPowerKeyHandled = true;
+            return false;
+        }
+    }
+
+    private final Runnable mPowerLongPress = new Runnable() {
         public void run() {
-            // The context isn't read
-            if (mLongPressOnPowerBehavior < 0) {
-                mLongPressOnPowerBehavior = mContext.getResources().getInteger(
-                        com.android.internal.R.integer.config_longPressOnPowerBehavior);
-            }
-            switch (mLongPressOnPowerBehavior) {
-            case LONG_PRESS_POWER_NOTHING:
-                break;
-            case LONG_PRESS_POWER_GLOBAL_ACTIONS:
-                mShouldTurnOffOnKeyUp = false;
-                performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
-                sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
-                showGlobalActionsDialog();
-                break;
-            case LONG_PRESS_POWER_SHUT_OFF:
-                mShouldTurnOffOnKeyUp = false;
-                performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
-                sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
-                ShutdownThread.shutdown(mContext, true);
-                break;
+            if (!mPowerKeyHandled) {
+                // The context isn't read
+                if (mLongPressOnPowerBehavior < 0) {
+                    mLongPressOnPowerBehavior = mContext.getResources().getInteger(
+                            com.android.internal.R.integer.config_longPressOnPowerBehavior);
+                }
+                switch (mLongPressOnPowerBehavior) {
+                case LONG_PRESS_POWER_NOTHING:
+                    break;
+                case LONG_PRESS_POWER_GLOBAL_ACTIONS:
+                    mPowerKeyHandled = true;
+                    performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+                    sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
+                    showGlobalActionsDialog();
+                    break;
+                case LONG_PRESS_POWER_SHUT_OFF:
+                    mPowerKeyHandled = true;
+                    performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+                    sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
+                    ShutdownThread.shutdown(mContext, true);
+                    break;
+                }
             }
         }
     };
@@ -1110,12 +1132,22 @@
                 com.android.internal.R.anim.lock_screen_behind_enter);
     }
     
-    static ITelephony getPhoneInterface() {
-        return ITelephony.Stub.asInterface(ServiceManager.checkService(Context.TELEPHONY_SERVICE));
+    static ITelephony getTelephonyService() {
+        ITelephony telephonyService = ITelephony.Stub.asInterface(
+                ServiceManager.checkService(Context.TELEPHONY_SERVICE));
+        if (telephonyService == null) {
+            Log.w(TAG, "Unable to find ITelephony interface.");
+        }
+        return telephonyService;
     }
 
-    static IAudioService getAudioInterface() {
-        return IAudioService.Stub.asInterface(ServiceManager.checkService(Context.AUDIO_SERVICE));
+    static IAudioService getAudioService() {
+        IAudioService audioService = IAudioService.Stub.asInterface(
+                ServiceManager.checkService(Context.AUDIO_SERVICE));
+        if (audioService == null) {
+            Log.w(TAG, "Unable to find IAudioService interface.");
+        }
+        return audioService;
     }
 
     boolean keyguardOn() {
@@ -1130,7 +1162,7 @@
     /** {@inheritDoc} */
     @Override
     public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
-            int keyCode, int metaState, int repeatCount, int policyFlags) {
+            int keyCode, int scanCode, int metaState, int repeatCount, int policyFlags) {
         final boolean keyguardOn = keyguardOn();
         final boolean down = (action == KeyEvent.ACTION_DOWN);
         final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0);
@@ -1163,11 +1195,9 @@
                         // and his ONLY options are to answer or reject the call.)
                         boolean incomingRinging = false;
                         try {
-                            ITelephony phoneServ = getPhoneInterface();
-                            if (phoneServ != null) {
-                                incomingRinging = phoneServ.isRinging();
-                            } else {
-                                Log.w(TAG, "Unable to find ITelephony interface");
+                            ITelephony telephonyService = getTelephonyService();
+                            if (telephonyService != null) {
+                                incomingRinging = telephonyService.isRinging();
                             }
                         } catch (RemoteException ex) {
                             Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
@@ -1386,7 +1416,7 @@
         }
     }
 
-    void setAttachedWindowFrames(WindowState win, int fl, int sim,
+    void setAttachedWindowFrames(WindowState win, int fl, int adjust,
             WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
         if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
             // Here's a special case: if this attached window is a panel that is
@@ -1407,7 +1437,7 @@
             // window is positioned within that content.  Otherwise we can use
             // the display frame and let the attached window take care of
             // positioning its content appropriately.
-            if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
+            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
                 cf.set(attached.getDisplayFrameLw());
             } else {
                 // If the window is resizing, then we want to base the content
@@ -1466,6 +1496,8 @@
             attrs.gravity = Gravity.BOTTOM;
             mDockLayer = win.getSurfaceLayer();
         } else {
+            final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
+
             if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
                     == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
                 // This is the case for a normal activity window: we want it
@@ -1481,7 +1513,7 @@
                     pf.top = df.top = mScreenTop;
                     pf.right = df.right = mScreenLeft+mScreenWidth;
                     pf.bottom = df.bottom = mScreenTop+mScreenHeight;
-                    if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
+                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
                         cf.left = mDockLeft;
                         cf.top = mDockTop;
                         cf.right = mDockRight;
@@ -1492,10 +1524,14 @@
                         cf.right = mContentRight;
                         cf.bottom = mContentBottom;
                     }
-                    vf.left = mCurLeft;
-                    vf.top = mCurTop;
-                    vf.right = mCurRight;
-                    vf.bottom = mCurBottom;
+                    if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
+                        vf.left = mCurLeft;
+                        vf.top = mCurTop;
+                        vf.right = mCurRight;
+                        vf.bottom = mCurBottom;
+                    } else {
+                        vf.set(cf);
+                    }
                 }
             } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
                 // A window that has requested to fill the entire screen just
@@ -1504,14 +1540,18 @@
                 pf.top = df.top = cf.top = mScreenTop;
                 pf.right = df.right = cf.right = mScreenLeft+mScreenWidth;
                 pf.bottom = df.bottom = cf.bottom = mScreenTop+mScreenHeight;
-                vf.left = mCurLeft;
-                vf.top = mCurTop;
-                vf.right = mCurRight;
-                vf.bottom = mCurBottom;
+                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
+                    vf.left = mCurLeft;
+                    vf.top = mCurTop;
+                    vf.right = mCurRight;
+                    vf.bottom = mCurBottom;
+                } else {
+                    vf.set(cf);
+                }
             } else if (attached != null) {
                 // A child window should be placed inside of the same visible
                 // frame that its parent had.
-                setAttachedWindowFrames(win, fl, sim, attached, false, pf, df, cf, vf);
+                setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf);
             } else {
                 // Otherwise, a normal window must be placed inside the content
                 // of all screen decorations.
@@ -1519,7 +1559,7 @@
                 pf.top = mContentTop;
                 pf.right = mContentRight;
                 pf.bottom = mContentBottom;
-                if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
+                if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
                     df.left = cf.left = mDockLeft;
                     df.top = cf.top = mDockTop;
                     df.right = cf.right = mDockRight;
@@ -1530,10 +1570,14 @@
                     df.right = cf.right = mContentRight;
                     df.bottom = cf.bottom = mContentBottom;
                 }
-                vf.left = mCurLeft;
-                vf.top = mCurTop;
-                vf.right = mCurRight;
-                vf.bottom = mCurBottom;
+                if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
+                    vf.left = mCurLeft;
+                    vf.top = mCurTop;
+                    vf.right = mCurRight;
+                    vf.bottom = mCurBottom;
+                } else {
+                    vf.set(cf);
+                }
             }
         }
         
@@ -1809,23 +1853,6 @@
     }
 
     /**
-     * @return Whether a telephone call is in progress right now.
-     */
-    boolean isInCall() {
-        final ITelephony phone = getPhoneInterface();
-        if (phone == null) {
-            Log.w(TAG, "couldn't get ITelephony reference");
-            return false;
-        }
-        try {
-            return phone.isOffhook();
-        } catch (RemoteException e) {
-            Log.w(TAG, "ITelephony.isOffhhook threw RemoteException " + e);
-            return false;
-        }
-    }
-
-    /**
      * @return Whether music is being played right now.
      */
     boolean isMusicActive() {
@@ -1842,9 +1869,8 @@
      * @param keycode
      */
     void handleVolumeKey(int stream, int keycode) {
-        final IAudioService audio = getAudioInterface();
-        if (audio == null) {
-            Log.w(TAG, "handleVolumeKey: couldn't get IAudioService reference");
+        IAudioService audioService = getAudioService();
+        if (audioService == null) {
             return;
         }
         try {
@@ -1852,7 +1878,7 @@
             // during the call, but we do it as a precaution for the rare possibility
             // that the music stops right before we call this
             mBroadcastWakeLock.acquire();
-            audio.adjustStreamVolume(stream,
+            audioService.adjustStreamVolume(stream,
                 keycode == KeyEvent.KEYCODE_VOLUME_UP
                             ? AudioManager.ADJUST_RAISE
                             : AudioManager.ADJUST_LOWER,
@@ -1863,41 +1889,15 @@
             mBroadcastWakeLock.release();
         }
     }
-    
-    static boolean isMediaKey(int code) {
-        if (code == KeyEvent.KEYCODE_HEADSETHOOK || 
-                code == KeyEvent.KEYCODE_MEDIA_PLAY ||
-                code == KeyEvent.KEYCODE_MEDIA_PAUSE ||
-                code == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
-                code == KeyEvent.KEYCODE_MEDIA_STOP || 
-                code == KeyEvent.KEYCODE_MEDIA_NEXT ||
-                code == KeyEvent.KEYCODE_MEDIA_PREVIOUS || 
-                code == KeyEvent.KEYCODE_MEDIA_REWIND ||
-                code == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
-            return true;
-        }
-        return false;    
-    }
- 
+
     /** {@inheritDoc} */
     @Override
-    public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
-            int policyFlags, boolean isScreenOn) {
-        int result = ACTION_PASS_TO_USER;
+    public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags,
+            int keyCode, int scanCode, int policyFlags, boolean isScreenOn) {
+        final boolean down = action == KeyEvent.ACTION_DOWN;
+        final boolean canceled = (flags & KeyEvent.FLAG_CANCELED) != 0;
 
-        if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) {
-            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
-        }
-
-        final boolean isWakeKey = (policyFlags
-                & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
-
-        // If the key is injected, pretend that the screen is on and don't let the
-        // device go to sleep.  This feature is mainly used for testing purposes.
         final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
-        if (isInjected) {
-            isScreenOn = true;
-        }
 
         // If screen is off then we treat the case where the keyguard is open but hidden
         // the same as if it were open and in front.
@@ -1912,202 +1912,210 @@
                   + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive);
         }
 
-        if (keyguardActive) {
-            if (isScreenOn) {
-                // when the screen is on, always give the event to the keyguard
-                result |= ACTION_PASS_TO_USER;
-            } else {
-                // otherwise, don't pass it to the user
-                result &= ~ACTION_PASS_TO_USER;
+        if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) {
+            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
+        }
 
-                if (isWakeKey && down) {
+        // Basic policy based on screen state and keyguard.
+        // FIXME: This policy isn't quite correct.  We shouldn't care whether the screen
+        //        is on or off, really.  We should care about whether the device is in an
+        //        interactive state or is in suspend pretending to be "off".
+        //        The primary screen might be turned off due to proximity sensor or
+        //        because we are presenting media on an auxiliary screen or remotely controlling
+        //        the device some other way (which is why we have an exemption here for injected
+        //        events).
+        int result;
+        if (isScreenOn || isInjected) {
+            // When the screen is on or if the key is injected pass the key to the application.
+            result = ACTION_PASS_TO_USER;
+        } else {
+            // When the screen is off and the key is not injected, determine whether
+            // to wake the device but don't pass the key to the application.
+            result = 0;
 
-                    // tell the mediator about a wake key, it may decide to
-                    // turn on the screen depending on whether the key is
-                    // appropriate.
-                    if (!mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode)
-                            && (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
-                                || keyCode == KeyEvent.KEYCODE_VOLUME_UP)) {
-                        // when keyguard is showing and screen off, we need
-                        // to handle the volume key for calls and  music here
-                        if (isInCall()) {
-                            handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
-                        } else if (isMusicActive()) {
-                            handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode);
-                        }
-                    }
+            final boolean isWakeKey = (policyFlags
+                    & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
+            if (down && isWakeKey) {
+                if (keyguardActive) {
+                    // If the keyguard is showing, let it decide what to do with the wake key.
+                    mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode);
+                } else {
+                    // Otherwise, wake the device ourselves.
+                    result |= ACTION_POKE_USER_ACTIVITY;
                 }
             }
-        } else if (!isScreenOn) {
-            // If we are in-call with screen off and keyguard is not showing,
-            // then handle the volume key ourselves.
-            // This is necessary because the phone app will disable the keyguard
-            // when the proximity sensor is in use.
-            if (isInCall() &&
-                     (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
-                                || keyCode == KeyEvent.KEYCODE_VOLUME_UP)) {
-                result &= ~ACTION_PASS_TO_USER;
-                handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
-            }
-            if (isWakeKey) {
-                // a wake key has a sole purpose of waking the device; don't pass
-                // it to the user
-                result |= ACTION_POKE_USER_ACTIVITY;
-                result &= ~ACTION_PASS_TO_USER;
-            }
         }
 
-        if (keyCode == KeyEvent.KEYCODE_ENDCALL
-                || keyCode == KeyEvent.KEYCODE_POWER) {
-            if (down) {
-                boolean handled = false;
-                boolean hungUp = false;
-                // key repeats are generated by the window manager, and we don't see them
-                // here, so unless the driver is doing something it shouldn't be, we know
-                // this is the real press event.
-                ITelephony phoneServ = getPhoneInterface();
-                if (phoneServ != null) {
-                    try {
-                        if (keyCode == KeyEvent.KEYCODE_ENDCALL) {
-                            handled = hungUp = phoneServ.endCall();
-                        } else if (keyCode == KeyEvent.KEYCODE_POWER) {
-                            if (phoneServ.isRinging()) {
-                                // Pressing Power while there's a ringing incoming
-                                // call should silence the ringer.
-                                phoneServ.silenceRinger();
-                                handled = true;
-                            } else if (phoneServ.isOffhook() &&
-                                       ((mIncallPowerBehavior
-                                         & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP)
-                                        != 0)) {
-                                // Otherwise, if "Power button ends call" is enabled,
-                                // the Power button will hang up any current active call.
-                                handled = hungUp = phoneServ.endCall();
+        // Handle special keys.
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+            case KeyEvent.KEYCODE_VOLUME_UP: {
+                if (down) {
+                    ITelephony telephonyService = getTelephonyService();
+                    if (telephonyService != null) {
+                        try {
+                            if (telephonyService.isRinging()) {
+                                // If an incoming call is ringing, either VOLUME key means
+                                // "silence ringer".  We handle these keys here, rather than
+                                // in the InCallScreen, to make sure we'll respond to them
+                                // even if the InCallScreen hasn't come to the foreground yet.
+                                // Look for the DOWN event here, to agree with the "fallback"
+                                // behavior in the InCallScreen.
+                                Log.i(TAG, "interceptKeyBeforeQueueing:"
+                                      + " VOLUME key-down while ringing: Silence ringer!");
+
+                                // Silence the ringer.  (It's safe to call this
+                                // even if the ringer has already been silenced.)
+                                telephonyService.silenceRinger();
+
+                                // And *don't* pass this key thru to the current activity
+                                // (which is probably the InCallScreen.)
+                                result &= ~ACTION_PASS_TO_USER;
+                                break;
+                            }
+                            if (telephonyService.isOffhook()
+                                    && (result & ACTION_PASS_TO_USER) == 0) {
+                                // If we are in call but we decided not to pass the key to
+                                // the application, handle the volume change here.
+                                handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
+                                break;
+                            }
+                        } catch (RemoteException ex) {
+                            Log.w(TAG, "ITelephony threw RemoteException", ex);
+                        }
+                    }
+
+                    if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) {
+                        // If music is playing but we decided not to pass the key to the
+                        // application, handle the volume change here.
+                        handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode);
+                        break;
+                    }
+                }
+                break;
+            }
+
+            case KeyEvent.KEYCODE_ENDCALL: {
+                result &= ~ACTION_PASS_TO_USER;
+                if (down) {
+                    ITelephony telephonyService = getTelephonyService();
+                    boolean hungUp = false;
+                    if (telephonyService != null) {
+                        try {
+                            hungUp = telephonyService.endCall();
+                        } catch (RemoteException ex) {
+                            Log.w(TAG, "ITelephony threw RemoteException", ex);
+                        }
+                    }
+                    interceptPowerKeyDown(!isScreenOn || hungUp);
+                } else {
+                    if (interceptPowerKeyUp(canceled)) {
+                        if ((mEndcallBehavior
+                                & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
+                            if (goHome()) {
+                                break;
                             }
                         }
-                    } catch (RemoteException ex) {
-                        Log.w(TAG, "ITelephony threw RemoteException" + ex);
+                        if ((mEndcallBehavior
+                                & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
+                            result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
+                        }
                     }
+                }
+                break;
+            }
+
+            case KeyEvent.KEYCODE_POWER: {
+                result &= ~ACTION_PASS_TO_USER;
+                if (down) {
+                    ITelephony telephonyService = getTelephonyService();
+                    boolean hungUp = false;
+                    if (telephonyService != null) {
+                        try {
+                            if (telephonyService.isRinging()) {
+                                // Pressing Power while there's a ringing incoming
+                                // call should silence the ringer.
+                                telephonyService.silenceRinger();
+                            } else if ((mIncallPowerBehavior
+                                    & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
+                                    && telephonyService.isOffhook()) {
+                                // Otherwise, if "Power button ends call" is enabled,
+                                // the Power button will hang up any current active call.
+                                hungUp = telephonyService.endCall();
+                            }
+                        } catch (RemoteException ex) {
+                            Log.w(TAG, "ITelephony threw RemoteException", ex);
+                        }
+                    }
+                    interceptPowerKeyDown(!isScreenOn || hungUp);
                 } else {
-                    Log.w(TAG, "!!! Unable to find ITelephony interface !!!");
-                }
-
-                if (!isScreenOn
-                        || (handled && keyCode != KeyEvent.KEYCODE_POWER)
-                        || (handled && hungUp && keyCode == KeyEvent.KEYCODE_POWER)) {
-                    mShouldTurnOffOnKeyUp = false;
-                } else {
-                    // Only try to turn off the screen if we didn't already hang up.
-                    mShouldTurnOffOnKeyUp = true;
-                    mHandler.postDelayed(mPowerLongPress,
-                            ViewConfiguration.getGlobalActionKeyTimeout());
-                    result &= ~ACTION_PASS_TO_USER;
-                }
-            } else {
-                mHandler.removeCallbacks(mPowerLongPress);
-                if (mShouldTurnOffOnKeyUp) {
-                    mShouldTurnOffOnKeyUp = false;
-                    boolean gohome, sleeps;
-                    if (keyCode == KeyEvent.KEYCODE_ENDCALL) {
-                        gohome = (mEndcallBehavior
-                                  & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0;
-                        sleeps = (mEndcallBehavior
-                                  & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0;
-                    } else {
-                        gohome = false;
-                        sleeps = true;
+                    if (interceptPowerKeyUp(canceled)) {
+                        result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
                     }
-                    if (keyguardActive
-                            || (sleeps && !gohome)
-                            || (gohome && !goHome() && sleeps)) {
-                        // They must already be on the keyguard or home screen,
-                        // go to sleep instead unless the event was injected.
-                        if (!isInjected) {
-                            Log.d(TAG, "I'm tired mEndcallBehavior=0x"
-                                    + Integer.toHexString(mEndcallBehavior));
-                            result &= ~ACTION_POKE_USER_ACTIVITY;
-                            result |= ACTION_GO_TO_SLEEP;
+                }
+                break;
+            }
+
+            case KeyEvent.KEYCODE_MEDIA_PLAY:
+            case KeyEvent.KEYCODE_MEDIA_PAUSE:
+            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                if (down) {
+                    ITelephony telephonyService = getTelephonyService();
+                    if (telephonyService != null) {
+                        try {
+                            if (!telephonyService.isIdle()) {
+                                // Suppress PLAY/PAUSE toggle when phone is ringing or in-call
+                                // to avoid music playback.
+                                break;
+                            }
+                        } catch (RemoteException ex) {
+                            Log.w(TAG, "ITelephony threw RemoteException", ex);
                         }
                     }
-                    result &= ~ACTION_PASS_TO_USER;
                 }
+            case KeyEvent.KEYCODE_HEADSETHOOK:
+            case KeyEvent.KEYCODE_MUTE:
+            case KeyEvent.KEYCODE_MEDIA_STOP:
+            case KeyEvent.KEYCODE_MEDIA_NEXT:
+            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+            case KeyEvent.KEYCODE_MEDIA_REWIND:
+            case KeyEvent.KEYCODE_MEDIA_RECORD:
+            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
+                if ((result & ACTION_PASS_TO_USER) == 0) {
+                    // Only do this if we would otherwise not pass it to the user. In that
+                    // case, the PhoneWindow class will do the same thing, except it will
+                    // only do it if the showing app doesn't process the key on its own.
+                    long when = whenNanos / 1000000;
+                    KeyEvent keyEvent = new KeyEvent(when, when, action, keyCode, 0, 0,
+                            0, scanCode, flags, InputDevice.SOURCE_KEYBOARD);
+                    mBroadcastWakeLock.acquire();
+                    mHandler.post(new PassHeadsetKey(keyEvent));
+                }
+                break;
             }
-        } else if (isMediaKey(keyCode)) {
-            // This key needs to be handled even if the screen is off.
-            // If others need to be handled while it's off, this is a reasonable
-            // pattern to follow.
-            if ((result & ACTION_PASS_TO_USER) == 0) {
-                // Only do this if we would otherwise not pass it to the user. In that
-                // case, the PhoneWindow class will do the same thing, except it will
-                // only do it if the showing app doesn't process the key on its own.
-                long when = whenNanos / 1000000;
-                KeyEvent keyEvent = new KeyEvent(when, when,
-                        down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP,
-                        keyCode, 0);
-                mBroadcastWakeLock.acquire();
-                mHandler.post(new PassHeadsetKey(keyEvent));
-            }
-        } else if (keyCode == KeyEvent.KEYCODE_CALL) {
-            // If an incoming call is ringing, answer it!
-            // (We handle this key here, rather than in the InCallScreen, to make
-            // sure we'll respond to the key even if the InCallScreen hasn't come to
-            // the foreground yet.)
 
-            // We answer the call on the DOWN event, to agree with
-            // the "fallback" behavior in the InCallScreen.
-            if (down) {
-                try {
-                    ITelephony phoneServ = getPhoneInterface();
-                    if (phoneServ != null) {
-                        if (phoneServ.isRinging()) {
-                            Log.i(TAG, "interceptKeyTq:"
-                                  + " CALL key-down while ringing: Answer the call!");
-                            phoneServ.answerRingingCall();
+            case KeyEvent.KEYCODE_CALL: {
+                if (down) {
+                    ITelephony telephonyService = getTelephonyService();
+                    if (telephonyService != null) {
+                        try {
+                            if (telephonyService.isRinging()) {
+                                Log.i(TAG, "interceptKeyBeforeQueueing:"
+                                      + " CALL key-down while ringing: Answer the call!");
+                                telephonyService.answerRingingCall();
 
-                            // And *don't* pass this key thru to the current activity
-                            // (which is presumably the InCallScreen.)
-                            result &= ~ACTION_PASS_TO_USER;
+                                // And *don't* pass this key thru to the current activity
+                                // (which is presumably the InCallScreen.)
+                                result &= ~ACTION_PASS_TO_USER;
+                            }
+                        } catch (RemoteException ex) {
+                            Log.w(TAG, "ITelephony threw RemoteException", ex);
                         }
-                    } else {
-                        Log.w(TAG, "CALL button: Unable to find ITelephony interface");
                     }
-                } catch (RemoteException ex) {
-                    Log.w(TAG, "CALL button: RemoteException from getPhoneInterface()", ex);
                 }
-            }
-        } else if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP)
-                   || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
-            // If an incoming call is ringing, either VOLUME key means
-            // "silence ringer".  We handle these keys here, rather than
-            // in the InCallScreen, to make sure we'll respond to them
-            // even if the InCallScreen hasn't come to the foreground yet.
-
-            // Look for the DOWN event here, to agree with the "fallback"
-            // behavior in the InCallScreen.
-            if (down) {
-                try {
-                    ITelephony phoneServ = getPhoneInterface();
-                    if (phoneServ != null) {
-                        if (phoneServ.isRinging()) {
-                            Log.i(TAG, "interceptKeyTq:"
-                                  + " VOLUME key-down while ringing: Silence ringer!");
-                            // Silence the ringer.  (It's safe to call this
-                            // even if the ringer has already been silenced.)
-                            phoneServ.silenceRinger();
-
-                            // And *don't* pass this key thru to the current activity
-                            // (which is probably the InCallScreen.)
-                            result &= ~ACTION_PASS_TO_USER;
-                        }
-                    } else {
-                        Log.w(TAG, "VOLUME button: Unable to find ITelephony interface");
-                    }
-                } catch (RemoteException ex) {
-                    Log.w(TAG, "VOLUME button: RemoteException from getPhoneInterface()", ex);
-                }
+                break;
             }
         }
-
         return result;
     }
 
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index cb4071a..e7eb129 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -404,17 +404,18 @@
         }
         
         @SuppressWarnings("unused")
-        public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
-                int policyFlags, boolean isScreenOn) {
+        public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags,
+                int keyCode, int scanCode, int policyFlags, boolean isScreenOn) {
             return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(
-                    whenNanos, keyCode, down, policyFlags, isScreenOn);
+                    whenNanos, action, flags, keyCode, scanCode, policyFlags, isScreenOn);
         }
         
         @SuppressWarnings("unused")
         public boolean interceptKeyBeforeDispatching(InputChannel focus, int action,
-                int flags, int keyCode, int metaState, int repeatCount, int policyFlags) {
+                int flags, int keyCode, int scanCode, int metaState, int repeatCount,
+                int policyFlags) {
             return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(focus,
-                    action, flags, keyCode, metaState, repeatCount, policyFlags);
+                    action, flags, keyCode, scanCode, metaState, repeatCount, policyFlags);
         }
         
         @SuppressWarnings("unused")
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 95d2b65..0eeef38 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -71,9 +71,7 @@
     Object mLock = new Object();
     // We usually call it lights out mode, but double negatives are annoying
     boolean mLightsOn = true;
-
     boolean mMenuVisible = false;
-
     boolean mIMEButtonVisible = false;
 
     private class DisableRecord implements IBinder.DeathRecipient {
@@ -352,7 +350,7 @@
     // ================================================================================
     public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,
             List<IBinder> notificationKeys, List<StatusBarNotification> notifications,
-            boolean switches[]) {
+            int switches[]) {
         enforceStatusBarService();
 
         Slog.i(TAG, "registerStatusBar bar=" + bar);
@@ -367,9 +365,10 @@
             }
         }
         synchronized (mLock) {
-            switches[0] = mLightsOn;
-            switches[1] = mMenuVisible;
-            switches[2] = mIMEButtonVisible;
+            switches[0] = gatherDisableActionsLocked();
+            switches[1] = mLightsOn ? 1 : 0;
+            switches[2] = mMenuVisible ? 1 : 0;
+            switches[3] = mIMEButtonVisible ? 1 : 0;
         }
     }
 
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 747af26..a7a0c68 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -103,6 +103,8 @@
 
     private int mDataConnectionNetworkType;
 
+    private int mOtaspMode;
+
     static final int PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
                 PhoneStateListener.LISTEN_CALL_STATE |
@@ -225,6 +227,13 @@
                             remove(r.binder);
                         }
                     }
+                    if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
+                        try {
+                            r.callback.onOtaspChanged(mOtaspMode);
+                        } catch (RemoteException ex) {
+                            remove(r.binder);
+                        }
+                    }
                 }
             }
         } else {
@@ -467,6 +476,25 @@
         }
     }
 
+    public void notifyOtaspChanged(int otaspMode) {
+        if (!checkNotifyPermission("notifyOtaspChanged()" )) {
+            return;
+        }
+        synchronized (mRecords) {
+            mOtaspMode = otaspMode;
+            for (Record r : mRecords) {
+                if ((r.events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
+                    try {
+                        r.callback.onOtaspChanged(otaspMode);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index c29e4a9..55ebded 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -5706,20 +5706,20 @@
         
         /* Provides an opportunity for the window manager policy to intercept early key
          * processing as soon as the key has been read from the device. */
-        public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
-                int policyFlags, boolean isScreenOn) {
-            return mPolicy.interceptKeyBeforeQueueing(whenNanos,
-                    keyCode, down, policyFlags, isScreenOn);
+        public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags,
+                int keyCode, int scanCode, int policyFlags, boolean isScreenOn) {
+            return mPolicy.interceptKeyBeforeQueueing(whenNanos, action, flags,
+                    keyCode, scanCode, policyFlags, isScreenOn);
         }
         
         /* Provides an opportunity for the window manager policy to process a key before
          * ordinary dispatch. */
         public boolean interceptKeyBeforeDispatching(InputChannel focus,
-                int action, int flags, int keyCode, int metaState, int repeatCount,
+                int action, int flags, int keyCode, int scanCode, int metaState, int repeatCount,
                 int policyFlags) {
             WindowState windowState = getWindowStateForInputChannel(focus);
             return mPolicy.interceptKeyBeforeDispatching(windowState, action, flags,
-                    keyCode, metaState, repeatCount, policyFlags);
+                    keyCode, scanCode, metaState, repeatCount, policyFlags);
         }
         
         /* Called when the current input focus changes.
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 599163b..d4c4ba4 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -857,7 +857,7 @@
         JNIEnv* env = jniEnv();
         jint wmActions = env->CallIntMethod(mCallbacksObj,
                 gCallbacksClassInfo.interceptKeyBeforeQueueing,
-                when, keyCode, action == AKEY_EVENT_ACTION_DOWN, policyFlags, isScreenOn);
+                when, action, flags, keyCode, scanCode, policyFlags, isScreenOn);
         if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
             wmActions = 0;
         }
@@ -926,7 +926,7 @@
         jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
                 gCallbacksClassInfo.interceptKeyBeforeDispatching,
                 inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(),
-                keyEvent->getKeyCode(), keyEvent->getMetaState(),
+                keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
                 keyEvent->getRepeatCount(), policyFlags);
         bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
 
@@ -1358,10 +1358,10 @@
             "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J");
 
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
-            "interceptKeyBeforeQueueing", "(JIZIZ)I");
+            "interceptKeyBeforeQueueing", "(JIIIIIZ)I");
 
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
-            "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z");
+            "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIIII)Z");
 
     GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
             "checkInjectEventsPermission", "(II)Z");
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 38f44d8..eda9b71 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -148,6 +148,14 @@
      */
     public static final int LISTEN_SIGNAL_STRENGTHS                         = 0x00000100;
 
+    /**
+     * Listen for changes to OTASP mode.
+     *
+     * @see #onOtaspChanged
+     * @hide
+     */
+    public static final int LISTEN_OTASP_CHANGED                            = 0x00000200;
+
     public PhoneStateListener() {
     }
 
@@ -252,6 +260,21 @@
         // default implementation empty
     }
 
+
+    /**
+     * The Over The Air Service Provisioning (OTASP) has changed. Requires
+     * the READ_PHONE_STATE permission.
+     * @param otaspMode is integer <code>OTASP_UNKNOWN=1<code>
+     *   means the value is currently unknown and the system should wait until
+     *   <code>OTASP_NEEDED=2<code> or <code>OTASP_NOT_NEEDED=3<code> is received before
+     *   making the decisision to perform OTASP or not.
+     *
+     * @hide
+     */
+    public void onOtaspChanged(int otaspMode) {
+        // default implementation empty
+    }
+
     /**
      * The callback methods need to be called on the handler thread where
      * this object was created.  If the binder did that for us it'd be nice.
@@ -292,9 +315,14 @@
         public void onDataActivity(int direction) {
             Message.obtain(mHandler, LISTEN_DATA_ACTIVITY, direction, 0, null).sendToTarget();
         }
+
         public void onSignalStrengthsChanged(SignalStrength signalStrength) {
             Message.obtain(mHandler, LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength).sendToTarget();
         }
+
+        public void onOtaspChanged(int otaspMode) {
+            Message.obtain(mHandler, LISTEN_OTASP_CHANGED, otaspMode, 0).sendToTarget();
+        }
     };
 
     Handler mHandler = new Handler() {
@@ -329,6 +357,9 @@
                 case LISTEN_SIGNAL_STRENGTHS:
                     PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj);
                     break;
+                case LISTEN_OTASP_CHANGED:
+                    PhoneStateListener.this.onOtaspChanged(msg.arg1);
+                    break;
             }
         }
     };
diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 6a163dd..14808b6 100644
--- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -148,6 +148,14 @@
         }
     }
 
+    public void notifyOtaspChanged(Phone sender, int otaspMode) {
+        try {
+            mRegistry.notifyOtaspChanged(otaspMode);
+        } catch (RemoteException ex) {
+            // system process is dead
+        }
+    }
+
     private void log(String s) {
         Log.d(LOG_TAG, "[PhoneNotifier] " + s);
     }
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 856d663..082c097 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -32,5 +32,6 @@
     void onDataConnectionStateChanged(int state, int networkType);
     void onDataActivity(int direction);
     void onSignalStrengthsChanged(in SignalStrength signalStrength);
+    void onOtaspChanged(in int otaspMode);
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 7a1587b..3c4bb12 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -66,7 +66,7 @@
     boolean showCallScreenWithDialpad(boolean showDialpad);
 
     /**
-     * End call or go to the Home screen
+     * End call if there is a call in progress, otherwise does nothing.
      *
      * @return whether it hung up
      */
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 6407a4e..3c83e50 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -38,4 +38,5 @@
             in LinkCapabilities linkCapabilities, int networkType);
     void notifyDataConnectionFailed(String reason, String apnType);
     void notifyCellLocation(in Bundle cellLocation);
+    void notifyOtaspChanged(in int otaspMode);
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 74e8c1b..554a7ba 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -750,6 +750,10 @@
         mNotifier.notifyDataConnection(this, reason, apnType);
     }
 
+    public void notifyOtaspChanged(int otaspMode) {
+        mNotifier.notifyOtaspChanged(this, otaspMode);
+    }
+
     public abstract String getPhoneName();
 
     public abstract int getPhoneType();
diff --git a/telephony/java/com/android/internal/telephony/PhoneNotifier.java b/telephony/java/com/android/internal/telephony/PhoneNotifier.java
index 691271f..b1cf953 100644
--- a/telephony/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/telephony/java/com/android/internal/telephony/PhoneNotifier.java
@@ -42,4 +42,5 @@
 
     public void notifyDataActivity(Phone sender);
 
+    public void notifyOtaspChanged(Phone sender, int otaspMode);
 }
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
index e8bbe5e..3f9ffc3 100644
--- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -53,6 +53,12 @@
 
     public SignalStrength mSignalStrength;
 
+    /* The otaspMode passed to PhoneStateListener#onOtaspChanged */
+    static public final int OTASP_UNINITIALIZED = 0;
+    static public final int OTASP_UNKNOWN = 1;
+    static public final int OTASP_NEEDED = 2;
+    static public final int OTASP_NOT_NEEDED = 3;
+
     /**
      * A unique identifier to track requests associated with a poll
      * and ignore stale responses.  The value is a count-down of
@@ -268,9 +274,11 @@
 
     public abstract void handleMessage(Message msg);
 
+    protected abstract Phone getPhone();
     protected abstract void handlePollStateResult(int what, AsyncResult ar);
     protected abstract void updateSpnDisplay();
     protected abstract void setPowerStateToDesired();
+    protected abstract void log(String s);
 
     /**
      * Clean up existing voice and data connection then turn off radio power.
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 6e53ec5..b9d5673 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -61,6 +61,7 @@
 import com.android.internal.telephony.PhoneNotifier;
 import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.PhoneSubInfo;
+import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.UUSInfo;
@@ -83,10 +84,6 @@
     static final String LOG_TAG = "CDMA";
     private static final boolean DBG = true;
 
-    // Min values used to by needsActivation
-    private static final String UNACTIVATED_MIN2_VALUE = "000000";
-    private static final String UNACTIVATED_MIN_VALUE = "1111110111";
-
     // Default Emergency Callback Mode exit timer
     private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
 
@@ -1170,19 +1167,7 @@
      */
     @Override
     public boolean needsOtaServiceProvisioning() {
-        String cdmaMin = getCdmaMin();
-        boolean needsProvisioning;
-        if (cdmaMin == null || (cdmaMin.length() < 6)) {
-            if (DBG) Log.d(LOG_TAG, "needsOtaServiceProvisioning: illegal cdmaMin='"
-                                    + cdmaMin + "' assume provisioning needed.");
-            needsProvisioning = true;
-        } else {
-            needsProvisioning = (cdmaMin.equals(UNACTIVATED_MIN_VALUE)
-                    || cdmaMin.substring(0,6).equals(UNACTIVATED_MIN2_VALUE))
-                    || SystemProperties.getBoolean("test_cdma_setup", false);
-        }
-        if (DBG) Log.d(LOG_TAG, "needsOtaServiceProvisioning: ret=" + needsProvisioning);
-        return needsProvisioning;
+        return mSST.getOtasp() != ServiceStateTracker.OTASP_NOT_NEEDED;
     }
 
     private static final String IS683A_FEATURE_CODE = "*228";
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
index 3669e60..325c2e1 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
@@ -354,6 +354,24 @@
                     || (foregroundCall.getState() == CdmaCall.State.ACTIVE)
                     || !backgroundCall.getState().isAlive());
 
+        if (!ret) {
+            log(String.format("canDial is false\n" +
+                              "((serviceState=%d) != ServiceState.STATE_POWER_OFF)::=%s\n" +
+                              "&& pendingMO == null::=%s\n" +
+                              "&& !ringingCall.isRinging()::=%s\n" +
+                              "&& !disableCall.equals(\"true\")::=%s\n" +
+                              "&& (!foregroundCall.getState().isAlive()::=%s\n" +
+                              "   || foregroundCall.getState() == CdmaCall.State.ACTIVE::=%s\n" +
+                              "   ||!backgroundCall.getState().isAlive())::=%s)",
+                    serviceState,
+                    serviceState != ServiceState.STATE_POWER_OFF,
+                    pendingMO == null,
+                    !ringingCall.isRinging(),
+                    !disableCall.equals("true"),
+                    !foregroundCall.getState().isAlive(),
+                    foregroundCall.getState() == CdmaCall.State.ACTIVE,
+                    !backgroundCall.getState().isAlive()));
+        }
         return ret;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 7d2013b..11e04d4 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -22,6 +22,7 @@
 import com.android.internal.telephony.EventLogTags;
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
@@ -65,6 +66,13 @@
     CdmaCellLocation cellLoc;
     CdmaCellLocation newCellLoc;
 
+    // Min values used to by getOtasp()
+    private static final String UNACTIVATED_MIN2_VALUE = "000000";
+    private static final String UNACTIVATED_MIN_VALUE = "1111110111";
+
+    // Current Otasp value
+    int mCurrentOtaspMode = OTASP_UNINITIALIZED;
+
      /** if time between NITZ updates is less than mNitzUpdateSpacing the update may be ignored. */
     private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10;
     private int mNitzUpdateSpacing = SystemProperties.getInt("ro.nitz_update_spacing",
@@ -446,6 +454,13 @@
                     if (!mIsMinInfoReady) {
                         mIsMinInfoReady = true;
                     }
+                    int otaspMode = getOtasp();
+                    if (mCurrentOtaspMode != otaspMode) {
+                        Log.d(LOG_TAG, "call phone.notifyOtaspChanged old otaspMode=" +
+                                mCurrentOtaspMode + " new otaspMode=" + otaspMode);
+                        mCurrentOtaspMode = otaspMode;
+                        phone.notifyOtaspChanged(mCurrentOtaspMode);
+                    }
                     phone.getIccCard().broadcastIccStateChangedIntent(IccCard.INTENT_VALUE_ICC_IMSI,
                             null);
                 } else {
@@ -642,6 +657,11 @@
         curPlmn = plmn;
     }
 
+    @Override
+    protected Phone getPhone() {
+        return phone;
+    }
+
     /**
      * Handle the result of one of the pollState()-related requests
      */
@@ -1641,10 +1661,6 @@
         return false;
     }
 
-    protected void log(String s) {
-        Log.d(LOG_TAG, "[CdmaServiceStateTracker] " + s);
-    }
-
     public String getMdnNumber() {
         return mMdn;
     }
@@ -1700,6 +1716,32 @@
         }
     }
 
+    /**
+     * Returns OTASP_UNKNOWN, OTASP_NEEDED or OTASP_NOT_NEEDED
+     */
+    int getOtasp() {
+        int provisioningState;
+        if (mMin == null || (mMin.length() < 6)) {
+            if (DBG) Log.d(LOG_TAG, "getOtasp: bad mMin='" + mMin + "'");
+            provisioningState = OTASP_UNKNOWN;
+        } else {
+            if ((mMin.equals(UNACTIVATED_MIN_VALUE)
+                    || mMin.substring(0,6).equals(UNACTIVATED_MIN2_VALUE))
+                    || SystemProperties.getBoolean("test_cdma_setup", false)) {
+                provisioningState = OTASP_NEEDED;
+            } else {
+                provisioningState = OTASP_NOT_NEEDED;
+            }
+        }
+        if (DBG) Log.d(LOG_TAG, "getOtasp: state=" + provisioningState);
+        return provisioningState;
+    }
+
+    @Override
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[CdmaServiceStateTracker] " + s);
+    }
+
     private void hangupAndPowerOff() {
         // hang up all active voice calls
         phone.mCT.ringingCall.hangupIfAlive();
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 6332415..bc41b01 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -22,6 +22,7 @@
 import com.android.internal.telephony.EventLogTags;
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyIntents;
@@ -226,6 +227,9 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_LOCALE_CHANGED);
         phone.getContext().registerReceiver(mIntentReceiver, filter);
+
+        // Gsm doesn't support OTASP so its not needed
+        phone.notifyOtaspChanged(OTASP_NOT_NEEDED);
     }
 
     public void dispose() {
@@ -246,6 +250,11 @@
         if(DBG) Log.d(LOG_TAG, "GsmServiceStateTracker finalized");
     }
 
+    @Override
+    public Phone getPhone() {
+        return phone;
+    }
+
     /**
      * Registration point for transition into GPRS attached.
      * @param h handler to notify
@@ -1676,7 +1685,8 @@
         }
     }
 
-    private void log(String s) {
+    @Override
+    protected void log(String s) {
         Log.d(LOG_TAG, "[GsmServiceStateTracker] " + s);
     }
 }
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java
index 8cb05cc..7bbe696 100644
--- a/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/TestPhoneNotifier.java
@@ -56,4 +56,7 @@
 
     public void notifyDataActivity(Phone sender) {
     }
+
+    public void notifyOtaspChanged(Phone sender, int otaspMode) {
+    }
 }
diff --git a/tests/StatusBar/res/layout/button_notification.xml b/tests/StatusBar/res/layout/button_notification.xml
new file mode 100644
index 0000000..822e8cd
--- /dev/null
+++ b/tests/StatusBar/res/layout/button_notification.xml
@@ -0,0 +1,21 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="80sp"
+    android:orientation="horizontal"
+    >
+
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:src="@drawable/icon1"
+        />
+
+    <Button android:id="@+id/button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="button"
+        />
+
+</LinearLayout>
+
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 38ee1b8..2df97dc 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -100,6 +100,19 @@
             }
         },
 
+        new Test("Button") {
+            public void run() {
+                Notification n = new Notification(R.drawable.icon1, null,
+                        mActivityCreateTime);
+                n.contentView = new RemoteViews(getPackageName(), R.layout.button_notification);
+                n.flags |= Notification.FLAG_ONGOING_EVENT;
+                n.contentIntent = makeIntent();
+                n.contentView.setOnClickPendingIntent(R.id.button, makeIntent2());
+
+                mNM.notify(1, n);
+            }
+        },
+
         new Test("custom intent on text view") {
             public void run() {
                 Notification n = new Notification(R.drawable.icon1, null,
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap.java
deleted file mode 100644
index 35f022e..0000000
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap.java
+++ /dev/null
@@ -1,278 +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 android.graphics;
-
-
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.imageio.ImageIO;
-
-public final class Bitmap extends _Original_Bitmap {
-
-    private BufferedImage mImage;
-
-    public Bitmap(File input) throws IOException {
-        super(1, true, null, -1);
-
-        mImage = ImageIO.read(input);
-    }
-
-    public Bitmap(InputStream is) throws IOException {
-        super(1, true, null, -1);
-
-        mImage = ImageIO.read(is);
-    }
-
-    Bitmap(BufferedImage image) {
-        super(1, true, null, -1);
-        mImage = image;
-    }
-
-    public BufferedImage getImage() {
-        return mImage;
-    }
-
-    // ----- overriden methods
-
-    public enum Config {
-        // these native values must match up with the enum in SkBitmap.h
-        ALPHA_8     (2),
-        RGB_565     (4),
-        ARGB_4444   (5),
-        ARGB_8888   (6);
-
-        Config(int ni) {
-            this.nativeInt = ni;
-        }
-        final int nativeInt;
-
-        /* package */ static Config nativeToConfig(int ni) {
-            return sConfigs[ni];
-        }
-
-        private static Config sConfigs[] = {
-            null, null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888
-        };
-    }
-
-    @Override
-    public int getWidth() {
-        return mImage.getWidth();
-    }
-
-    @Override
-    public int getHeight() {
-        return mImage.getHeight();
-    }
-
-    /**
-     * Returns an immutable bitmap from the source bitmap. The new bitmap may
-     * be the same object as source, or a copy may have been made.
-     */
-    public static Bitmap createBitmap(Bitmap src) {
-        return createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), null, false);
-    }
-
-    /**
-     * Returns an immutable bitmap from the specified subset of the source
-     * bitmap. The new bitmap may be the same object as source, or a copy may
-     * have been made.
-     *
-     * @param source   The bitmap we are subsetting
-     * @param x        The x coordinate of the first pixel in source
-     * @param y        The y coordinate of the first pixel in source
-     * @param width    The number of pixels in each row
-     * @param height   The number of rows
-     */
-    public static Bitmap createBitmap(Bitmap source, int x, int y,
-                                      int width, int height) {
-        return new Bitmap(source.mImage.getSubimage(x, y, width, height));
-    }
-
-    /**
-     * Returns an immutable bitmap from subset of the source bitmap,
-     * transformed by the optional matrix.
-     *
-     * @param source   The bitmap we are subsetting
-     * @param x        The x coordinate of the first pixel in source
-     * @param y        The y coordinate of the first pixel in source
-     * @param width    The number of pixels in each row
-     * @param height   The number of rows
-     * @param m        Option matrix to be applied to the pixels
-     * @param filter   true if the source should be filtered.
-     *                   Only applies if the matrix contains more than just
-     *                   translation.
-     * @return A bitmap that represents the specified subset of source
-     * @throws IllegalArgumentException if the x, y, width, height values are
-     *         outside of the dimensions of the source bitmap.
-     */
-    public static Bitmap createBitmap(Bitmap source, int x, int y, int width,
-                                      int height, Matrix m, boolean filter) {
-        checkXYSign(x, y);
-        checkWidthHeight(width, height);
-        if (x + width > source.getWidth()) {
-            throw new IllegalArgumentException(
-                    "x + width must be <= bitmap.width()");
-        }
-        if (y + height > source.getHeight()) {
-            throw new IllegalArgumentException(
-                    "y + height must be <= bitmap.height()");
-        }
-
-        // check if we can just return our argument unchanged
-        if (!source.isMutable() && x == 0 && y == 0
-                && width == source.getWidth() && height == source.getHeight()
-                && (m == null || m.isIdentity())) {
-            return source;
-        }
-
-        if (m == null || m.isIdentity()) {
-            return new Bitmap(source.mImage.getSubimage(x, y, width, height));
-        }
-
-        int neww = width;
-        int newh = height;
-        Paint paint;
-
-        Rect srcR = new Rect(x, y, x + width, y + height);
-        RectF dstR = new RectF(0, 0, width, height);
-
-        /*  the dst should have alpha if the src does, or if our matrix
-            doesn't preserve rectness
-        */
-        boolean hasAlpha = source.hasAlpha() || !m.rectStaysRect();
-        RectF deviceR = new RectF();
-        m.mapRect(deviceR, dstR);
-        neww = Math.round(deviceR.width());
-        newh = Math.round(deviceR.height());
-
-        Canvas canvas = new Canvas(neww, newh);
-
-        canvas.translate(-deviceR.left, -deviceR.top);
-        canvas.concat(m);
-        paint = new Paint();
-        paint.setFilterBitmap(filter);
-        if (!m.rectStaysRect()) {
-            paint.setAntiAlias(true);
-        }
-
-        canvas.drawBitmap(source, srcR, dstR, paint);
-
-        return new Bitmap(canvas.getImage());
-    }
-
-    /**
-     * Returns a mutable bitmap with the specified width and height.
-     *
-     * @param width    The width of the bitmap
-     * @param height   The height of the bitmap
-     * @param config   The bitmap config to create.
-     * @throws IllegalArgumentException if the width or height are <= 0
-     */
-    public static Bitmap createBitmap(int width, int height, Config config) {
-        return new Bitmap(new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB));
-    }
-
-    /**
-     * Returns a immutable bitmap with the specified width and height, with each
-     * pixel value set to the corresponding value in the colors array.
-     *
-     * @param colors   Array of {@link Color} used to initialize the pixels.
-     * @param offset   Number of values to skip before the first color in the
-     *                 array of colors.
-     * @param stride   Number of colors in the array between rows (must be >=
-     *                 width or <= -width).
-     * @param width    The width of the bitmap
-     * @param height   The height of the bitmap
-     * @param config   The bitmap config to create. If the config does not
-     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
-     *                 bytes in the colors[] will be ignored (assumed to be FF)
-     * @throws IllegalArgumentException if the width or height are <= 0, or if
-     *         the color array's length is less than the number of pixels.
-     */
-    public static Bitmap createBitmap(int colors[], int offset, int stride,
-                                      int width, int height, Config config) {
-        checkWidthHeight(width, height);
-        if (Math.abs(stride) < width) {
-            throw new IllegalArgumentException("abs(stride) must be >= width");
-        }
-        int lastScanline = offset + (height - 1) * stride;
-        int length = colors.length;
-        if (offset < 0 || (offset + width > length)
-            || lastScanline < 0
-            || (lastScanline + width > length)) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-
-        // TODO: create an immutable bitmap...
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Returns a immutable bitmap with the specified width and height, with each
-     * pixel value set to the corresponding value in the colors array.
-     *
-     * @param colors   Array of {@link Color} used to initialize the pixels.
-     *                 This array must be at least as large as width * height.
-     * @param width    The width of the bitmap
-     * @param height   The height of the bitmap
-     * @param config   The bitmap config to create. If the config does not
-     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
-     *                 bytes in the colors[] will be ignored (assumed to be FF)
-     * @throws IllegalArgumentException if the width or height are <= 0, or if
-     *         the color array's length is less than the number of pixels.
-     */
-    public static Bitmap createBitmap(int colors[], int width, int height,
-                                      Config config) {
-        return createBitmap(colors, 0, width, width, height, config);
-    }
-
-    public static Bitmap createScaledBitmap(Bitmap src, int dstWidth,
-            int dstHeight, boolean filter) {
-        Matrix m;
-        synchronized (Bitmap.class) {
-            // small pool of just 1 matrix
-            m = sScaleMatrix;
-            sScaleMatrix = null;
-        }
-
-        if (m == null) {
-            m = new Matrix();
-        }
-
-        final int width = src.getWidth();
-        final int height = src.getHeight();
-        final float sx = dstWidth  / (float)width;
-        final float sy = dstHeight / (float)height;
-        m.setScale(sx, sy);
-        Bitmap b = Bitmap.createBitmap(src, 0, 0, width, height, m, filter);
-
-        synchronized (Bitmap.class) {
-            // do we need to check for null? why not just assign everytime?
-            if (sScaleMatrix == null) {
-                sScaleMatrix = m;
-            }
-        }
-
-        return b;
-    }
-
-
-}
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
index e978fe8..6fd59c4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import com.android.layoutlib.api.IDensityBasedResourceValue.Density;
+
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.util.DisplayMetrics;
@@ -454,7 +456,7 @@
             // into is.read(...) This number is not related to the value passed
             // to mark(...) above.
             try {
-                bm = new Bitmap(is);
+                bm = Bitmap_Delegate.createBitmap(is, Density.MEDIUM);
             } 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
new file mode 100644
index 0000000..24fba72
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -0,0 +1,327 @@
+/*
+ * 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.api.IDensityBasedResourceValue.Density;
+import com.android.layoutlib.bridge.DelegateManager;
+
+import android.graphics.Bitmap.Config;
+import android.os.Parcel;
+
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.Buffer;
+
+import javax.imageio.ImageIO;
+
+/**
+ * Delegate implementing the native methods of android.graphics.Bitmap
+ *
+ * Through the layoutlib_create tool, the original native methods of Bitmap have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original Bitmap class.
+ *
+ * @see DelegateManager
+ *
+ */
+public class Bitmap_Delegate {
+
+    // ---- delegate manager ----
+    private static final DelegateManager<Bitmap_Delegate> sManager =
+            new DelegateManager<Bitmap_Delegate>();
+
+    // ---- delegate helper data ----
+
+    // ---- delegate data ----
+    private BufferedImage mImage;
+    private boolean mHasAlpha = true;
+
+    // ---- Public Helper methods ----
+
+    /**
+     * Creates and returns a {@link Bitmap} initialized with the given file content.
+     */
+    public static Bitmap createBitmap(File input, 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());
+    }
+
+    /**
+     * Creates and returns a {@link Bitmap} initialized with the given stream content.
+     */
+    public static Bitmap createBitmap(InputStream input, 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());
+    }
+
+    /**
+     * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
+     */
+    public static Bitmap createBitmap(BufferedImage image, Density density) throws IOException {
+        // create a delegate with the given image.
+        Bitmap_Delegate delegate = new Bitmap_Delegate(image);
+
+        return createBitmap(delegate, density.getValue());
+    }
+
+    /**
+     * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}.
+     */
+    public static BufferedImage getImage(Bitmap bitmap) {
+        // get the delegate from the native int.
+        Bitmap_Delegate delegate = sManager.getDelegate(bitmap.mNativeBitmap);
+        if (delegate == null) {
+            assert false;
+            return null;
+        }
+
+        return delegate.mImage;
+    }
+
+    public static int getBufferedImageType(int nativeBitmapConfig) {
+        switch (Config.sConfigs[nativeBitmapConfig]) {
+            case ALPHA_8:
+                return BufferedImage.TYPE_INT_ARGB;
+            case RGB_565:
+                return BufferedImage.TYPE_INT_ARGB;
+            case ARGB_4444:
+                return BufferedImage.TYPE_INT_ARGB;
+            case ARGB_8888:
+                return BufferedImage.TYPE_INT_ARGB;
+        }
+
+        return BufferedImage.TYPE_INT_ARGB;
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width,
+            int height, int nativeConfig, boolean mutable) {
+        int imageType = getBufferedImageType(nativeConfig);
+
+        // create the image
+        BufferedImage image = new BufferedImage(width, height, imageType);
+
+        // fill it
+        //image.setRGB(x, y, rgb)
+
+        // create a delegate with the content of the stream.
+        Bitmap_Delegate delegate = new Bitmap_Delegate(image);
+
+        return createBitmap(delegate, Bitmap.getDefaultDensity());
+    }
+
+    /*package*/ static Bitmap nativeCopy(int srcBitmap, int nativeConfig, boolean isMutable) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap");
+    }
+
+    /*package*/ static void nativeDestructor(int nativeBitmap) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap");
+    }
+
+    /*package*/ static void nativeRecycle(int nativeBitmap) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap");
+    }
+
+    /*package*/ static boolean nativeCompress(int nativeBitmap, int format, int quality,
+            OutputStream stream, byte[] tempStorage) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap");
+    }
+
+    /*package*/ static void nativeErase(int nativeBitmap, int color) {
+        // get the delegate from the native int.
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            assert false;
+            return;
+        }
+
+        BufferedImage image = delegate.mImage;
+
+        Graphics2D g = image.createGraphics();
+        try {
+            if (delegate.mHasAlpha == false) {
+                color |= color & 0xFF000000;
+            }
+            g.setColor(new java.awt.Color(color));
+
+            g.fillRect(0, 0, image.getWidth(), image.getHeight());
+        } finally {
+            g.dispose();
+        }
+    }
+
+    /*package*/ static int nativeWidth(int nativeBitmap) {
+        // get the delegate from the native int.
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            assert false;
+            return 0;
+        }
+
+        return delegate.mImage.getWidth();
+    }
+
+    /*package*/ static int nativeHeight(int nativeBitmap) {
+        // get the delegate from the native int.
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            assert false;
+            return 0;
+        }
+
+        return delegate.mImage.getHeight();
+    }
+
+    /*package*/ static int nativeRowBytes(int nativeBitmap) {
+        // get the delegate from the native int.
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            assert false;
+            return 0;
+        }
+
+        return delegate.mImage.getWidth();
+    }
+
+    /*package*/ static int nativeConfig(int nativeBitmap) {
+        return Config.ARGB_8888.nativeInt;
+    }
+
+    /*package*/ static boolean nativeHasAlpha(int nativeBitmap) {
+        // get the delegate from the native int.
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            assert false;
+            return true;
+        }
+
+        return delegate.mHasAlpha;
+    }
+
+    /*package*/ static int nativeGetPixel(int nativeBitmap, int x, int y) {
+        // get the delegate from the native int.
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            assert false;
+            return 0;
+        }
+
+        return delegate.mImage.getRGB(x, y);
+    }
+
+    /*package*/ static void nativeGetPixels(int nativeBitmap, int[] pixels, int offset,
+            int stride, int x, int y, int width, int height) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeGetPixels");
+    }
+
+
+    /*package*/ static void nativeSetPixel(int nativeBitmap, int x, int y, int color) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSetPixel");
+    }
+
+    /*package*/ static void nativeSetPixels(int nativeBitmap, int[] colors, int offset,
+            int stride, int x, int y, int width, int height) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSetPixels");
+    }
+
+    /*package*/ static void nativeCopyPixelsToBuffer(int nativeBitmap, Buffer dst) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeCopyPixelsToBuffer");
+    }
+
+    /*package*/ static void nativeCopyPixelsFromBuffer(int nb, Buffer src) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeCopyPixelsFromBuffer");
+    }
+
+    /*package*/ static int nativeGenerationId(int nativeBitmap) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeGenerationId");
+    }
+
+    /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeCreateFromParcel");
+    }
+
+    /*package*/ static boolean nativeWriteToParcel(int nativeBitmap, boolean isMutable,
+            int density, Parcel p) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeWriteToParcel");
+    }
+
+    /*package*/ static Bitmap nativeExtractAlpha(int nativeBitmap, int nativePaint,
+            int[] offsetXY) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeExtractAlpha");
+    }
+
+
+    /*package*/ static void nativePrepareToDraw(int nativeBitmap) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativePrepareToDraw");
+    }
+
+    /*package*/ static void nativeSetHasAlpha(int nativeBitmap, boolean hasAlpha) {
+        // get the delegate from the native int.
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            assert false;
+            return;
+        }
+
+        delegate.mHasAlpha = hasAlpha;
+    }
+
+    /*package*/ static boolean nativeSameAs(int nb0, int nb1) {
+        // FIXME implement native delegate
+        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSameAs");
+    }
+
+    // ---- Private delegate/helper methods ----
+
+    private Bitmap_Delegate(BufferedImage image) {
+        mImage = image;
+    }
+
+    private static Bitmap createBitmap(Bitmap_Delegate delegate, 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);
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas.java b/tools/layoutlib/bridge/src/android/graphics/Canvas.java
index 0dccc0d6..24da812 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas.java
@@ -51,7 +51,7 @@
 
     public Canvas(Bitmap bitmap) {
         mLogger = null;
-        mBufferedImage = bitmap.getImage();
+        mBufferedImage = Bitmap_Delegate.getImage(bitmap);
         mGraphicsStack.push(mBufferedImage.createGraphics());
     }
 
@@ -227,7 +227,7 @@
      */
     @Override
     public void setBitmap(Bitmap bitmap) {
-        mBufferedImage = bitmap.getImage();
+        mBufferedImage = Bitmap_Delegate.getImage(bitmap);
         mGraphicsStack.push(mBufferedImage.createGraphics());
     }
 
@@ -557,7 +557,7 @@
 
     private void drawBitmap(Bitmap bitmap, int sleft, int stop, int sright, int sbottom, int dleft,
             int dtop, int dright, int dbottom, Paint paint) {
-        BufferedImage image = bitmap.getImage();
+        BufferedImage image = Bitmap_Delegate.getImage(bitmap);
 
         Graphics2D g = getGraphics2d();
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index ed2eff2..cc4a80c 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -76,7 +76,7 @@
 
     // ---- native methods ----
 
-    public static int native_create(int native_src_or_zero) {
+    /*package*/ static int native_create(int native_src_or_zero) {
         // create the delegate
         Matrix_Delegate newDelegate = new Matrix_Delegate();
 
@@ -94,7 +94,7 @@
         return sManager.addDelegate(newDelegate);
     }
 
-    public static boolean native_isIdentity(int native_object) {
+    /*package*/ static boolean native_isIdentity(int native_object) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -112,7 +112,7 @@
         return true;
     }
 
-    public static boolean native_rectStaysRect(int native_object) {
+    /*package*/ static boolean native_rectStaysRect(int native_object) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -122,7 +122,7 @@
         return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
     }
 
-    public static void native_reset(int native_object) {
+    /*package*/ static void native_reset(int native_object) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -132,7 +132,7 @@
         reset(d.mValues);
     }
 
-    public static void native_set(int native_object, int other) {
+    /*package*/ static void native_set(int native_object, int other) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -148,7 +148,7 @@
         System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
     }
 
-    public static void native_setTranslate(int native_object, float dx, float dy) {
+    /*package*/ static void native_setTranslate(int native_object, float dx, float dy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -158,7 +158,7 @@
         setTranslate(d.mValues, dx, dy);
     }
 
-    public static void native_setScale(int native_object, float sx, float sy, float px, float py) {
+    /*package*/ static void native_setScale(int native_object, float sx, float sy, float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -168,7 +168,7 @@
         d.mValues = getScale(sx, sy, px, py);
     }
 
-    public static void native_setScale(int native_object, float sx, float sy) {
+    /*package*/ static void native_setScale(int native_object, float sx, float sy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -186,7 +186,7 @@
         d.mValues[8] = 1;
     }
 
-    public static void native_setRotate(int native_object, float degrees, float px, float py) {
+    /*package*/ static void native_setRotate(int native_object, float degrees, float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -196,7 +196,7 @@
         d.mValues = getRotate(degrees, px, py);
     }
 
-    public static void native_setRotate(int native_object, float degrees) {
+    /*package*/ static void native_setRotate(int native_object, float degrees) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -206,7 +206,7 @@
         setRotate(d.mValues, degrees);
     }
 
-    public static void native_setSinCos(int native_object, float sinValue, float cosValue,
+    /*package*/ static void native_setSinCos(int native_object, float sinValue, float cosValue,
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
@@ -225,7 +225,7 @@
         d.postTransform(getTranslate(px, py));
     }
 
-    public static void native_setSinCos(int native_object, float sinValue, float cosValue) {
+    /*package*/ static void native_setSinCos(int native_object, float sinValue, float cosValue) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -235,7 +235,7 @@
         setRotate(d.mValues, sinValue, cosValue);
     }
 
-    public static void native_setSkew(int native_object, float kx, float ky, float px, float py) {
+    /*package*/ static void native_setSkew(int native_object, float kx, float ky, float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -245,7 +245,7 @@
         d.mValues = getSkew(kx, ky, px, py);
     }
 
-    public static void native_setSkew(int native_object, float kx, float ky) {
+    /*package*/ static void native_setSkew(int native_object, float kx, float ky) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -263,7 +263,7 @@
         d.mValues[8] = 1;
     }
 
-    public static boolean native_setConcat(int native_object, int a, int b) {
+    /*package*/ static boolean native_setConcat(int native_object, int a, int b) {
         if (a == native_object) {
             return native_preConcat(native_object, b);
         } else if (b == native_object) {
@@ -293,7 +293,7 @@
         return true;
     }
 
-    public static boolean native_preTranslate(int native_object, float dx, float dy) {
+    /*package*/ static boolean native_preTranslate(int native_object, float dx, float dy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -304,7 +304,7 @@
         return true;
     }
 
-    public static boolean native_preScale(int native_object, float sx, float sy,
+    /*package*/ static boolean native_preScale(int native_object, float sx, float sy,
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
@@ -316,7 +316,7 @@
         return true;
     }
 
-    public static boolean native_preScale(int native_object, float sx, float sy) {
+    /*package*/ static boolean native_preScale(int native_object, float sx, float sy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -327,7 +327,7 @@
         return true;
     }
 
-    public static boolean native_preRotate(int native_object, float degrees, float px, float py) {
+    /*package*/ static boolean native_preRotate(int native_object, float degrees, float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -338,7 +338,7 @@
         return true;
     }
 
-    public static boolean native_preRotate(int native_object, float degrees) {
+    /*package*/ static boolean native_preRotate(int native_object, float degrees) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -353,7 +353,7 @@
         return true;
     }
 
-    public static boolean native_preSkew(int native_object, float kx, float ky,
+    /*package*/ static boolean native_preSkew(int native_object, float kx, float ky,
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
@@ -365,7 +365,7 @@
         return true;
     }
 
-    public static boolean native_preSkew(int native_object, float kx, float ky) {
+    /*package*/ static boolean native_preSkew(int native_object, float kx, float ky) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -376,7 +376,7 @@
         return true;
     }
 
-    public static boolean native_preConcat(int native_object, int other_matrix) {
+    /*package*/ static boolean native_preConcat(int native_object, int other_matrix) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -393,7 +393,7 @@
         return true;
     }
 
-    public static boolean native_postTranslate(int native_object, float dx, float dy) {
+    /*package*/ static boolean native_postTranslate(int native_object, float dx, float dy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -404,7 +404,7 @@
         return true;
     }
 
-    public static boolean native_postScale(int native_object, float sx, float sy,
+    /*package*/ static boolean native_postScale(int native_object, float sx, float sy,
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
@@ -416,7 +416,7 @@
         return true;
     }
 
-    public static boolean native_postScale(int native_object, float sx, float sy) {
+    /*package*/ static boolean native_postScale(int native_object, float sx, float sy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -427,7 +427,7 @@
         return true;
     }
 
-    public static boolean native_postRotate(int native_object, float degrees, float px, float py) {
+    /*package*/ static boolean native_postRotate(int native_object, float degrees, float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -438,7 +438,7 @@
         return true;
     }
 
-    public static boolean native_postRotate(int native_object, float degrees) {
+    /*package*/ static boolean native_postRotate(int native_object, float degrees) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -449,7 +449,7 @@
         return true;
     }
 
-    public static boolean native_postSkew(int native_object, float kx, float ky,
+    /*package*/ static boolean native_postSkew(int native_object, float kx, float ky,
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
@@ -461,7 +461,7 @@
         return true;
     }
 
-    public static boolean native_postSkew(int native_object, float kx, float ky) {
+    /*package*/ static boolean native_postSkew(int native_object, float kx, float ky) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -472,7 +472,7 @@
         return true;
     }
 
-    public static boolean native_postConcat(int native_object, int other_matrix) {
+    /*package*/ static boolean native_postConcat(int native_object, int other_matrix) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -489,7 +489,7 @@
         return true;
     }
 
-    public static boolean native_setRectToRect(int native_object, RectF src, RectF dst, int stf) {
+    /*package*/ static boolean native_setRectToRect(int native_object, RectF src, RectF dst, int stf) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -553,13 +553,13 @@
         return true;
     }
 
-    public static boolean native_setPolyToPoly(int native_object, float[] src, int srcIndex,
+    /*package*/ static boolean native_setPolyToPoly(int native_object, float[] src, int srcIndex,
             float[] dst, int dstIndex, int pointCount) {
         // FIXME
-        throw new UnsupportedOperationException("NATIVE DELEGATE NEEDED");
+        throw new UnsupportedOperationException("Native delegate needed: Matrix_Delegate.native_setPolyToPoly");
     }
 
-    public static boolean native_invert(int native_object, int inverse) {
+    /*package*/ static boolean native_invert(int native_object, int inverse) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -589,7 +589,7 @@
         }
     }
 
-    public static void native_mapPoints(int native_object, float[] dst, int dstIndex,
+    /*package*/ static void native_mapPoints(int native_object, float[] dst, int dstIndex,
             float[] src, int srcIndex, int ptCount, boolean isPts) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
@@ -602,11 +602,11 @@
         } else {
             // src is vectors
             // FIXME
-            throw new UnsupportedOperationException("NATIVE DELEGATE NEEDED");
+            throw new UnsupportedOperationException("Native delegate needed: Matrix_Delegate.native_mapPoints");
         }
     }
 
-    public static boolean native_mapRect(int native_object, RectF dst, RectF src) {
+    /*package*/ static boolean native_mapRect(int native_object, RectF dst, RectF src) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -635,12 +635,12 @@
         return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
     }
 
-    public static float native_mapRadius(int native_object, float radius) {
+    /*package*/ static float native_mapRadius(int native_object, float radius) {
         // FIXME
-        throw new UnsupportedOperationException();
+        throw new UnsupportedOperationException("Native delegate needed: Matrix_Delegate.native_mapRadius");
     }
 
-    public static void native_getValues(int native_object, float[] values) {
+    /*package*/ static void native_getValues(int native_object, float[] values) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -650,7 +650,7 @@
         System.arraycopy(d.mValues, 0, d.mValues, 0, MATRIX_SIZE);
     }
 
-    public static void native_setValues(int native_object, float[] values) {
+    /*package*/ static void native_setValues(int native_object, float[] values) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
             assert false;
@@ -660,7 +660,7 @@
         System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
     }
 
-    public static boolean native_equals(int native_a, int native_b) {
+    /*package*/ static boolean native_equals(int native_a, int native_b) {
         Matrix_Delegate a = sManager.getDelegate(native_a);
         if (a == null) {
             assert false;
@@ -682,7 +682,7 @@
         return true;
     }
 
-    public static void finalizer(int native_instance) {
+    /*package*/ static void finalizer(int native_instance) {
         sManager.removeDelegate(native_instance);
     }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 309d934..248bdab 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -34,7 +34,7 @@
  *
  * This class behaves like the original native implementation, but in Java, keeping previously
  * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original Matrix class.
+ * it and the original Typeface class.
  *
  * @see DelegateManager
  *
@@ -84,7 +84,7 @@
 
     // ---- native methods ----
 
-    public static synchronized int nativeCreate(String familyName, int style) {
+    /*package*/ static synchronized int nativeCreate(String familyName, int style) {
         if (familyName == null) {
             familyName = DEFAULT_FAMILY;
         }
@@ -102,7 +102,7 @@
         return sManager.addDelegate(newDelegate);
     }
 
-    public static synchronized int nativeCreateFromTypeface(int native_instance, int style) {
+    /*package*/ static synchronized int nativeCreateFromTypeface(int native_instance, int style) {
         Typeface_Delegate delegate = sManager.getDelegate(native_instance);
         if (delegate == null) {
             assert false;
@@ -122,21 +122,21 @@
         return sManager.addDelegate(newDelegate);
     }
 
-    public static synchronized int nativeCreateFromAsset(AssetManager mgr, String path) {
+    /*package*/ static synchronized int nativeCreateFromAsset(AssetManager mgr, String path) {
         // FIXME
-        throw new UnsupportedOperationException();
+        throw new UnsupportedOperationException("Native delegate needed: Typeface_Delegate.nativeCreateFromAsset");
     }
 
-    public static synchronized int nativeCreateFromFile(String path) {
+    /*package*/ static synchronized int nativeCreateFromFile(String path) {
         // FIXME
-        throw new UnsupportedOperationException();
+        throw new UnsupportedOperationException("Native delegate needed: Typeface_Delegate.nativeCreateFromFile");
     }
 
-    public static void nativeUnref(int native_instance) {
+    /*package*/ static void nativeUnref(int native_instance) {
         sManager.removeDelegate(native_instance);
     }
 
-    public static int nativeGetStyle(int native_instance) {
+    /*package*/ static int nativeGetStyle(int native_instance) {
         Typeface_Delegate delegate = sManager.getDelegate(native_instance);
         if (delegate == null) {
             assert false;
@@ -146,7 +146,7 @@
         return delegate.mStyle;
     }
 
-    public static void setGammaForText(float blackGamma, float whiteGamma) {
+    /*package*/ static void setGammaForText(float blackGamma, float whiteGamma) {
         // This is for device testing only: pass
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java
index f624753..f13ecdc 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java
@@ -17,8 +17,8 @@
 package com.android.layoutlib.bridge;
 
 import com.android.layoutlib.api.IDensityBasedResourceValue;
-import com.android.layoutlib.api.IResourceValue;
 import com.android.layoutlib.api.IDensityBasedResourceValue.Density;
+import com.android.layoutlib.api.IResourceValue;
 import com.android.ninepatch.NinePatch;
 
 import org.kxml2.io.KXmlParser;
@@ -26,6 +26,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.graphics.Bitmap;
+import android.graphics.Bitmap_Delegate;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -105,7 +106,8 @@
      * @param isFramework indicates whether the resource is a framework resources.
      * Framework resources are cached, and loaded only once.
      */
-    public static Drawable getDrawable(IResourceValue value, BridgeContext context, boolean isFramework) {
+    public static Drawable getDrawable(IResourceValue value, BridgeContext context,
+            boolean isFramework) {
         Drawable d = null;
 
         String stringValue = value.getValue();
@@ -168,14 +170,8 @@
                             isFramework ? null : context.getProjectKey());
 
                     if (bitmap == null) {
-                        bitmap = new Bitmap(bmpFile);
-                        try {
-                            bitmap.setDensity(Density.MEDIUM.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.
-                        }
+                        // always create the cache copy in the original density.
+                        bitmap = Bitmap_Delegate.createBitmap(bmpFile, Density.MEDIUM);
                         Bridge.setCachedBitmap(stringValue, bitmap,
                                 isFramework ? null : context.getProjectKey());
                     }
diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java
index 6eed8ba..7c1eecd 100644
--- a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java
+++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java
@@ -87,7 +87,7 @@
 
             try {
                 // try to load the method with the given parameter types.
-                delegateClass.getMethod(originalMethod.getName(), parameters);
+                delegateClass.getDeclaredMethod(originalMethod.getName(), parameters);
             } catch (NoSuchMethodException e) {
                 // compute a full class name that's long but not too long.
                 StringBuilder sb = new StringBuilder(originalMethod.getName() + "(");
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 f6d11fe..0ecb474 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
@@ -103,6 +103,7 @@
      * The list of classes on which to delegate all native methods.
      */
     private final static String[] DELEGATE_CLASS_NATIVES = new String[] {
+        "android.graphics.Bitmap",
         "android.graphics.Matrix",
         "android.graphics.Typeface",
     };
@@ -123,7 +124,6 @@
      */
     private final static String[] RENAMED_CLASSES =
         new String[] {
-            "android.graphics.Bitmap",              "android.graphics._Original_Bitmap",
             "android.graphics.BitmapFactory",       "android.graphics._Original_BitmapFactory",
             "android.graphics.BitmapShader",        "android.graphics._Original_BitmapShader",
             "android.graphics.Canvas",              "android.graphics._Original_Canvas",