Merge change 8571

* changes:
  Don't leave restore data lying around after the operation
diff --git a/api/current.xml b/api/current.xml
index c6d68ef..9ae44e2 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -52941,8 +52941,8 @@
  visibility="public"
 >
 </method>
-<method name="getDensityScale"
- return="float"
+<method name="getDensity"
+ return="int"
  abstract="false"
  native="false"
  synchronized="false"
@@ -53051,6 +53051,19 @@
 <parameter name="metrics" type="android.util.DisplayMetrics">
 </parameter>
 </method>
+<method name="getScaledHeight"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetDensity" type="int">
+</parameter>
+</method>
 <method name="getScaledWidth"
  return="int"
  abstract="false"
@@ -53077,6 +53090,19 @@
 <parameter name="metrics" type="android.util.DisplayMetrics">
 </parameter>
 </method>
+<method name="getScaledWidth"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetDensity" type="int">
+</parameter>
+</method>
 <method name="getWidth"
  return="int"
  abstract="false"
@@ -53099,17 +53125,6 @@
  visibility="public"
 >
 </method>
-<method name="isAutoScalingEnabled"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="isMutable"
  return="boolean"
  abstract="false"
@@ -53154,7 +53169,7 @@
  visibility="public"
 >
 </method>
-<method name="setAutoScalingEnabled"
+<method name="setDensity"
  return="void"
  abstract="false"
  native="false"
@@ -53164,20 +53179,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="autoScalingEnabled" type="boolean">
-</parameter>
-</method>
-<method name="setDensityScale"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="densityScale" type="float">
+<parameter name="density" type="int">
 </parameter>
 </method>
 <method name="setPixel"
@@ -53247,11 +53249,11 @@
  visibility="public"
 >
 </field>
-<field name="DENSITY_SCALE_UNKNOWN"
- type="float"
+<field name="DENSITY_NONE"
+ type="int"
  transient="false"
  volatile="false"
- value="-1.0f"
+ value="0"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -53467,7 +53469,7 @@
 <parameter name="id" type="int">
 </parameter>
 </method>
-<method name="decodeStream"
+<method name="decodeResourceStream"
  return="android.graphics.Bitmap"
  abstract="false"
  native="false"
@@ -53626,6 +53628,26 @@
  visibility="public"
 >
 </field>
+<field name="inScreenDensity"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="inTargetDensity"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="inTempStorage"
  type="byte[]"
  transient="false"
@@ -54880,8 +54902,8 @@
  visibility="public"
 >
 </method>
-<method name="getDensityScale"
- return="float"
+<method name="getDensity"
+ return="int"
  abstract="false"
  native="false"
  synchronized="false"
@@ -55237,7 +55259,7 @@
 <parameter name="bitmap" type="android.graphics.Bitmap">
 </parameter>
 </method>
-<method name="setDensityScale"
+<method name="setDensity"
  return="void"
  abstract="false"
  native="false"
@@ -55247,7 +55269,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="densityScale" type="float">
+<parameter name="density" type="int">
 </parameter>
 </method>
 <method name="setDrawFilter"
@@ -57559,6 +57581,17 @@
 <parameter name="paint" type="android.graphics.Paint">
 </parameter>
 </method>
+<method name="getDensity"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getHeight"
  return="int"
  abstract="false"
@@ -62962,7 +62995,7 @@
  type="android.graphics.drawable.BitmapDrawable"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </constructor>
@@ -62973,6 +63006,28 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+</constructor>
+<constructor name="BitmapDrawable"
+ type="android.graphics.drawable.BitmapDrawable"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="bitmap" type="android.graphics.Bitmap">
+</parameter>
+</constructor>
+<constructor name="BitmapDrawable"
+ type="android.graphics.drawable.BitmapDrawable"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
 <parameter name="bitmap" type="android.graphics.Bitmap">
 </parameter>
 </constructor>
@@ -63138,6 +63193,45 @@
 <parameter name="gravity" type="int">
 </parameter>
 </method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="canvas" type="android.graphics.Canvas">
+</parameter>
+</method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="metrics" type="android.util.DisplayMetrics">
+</parameter>
+</method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="density" type="int">
+</parameter>
+</method>
 <method name="setTileModeX"
  return="void"
  abstract="false"
@@ -63474,6 +63568,25 @@
 <parameter name="pathName" type="java.lang.String">
 </parameter>
 </method>
+<method name="createFromResourceStream"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="value" type="android.util.TypedValue">
+</parameter>
+<parameter name="is" type="java.io.InputStream">
+</parameter>
+<parameter name="srcName" type="java.lang.String">
+</parameter>
+</method>
 <method name="createFromStream"
  return="android.graphics.drawable.Drawable"
  abstract="false"
@@ -65171,7 +65284,7 @@
  type="android.graphics.drawable.NinePatchDrawable"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="bitmap" type="android.graphics.Bitmap">
@@ -65190,6 +65303,36 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="bitmap" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="chunk" type="byte[]">
+</parameter>
+<parameter name="padding" type="android.graphics.Rect">
+</parameter>
+<parameter name="srcName" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="NinePatchDrawable"
+ type="android.graphics.drawable.NinePatchDrawable"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="patch" type="android.graphics.NinePatch">
+</parameter>
+</constructor>
+<constructor name="NinePatchDrawable"
+ type="android.graphics.drawable.NinePatchDrawable"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
 <parameter name="patch" type="android.graphics.NinePatch">
 </parameter>
 </constructor>
@@ -65254,6 +65397,45 @@
 <parameter name="cf" type="android.graphics.ColorFilter">
 </parameter>
 </method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="canvas" type="android.graphics.Canvas">
+</parameter>
+</method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="metrics" type="android.util.DisplayMetrics">
+</parameter>
+</method>
+<method name="setTargetDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="density" type="int">
+</parameter>
+</method>
 </class>
 <class name="PaintDrawable"
  extends="android.graphics.drawable.ShapeDrawable"
@@ -137944,6 +138126,16 @@
  visibility="public"
 >
 </field>
+<field name="densityDpi"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="heightPixels"
  type="int"
  transient="false"
diff --git a/cmds/keystore/keymgmt.c b/cmds/keystore/keymgmt.c
index 66edd56..c45b53c 100644
--- a/cmds/keystore/keymgmt.c
+++ b/cmds/keystore/keymgmt.c
@@ -79,14 +79,26 @@
 {
     int size, fd, ret = -1;
     unsigned char enc_blob[MAX_BLOB_LEN];
-
     char tmpfile[KEYFILE_LEN];
+
+    if ((keyfile == NULL) || (strlen(keyfile) >= (KEYFILE_LEN - 4))) {
+        LOGE("keyfile name is too long or null");
+        return -1;
+    }
     strcpy(tmpfile, keyfile);
     strcat(tmpfile, ".tmp");
 
     // prepare the blob
+    if (IV_LEN > USER_KEY_LEN) {
+        LOGE("iv length is too long.");
+        return -1;
+    }
     memcpy(blob->iv, iv, IV_LEN);
     blob->blob_size = get_blob_size(blob);
+    if (blob->blob_size > MAX_BLOB_LEN) {
+        LOGE("blob data size is too large.");
+        return -1;
+    }
     memcpy(enc_blob, blob->blob, blob->blob_size);
     AES_cbc_encrypt((unsigned char *)enc_blob, (unsigned char *)blob->blob,
                     blob->blob_size, enc_key, iv, AES_ENCRYPT);
@@ -133,8 +145,13 @@
     DATA_BLOB blob;
 
     // prepare the blob
+    if (strlen(MASTER_KEY_TAG) >= USER_KEY_LEN) return -1;
     strlcpy(blob.keyname, MASTER_KEY_TAG, USER_KEY_LEN);
     blob.value_size = USER_KEY_LEN;
+    if (USER_KEY_LEN > MAX_KEY_VALUE_LENGTH) {
+        LOGE("master_key length is too long.");
+        return -1;
+    }
     memcpy((void*)blob.value, (const void*)master_key, USER_KEY_LEN);
 
     // generate the encryption key
@@ -150,6 +167,10 @@
 
     get_decrypt_key(upasswd, &key);
     ret = load_n_decrypt(MASTER_KEY_TAG, MASTER_KEY, &key, &blob);
+    if (blob.value_size > USER_KEY_LEN) {
+        LOGE("the blob's value size is too large");
+        return -1;
+    }
     if (!ret) memcpy(master_key, blob.value, blob.value_size);
     return ret;
 }
@@ -224,8 +245,16 @@
     }
     sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
     // flatten the args
+    if (strlen(keyname) >= MAX_KEY_NAME_LENGTH) {
+        LOGE("keyname is too long.");
+        return -1;
+    }
     strcpy(blob.keyname, keyname);
     blob.value_size = size;
+    if (size > MAX_KEY_VALUE_LENGTH) {
+        LOGE("the data size is too large.");
+        return -1;
+    }
     memcpy(blob.value, data, size);
     return encrypt_n_save(&encryptKey, &blob, keyfile);
 }
@@ -246,6 +275,7 @@
     ret = load_n_decrypt(keyname, keyfile, &decryptKey, &blob);
     if (!ret) {
         if ((blob.value_size > MAX_KEY_VALUE_LENGTH)) {
+            LOGE("blob value size is too large.");
             ret = -1;
         } else {
             *size = blob.value_size;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 76b47f1..182843a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -177,11 +177,17 @@
         synchronized (mPackages) {
             // Resources is app scale dependent.
             ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
-            //Log.w(TAG, "getTopLevelResources: " + resDir);
+            if (false) {
+                Log.w(TAG, "getTopLevelResources: " + resDir + " / "
+                        + compInfo.applicationScale);
+            }
             WeakReference<Resources> wr = mActiveResources.get(key);
             Resources r = wr != null ? wr.get() : null;
             if (r != null && r.getAssets().isUpToDate()) {
-                //Log.w(TAG, "Returning cached resources " + r + " " + resDir);
+                if (false) {
+                    Log.w(TAG, "Returning cached resources " + r + " " + resDir
+                            + ": appScale=" + r.getCompatibilityInfo().applicationScale);
+                }
                 return r;
             }
 
@@ -198,7 +204,11 @@
             //Log.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
             DisplayMetrics metrics = getDisplayMetricsLocked(false);
             r = new Resources(assets, metrics, getConfiguration(), compInfo);
-            //Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration());
+            if (false) {
+                Log.i(TAG, "Created app resources " + resDir + " " + r + ": "
+                        + r.getConfiguration() + " appScale="
+                        + r.getCompatibilityInfo().applicationScale);
+            }
             // XXX need to remove entries when weak references go away
             mActiveResources.put(key, new WeakReference<Resources>(r));
             return r;
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index ae9e380..1e4ab68 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -544,7 +544,10 @@
             if (fd != null) {
                 Bitmap bm = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor());
                 if (bm != null) {
-                    return new BitmapDrawable(bm);
+                    // For now clear the density until we figure out how
+                    // to deal with it for wallpapers.
+                    bm.setDensity(0);
+                    return new BitmapDrawable(getResources(), bm);
                 }
             }
         } catch (RemoteException e) {
@@ -1965,6 +1968,15 @@
             try {
                 Resources r = getResourcesForApplication(appInfo);
                 dr = r.getDrawable(resid);
+                if (false) {
+                    RuntimeException e = new RuntimeException("here");
+                    e.fillInStackTrace();
+                    Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
+                            + " from package " + packageName
+                            + ": app scale=" + r.getCompatibilityInfo().applicationScale
+                            + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
+                            e);
+                }
                 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
                         + Integer.toHexString(resid) + " from " + r
                         + ": " + dr);
@@ -2052,10 +2064,9 @@
             if (app.packageName.equals("system")) {
                 return mContext.mMainThread.getSystemContext().getResources();
             }
-            ActivityThread.PackageInfo pi = mContext.mMainThread.getPackageInfoNoCheck(app);
             Resources r = mContext.mMainThread.getTopLevelResources(
                     app.uid == Process.myUid() ? app.sourceDir
-                    : app.publicSourceDir, pi);
+                    : app.publicSourceDir, mContext.mPackageInfo);
             if (r != null) {
                 return r;
             }
diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java
index accdda9..d788c43 100644
--- a/core/java/android/app/LauncherActivity.java
+++ b/core/java/android/app/LauncherActivity.java
@@ -297,7 +297,7 @@
                     icon.setBounds(x, y, x + width, y + height);
                     icon.draw(canvas);
                     icon.setBounds(mOldBounds);
-                    icon = new BitmapDrawable(thumb);
+                    icon = new BitmapDrawable(getResources(), thumb);
                 } else if (iconWidth < width && iconHeight < height) {
                     final Bitmap.Config c = Bitmap.Config.ARGB_8888;
                     final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
@@ -309,7 +309,7 @@
                     icon.setBounds(x, y, x + iconWidth, y + iconHeight);
                     icon.draw(canvas);
                     icon.setBounds(mOldBounds);
-                    icon = new BitmapDrawable(thumb);
+                    icon = new BitmapDrawable(getResources(), thumb);
                 }
             }
 
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 54061ae..17e6e50 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -136,6 +136,8 @@
             private int mPreviousLength = 0;
 
             public long getPostingDelay(CharSequence constraint) {
+                if (constraint == null) return 0;
+                
                 long delay = constraint.length() < mPreviousLength ? DELETE_KEY_POST_DELAY : 0;
                 mPreviousLength = constraint.length();
                 return delay;
@@ -196,14 +198,18 @@
             callCursorPreClose(mCursor);
         }
 
-        super.changeCursor(c);
-        if (c != null) {
-            mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT);
-            mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
-            mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
-            mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
-            mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
-            mBackgroundColorCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_BACKGROUND_COLOR);
+        try {
+            super.changeCursor(c);
+            if (c != null) {
+                mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT);
+                mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
+                mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
+                mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
+                mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
+                mBackgroundColorCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_BACKGROUND_COLOR);
+            }
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "error changing cursor and caching columns", e);
         }
     }
 
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 69c3d41..5fb0120 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -113,7 +113,7 @@
         public static final String SEND_TO_VOICEMAIL = "send_to_voicemail";
     }
 
-    public interface AggregatesColumns {
+    private interface AggregatesColumns {
         /**
          * The display name for the contact.
          * <P>Type: TEXT</P>
@@ -143,8 +143,33 @@
          * any {@link GroupMembership} for this aggregate.
          */
         public static final String IN_VISIBLE_GROUP = "in_visible_group";
+
+        /**
+         * Contact presence status.  See {@link android.provider.Im.CommonPresenceColumns}
+         * for individual status definitions.
+         */
+        public static final String PRESENCE_STATUS = Presence.PRESENCE_STATUS;
+
+        /**
+         * The type of data, for example Home or Work.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String PRIMARY_PHONE_TYPE = CommonDataKinds.Phone.TYPE;
+
+        /**
+         * The user defined label for the primary phone.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PRIMARY_PHONE_LABEL = CommonDataKinds.Phone.LABEL;
+
+        /**
+         * The primary phone number.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PRIMARY_PHONE_NUMBER = CommonDataKinds.Phone.NUMBER;
     }
 
+
     /**
      * Constants for the aggregates table, which contains a record per group
      * of contact representing the same person.
@@ -196,7 +221,6 @@
 
         public static final Uri CONTENT_SUMMARY_GROUP_URI = Uri.withAppendedPath(
                 CONTENT_SUMMARY_URI, "group");
-
         /**
          * The MIME type of {@link #CONTENT_URI} providing a directory of
          * people.
@@ -511,11 +535,19 @@
      * back to specific {@link ContactsContract.Aggregates#_ID} entries.
      */
     private interface PresenceColumns {
+
         /**
-         * Reference to the {@link Aggregates#_ID} this presence references.
+         * The unique ID for a row.
+         * <P>Type: INTEGER (long)</P>
+         */
+        public static final String _ID = "presence_id";
+
+        /**
+         * Reference to the {@link android.provider.ContactsContract.Contacts#_ID} this presence
+         * references.
          * <P>Type: INTEGER</P>
          */
-        public static final String AGGREGATE_ID = "aggregate_id";
+        public static final String CONTACT_ID = "contact_id";
 
         /**
          * Reference to the {@link Data#_ID} entry that owns this presence.
@@ -545,8 +577,7 @@
         public static final String IM_ACCOUNT = "im_account";
     }
 
-    public static final class Presence implements BaseColumns, PresenceColumns,
-            Im.CommonPresenceColumns {
+    public static final class Presence implements PresenceColumns, Im.CommonPresenceColumns {
         /**
          * This utility class cannot be instantiated
          */
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 3d10f17..524f941 100644
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -284,6 +284,12 @@
      */
     public static java.text.DateFormat getDateFormatForSetting(Context context,
                                                                String value) {
+        String format = getDateFormatStringForSetting(context, value);
+
+        return new java.text.SimpleDateFormat(format);
+    }
+
+    private static String getDateFormatStringForSetting(Context context, String value) {
         if (value != null) {
             int month = value.indexOf('M');
             int day = value.indexOf('d');
@@ -291,7 +297,7 @@
 
             if (month >= 0 && day >= 0 && year >= 0) {
                 String template = context.getString(R.string.numeric_date_template);
-                if (year < month) {
+                if (year < month && year < day) {
                     if (month < day) {
                         value = String.format(template, "yyyy", "MM", "dd");
                     } else {
@@ -311,7 +317,7 @@
                     }
                 }
 
-                return new java.text.SimpleDateFormat(value);
+                return value;
             }
         }
 
@@ -321,7 +327,7 @@
          * so that we get a four-digit year instead a two-digit year.
          */
         value = context.getString(R.string.numeric_date_format);
-        return new java.text.SimpleDateFormat(value);
+        return value;
     }
     
     /**
@@ -347,7 +353,11 @@
     /**
      * Gets the current date format stored as a char array. The array will contain
      * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order    
-     * preferred by the user.
+     * specified by the user's format preference.  Note that this order is
+     * only appropriate for all-numeric dates; spelled-out (MEDIUM and LONG)
+     * dates will generally contain other punctuation, spaces, or words,
+     * not just the day, month, and year, and not necessarily in the same
+     * order returned here.
      */    
     public static final char[] getDateFormatOrder(Context context) {
         char[] order = new char[] {DATE, MONTH, YEAR};
@@ -380,22 +390,10 @@
     }
     
     private static String getDateFormatString(Context context) {
-        java.text.DateFormat df;
-        df = java.text.DateFormat.getDateInstance(java.text.DateFormat.SHORT);
-        if (df instanceof SimpleDateFormat) {
-            return ((SimpleDateFormat) df).toPattern();
-        }
-
         String value = Settings.System.getString(context.getContentResolver(),
                 Settings.System.DATE_FORMAT);
-        if (value == null || value.length() < 6) {
-            /*
-             * No need to localize -- this is an emergency fallback in case
-             * the setting is missing, but it should always be set.
-             */
-            value = "MM-dd-yyyy";
-        }
-        return value;
+
+        return getDateFormatStringForSetting(context, value);
     }
 
     /**
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index 29c0c76..911a23c 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -43,7 +43,7 @@
      */
     public ImageSpan(Bitmap b, int verticalAlignment) {
         super(verticalAlignment);
-        mDrawable = new BitmapDrawable(b);
+        mDrawable = new BitmapDrawable(mContext.getResources(), b);
         int width = mDrawable.getIntrinsicWidth();
         int height = mDrawable.getIntrinsicHeight();
         mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0); 
@@ -117,7 +117,7 @@
                 InputStream is = mContext.getContentResolver().openInputStream(
                         mContentUri);
                 bitmap = BitmapFactory.decodeStream(is);
-                drawable = new BitmapDrawable(bitmap);
+                drawable = new BitmapDrawable(mContext.getResources(), bitmap);
                 drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
                         drawable.getIntrinsicHeight());
                 is.close();
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 061f98a..dd5a440 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -80,6 +80,11 @@
      */
     public float density;
     /**
+     * The screen density expressed as dots-per-inch.  May be either
+     * {@link #DENSITY_LOW}, {@link #DENSITY_MEDIUM}, or {@link #DENSITY_HIGH}.
+     */
+    public int densityDpi;
+    /**
      * A scaling factor for fonts displayed on the display.  This is the same
      * as {@link #density}, except that it may be adjusted in smaller
      * increments at runtime based on a user preference for the font size.
@@ -101,6 +106,7 @@
         widthPixels = o.widthPixels;
         heightPixels = o.heightPixels;
         density = o.density;
+        densityDpi = o.densityDpi;
         scaledDensity = o.scaledDensity;
         xdpi = o.xdpi;
         ydpi = o.ydpi;
@@ -110,6 +116,7 @@
         widthPixels = 0;
         heightPixels = 0;
         density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
+        densityDpi = DENSITY_DEVICE;
         scaledDensity = density;
         xdpi = DENSITY_DEVICE;
         ydpi = DENSITY_DEVICE;
@@ -186,9 +193,11 @@
                 heightPixels = defaultHeight;
             }
         }
+        
         if (compatibilityInfo.isScalingRequired()) {
             float invertedRatio = compatibilityInfo.applicationInvertedScale;
             density *= invertedRatio;
+            densityDpi = (int)((density*DisplayMetrics.DENSITY_DEFAULT)+.5f);
             scaledDensity *= invertedRatio;
             xdpi *= invertedRatio;
             ydpi *= invertedRatio;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 5551f64..b055d51 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -94,6 +94,7 @@
         outMetrics.widthPixels  = getWidth();
         outMetrics.heightPixels = getHeight();
         outMetrics.density      = mDensity;
+        outMetrics.densityDpi   = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
         outMetrics.scaledDensity= outMetrics.density;
         outMetrics.xdpi         = mDpiX;
         outMetrics.ydpi         = mDpiY;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ff8868b..7ed2712 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -46,6 +46,7 @@
 import android.os.SystemProperties;
 import android.util.AttributeSet;
 import android.util.Config;
+import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Pool;
@@ -5976,6 +5977,7 @@
 
                 try {
                     bitmap = Bitmap.createBitmap(width, height, quality);
+                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
                     if (autoScale) {
                         mDrawingCache = new SoftReference<Bitmap>(bitmap);
                     } else {
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 0003eb7..cacf7a2 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -191,7 +191,7 @@
      */
     AudioManager mAudioManager;
 
-    private final float mDensity;
+    private final int mDensity;
 
     public ViewRoot(Context context) {
         super();
@@ -236,7 +236,7 @@
         mAdded = false;
         mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, this);
         mViewConfiguration = ViewConfiguration.get(context);
-        mDensity = context.getResources().getDisplayMetrics().density;
+        mDensity = context.getResources().getDisplayMetrics().densityDpi;
     }
 
     @Override
@@ -1277,7 +1277,7 @@
             }
 
             // TODO: Do this in native
-            canvas.setDensityScale(mDensity);
+            canvas.setDensity(mDensity);
         } catch (Surface.OutOfResourcesException e) {
             Log.e("ViewRoot", "OutOfResourcesException locking surface", e);
             // TODO: we should ask the window manager to do something!
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index 4fe4036..3da5a3c 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -31,7 +31,6 @@
 import android.security.CertTool;
 import android.util.Log;
 import android.webkit.CacheManager.CacheResult;
-import android.widget.Toast;
 
 import com.android.internal.R;
 
@@ -997,8 +996,6 @@
                 mDataBuilder.releaseChunk(c);
             }
             CertTool.getInstance().addCertificate(cert, mContext);
-            Toast.makeText(mContext, R.string.certificateSaved,
-                    Toast.LENGTH_SHORT).show();
             mBrowserFrame.stopLoading();
             return;
         }
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 3b9f1de..5e76cc3 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -31,6 +31,7 @@
 import com.android.internal.widget.NumberPicker.OnChangedListener;
 
 import java.text.DateFormatSymbols;
+import java.text.SimpleDateFormat;
 import java.util.Calendar;
 
 /**
@@ -101,7 +102,8 @@
         mMonthPicker = (NumberPicker) findViewById(R.id.month);
         mMonthPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
         DateFormatSymbols dfs = new DateFormatSymbols();
-        mMonthPicker.setRange(1, 12, dfs.getShortMonths());
+        String[] months = dfs.getShortMonths();
+        mMonthPicker.setRange(1, 12, months);
         mMonthPicker.setSpeed(200);
         mMonthPicker.setOnChangeListener(new OnChangedListener() {
             public void onChanged(NumberPicker picker, int oldVal, int newVal) {
@@ -146,7 +148,7 @@
         init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), null);
         
         // re-order the number pickers to match the current date format
-        reorderPickers();
+        reorderPickers(months);
         
         if (!isEnabled()) {
             setEnabled(false);
@@ -161,29 +163,69 @@
         mYearPicker.setEnabled(enabled);
     }
 
-    private void reorderPickers() {
-        char[] order = DateFormat.getDateFormatOrder(mContext);
-        
-        /* Default order is month, date, year so if that's the order then
-         * do nothing.
+    private void reorderPickers(String[] months) {
+        java.text.DateFormat format;
+        String order;
+
+        /*
+         * If the user is in a locale where the medium date format is
+         * still numeric (Japanese and Czech, for example), respect
+         * the date format order setting.  Otherwise, use the order
+         * that the locale says is appropriate for a spelled-out date.
          */
-        if ((order[0] == DateFormat.MONTH) && (order[1] == DateFormat.DATE)) {
-            return;
+
+        if (months[0].startsWith("1")) {
+            format = DateFormat.getDateFormat(getContext());
+        } else {
+            format = DateFormat.getMediumDateFormat(getContext());
         }
-        
+
+        if (format instanceof SimpleDateFormat) {
+            order = ((SimpleDateFormat) format).toPattern();
+        } else {
+            // Shouldn't happen, but just in case.
+            order = new String(DateFormat.getDateFormatOrder(getContext()));
+        }
+
         /* Remove the 3 pickers from their parent and then add them back in the
          * required order.
          */
         LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
         parent.removeAllViews();
-        for (char c : order) {
-            if (c == DateFormat.DATE) {
-                parent.addView(mDayPicker);
-            } else if (c == DateFormat.MONTH) {
-                parent.addView(mMonthPicker);
-            } else {
-                parent.addView (mYearPicker);
+
+        boolean quoted = false;
+        boolean didDay = false, didMonth = false, didYear = false;
+
+        for (int i = 0; i < order.length(); i++) {
+            char c = order.charAt(i);
+
+            if (c == '\'') {
+                quoted = !quoted;
             }
+
+            if (!quoted) {
+                if (c == DateFormat.DATE && !didDay) {
+                    parent.addView(mDayPicker);
+                    didDay = true;
+                } else if ((c == DateFormat.MONTH || c == 'L') && !didMonth) {
+                    parent.addView(mMonthPicker);
+                    didMonth = true;
+                } else if (c == DateFormat.YEAR && !didYear) {
+                    parent.addView (mYearPicker);
+                    didYear = true;
+                }
+            }
+        }
+
+        // Shouldn't happen, but just in case.
+        if (!didMonth) {
+            parent.addView(mMonthPicker);
+        }
+        if (!didDay) {
+            parent.addView(mDayPicker);
+        }
+        if (!didYear) {
+            parent.addView(mYearPicker);
         }
     }
 
@@ -192,6 +234,7 @@
         mMonth = monthOfYear;
         mDay = dayOfMonth;
         updateSpinners();
+        reorderPickers(new DateFormatSymbols().getShortMonths());
     }
 
     private static class SavedState extends BaseSavedState {
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 2796774..6a9bcfb 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -317,7 +317,7 @@
     public void setImageBitmap(Bitmap bm) {
         // if this is used frequently, may handle bitmaps explicitly
         // to reduce the intermediate drawable object
-        setImageDrawable(new BitmapDrawable(bm));
+        setImageDrawable(new BitmapDrawable(mContext.getResources(), bm));
     }
 
     public void setImageState(int[] state, boolean merge) {
diff --git a/core/java/com/android/internal/widget/EditStyledText.java b/core/java/com/android/internal/widget/EditStyledText.java
index f0ad7b3..82197c0 100644
--- a/core/java/com/android/internal/widget/EditStyledText.java
+++ b/core/java/com/android/internal/widget/EditStyledText.java
@@ -1242,7 +1242,8 @@
                         try {
                             InputStream is = mEST.getContext().getContentResolver().openInputStream(uri);
                             Bitmap bitmap = BitmapFactory.decodeStream(is);
-                            Drawable drawable = new BitmapDrawable(bitmap);
+                            Drawable drawable = new BitmapDrawable(
+                                    getContext().getResources(), bitmap);
                             drawable.setBounds(0, 0,
                                     drawable.getIntrinsicWidth(),
                                     drawable.getIntrinsicHeight());
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index c61b2ed..c16a75e 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -463,17 +463,18 @@
     static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
                                           SkCanvas* canvas, SkBitmap* bitmap,
                                           jfloat left, jfloat top,
-                                          SkPaint* paint,
-                                          jboolean autoScale, jfloat densityScale) {
+                                          SkPaint* paint, jint canvasDensity,
+                                          jint bitmapDensity) {
         SkScalar left_ = SkFloatToScalar(left);
         SkScalar top_ = SkFloatToScalar(top);
 
-        if (!autoScale || densityScale <= 0.0f) {
+        if (canvasDensity == bitmapDensity || canvasDensity == 0
+                || bitmapDensity == 0) {
             canvas->drawBitmap(*bitmap, left_, top_, paint);
         } else {
             canvas->save();
-            SkScalar canvasScale = GraphicsJNI::getCanvasDensityScale(env, jcanvas);
-            SkScalar scale = canvasScale / SkFloatToScalar(densityScale);
+            SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity);
+            canvas->translate(left_, top_);
             canvas->scale(scale, scale);
 
             SkPaint filteredPaint;
@@ -482,7 +483,7 @@
             }
             filteredPaint.setFilterBitmap(true);
 
-            canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
+            canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
 
             canvas->restore();
         }
@@ -906,7 +907,7 @@
     {"native_drawRoundRect","(ILandroid/graphics/RectF;FFI)V",
         (void*) SkCanvasGlue::drawRoundRect},
     {"native_drawPath","(III)V", (void*) SkCanvasGlue::drawPath},
-    {"native_drawBitmap","(IIFFIZF)V",
+    {"native_drawBitmap","(IIFFIII)V",
         (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
     {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;I)V",
         (void*) SkCanvasGlue::drawBitmapRF},
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 6e159a8..ca1cb7d 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -163,7 +163,6 @@
 
 static jclass   gCanvas_class;
 static jfieldID gCanvas_nativeInstanceID;
-static jfieldID gCanvas_densityScaleID;
 
 static jclass   gPaint_class;
 static jfieldID gPaint_nativeInstanceID;
@@ -320,13 +319,6 @@
     return c;
 }
 
-SkScalar GraphicsJNI::getCanvasDensityScale(JNIEnv* env, jobject canvas) {
-    SkASSERT(env);
-    SkASSERT(canvas);
-    SkASSERT(env->IsInstanceOf(canvas, gCanvas_class));
-    return SkFloatToScalar(env->GetFloatField(canvas, gCanvas_densityScaleID));
-}
-
 SkPaint* GraphicsJNI::getNativePaint(JNIEnv* env, jobject paint) {
     SkASSERT(env);
     SkASSERT(paint);
@@ -557,7 +549,6 @@
 
     gCanvas_class = make_globalref(env, "android/graphics/Canvas");
     gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvas", "I");
-    gCanvas_densityScaleID = getFieldIDCheck(env, gCanvas_class, "mDensityScale", "F");
 
     gPaint_class = make_globalref(env, "android/graphics/Paint");
     gPaint_nativeInstanceID = getFieldIDCheck(env, gPaint_class, "mNativePaint", "I");
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 16925e4..f8b60a8 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -38,7 +38,6 @@
     static SkBitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
     static SkPicture* getNativePicture(JNIEnv*, jobject picture);
     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
-    static SkScalar getCanvasDensityScale(JNIEnv*, jobject canvas);
     
     /** Return the corresponding native config from the java Config enum,
         or kNo_Config if the java object is null.
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index b11edfc..fd5271e 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -1,5 +1,6 @@
 #include <utils/ResourceTypes.h>
 
+#include "SkCanvas.h"
 #include "SkRegion.h"
 #include "GraphicsJNI.h"
 
@@ -45,7 +46,8 @@
     }
 
     static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds,
-                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint)
+                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
+                      jint destDensity, jint srcDensity)
     {
         size_t chunkSize = env->GetArrayLength(chunkObj);
         void* storage = alloca(chunkSize);
@@ -56,13 +58,32 @@
             Res_png_9patch* chunk = static_cast<Res_png_9patch*>(storage);
             assert(chunkSize == chunk->serializedSize());
             // this relies on deserialization being done in place
-            Res_png_9patch::deserialize(chunk);            
-            NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
+            Res_png_9patch::deserialize(chunk);
+            
+            if (destDensity == srcDensity || destDensity == 0
+                    || srcDensity == 0) {
+                NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
+            } else {
+                canvas->save();
+                
+                SkScalar scale = SkFloatToScalar(destDensity / (float)srcDensity);
+                canvas->translate(bounds.fLeft, bounds.fTop);
+                canvas->scale(scale, scale);
+    
+                bounds.fRight = SkScalarDiv(bounds.fRight-bounds.fLeft, scale);
+                bounds.fBottom = SkScalarDiv(bounds.fBottom-bounds.fTop, scale);
+                bounds.fLeft = bounds.fTop = 0;
+    
+                NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
+    
+                canvas->restore();
+            }
         }
     } 
 
     static void drawF(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRectF,
-                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint)
+                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
+                      jint destDensity, jint srcDensity)
     {
         SkASSERT(canvas);
         SkASSERT(boundsRectF);
@@ -73,11 +94,12 @@
         SkRect      bounds;
         GraphicsJNI::jrectf_to_rect(env, boundsRectF, &bounds);
 
-        draw(env, canvas, bounds, bitmap, chunkObj, paint);
+        draw(env, canvas, bounds, bitmap, chunkObj, paint, destDensity, srcDensity);
     }
  
     static void drawI(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRect,
-                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint)
+                      const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
+                      jint destDensity, jint srcDensity)
     {
         SkASSERT(canvas);
         SkASSERT(boundsRect);
@@ -87,7 +109,7 @@
 
         SkRect      bounds;
         GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
-        draw(env, canvas, bounds, bitmap, chunkObj, paint);
+        draw(env, canvas, bounds, bitmap, chunkObj, paint, destDensity, srcDensity);
     }
     
     static jint getTransparentRegion(JNIEnv* env, jobject,
@@ -126,8 +148,8 @@
 static JNINativeMethod gNinePatchMethods[] = {
     { "isNinePatchChunk", "([B)Z",                      (void*)SkNinePatchGlue::isNinePatchChunk   },
     { "validateNinePatchChunk", "(I[B)V",               (void*)SkNinePatchGlue::validateNinePatchChunk   },
-    { "nativeDraw", "(ILandroid/graphics/RectF;I[BI)V", (void*)SkNinePatchGlue::drawF   },
-    { "nativeDraw", "(ILandroid/graphics/Rect;I[BI)V",  (void*)SkNinePatchGlue::drawI   },
+    { "nativeDraw", "(ILandroid/graphics/RectF;I[BIII)V", (void*)SkNinePatchGlue::drawF   },
+    { "nativeDraw", "(ILandroid/graphics/Rect;I[BIII)V",  (void*)SkNinePatchGlue::drawI   },
     { "nativeGetTransparentRegion", "(I[BLandroid/graphics/Rect;)I", 
                                                         (void*)SkNinePatchGlue::getTransparentRegion   }
 };
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index bbb3a7d..0d6137b 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"K souboru nelze získat přístup."</string>
     <string name="httpErrorFileNotFound">"Požadovaný soubor nebyl nalezen."</string>
     <string name="httpErrorTooManyRequests">"Je zpracováváno příliš mnoho požadavků. Opakujte akci později."</string>
-    <string name="certificateSaved">"Certifikát je uložen v systémovém úložišti klíčů."</string>
     <string name="contentServiceSync">"Synchronizace"</string>
     <string name="contentServiceSyncNotificationTitle">"Synchronizace"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Příliš mnoho smazaných položek služby <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index cb8fa78..4add1f8 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Der kunne ikke oprettes adgang til filen."</string>
     <string name="httpErrorFileNotFound">"Den anmodede fil blev ikke fundet."</string>
     <string name="httpErrorTooManyRequests">"Der behandles for mange anmodninger. Prøv igen senere."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Synkroniser"</string>
     <string name="contentServiceSyncNotificationTitle">"Synkroniser"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"For mange <xliff:g id="CONTENT_TYPE">%s</xliff:g> sletninger"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 51de385..9163c61 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"Auf die Datei konnte nicht zugegriffen werden."</string>
     <string name="httpErrorFileNotFound">"Die angeforderte Datei wurde nicht gefunden."</string>
     <string name="httpErrorTooManyRequests">"Es werden zurzeit zu viele Anfragen verarbeitet. Versuchen Sie es später erneut."</string>
-    <string name="certificateSaved">"Das Zertifikat wird im Schlüsselspeicher des Systems gespeichert."</string>
     <string name="contentServiceSync">"Synchronisieren"</string>
     <string name="contentServiceSyncNotificationTitle">"Synchronisieren"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Zu viele <xliff:g id="CONTENT_TYPE">%s</xliff:g> gelöscht."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 723ab03..3158a37 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Η πρόσβαση στο αρχείο δεν ήταν δυνατή."</string>
     <string name="httpErrorFileNotFound">"Το αρχείο που ζητήθηκε δεν βρέθηκε."</string>
     <string name="httpErrorTooManyRequests">"Πραγματοποιείται επεξεργασία πάρα πολλών αιτημάτων. Προσπαθήστε ξανά αργότερα."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Συγχρονισμός"</string>
     <string name="contentServiceSyncNotificationTitle">"Συγχρονισμός"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Πάρα πολλές <xliff:g id="CONTENT_TYPE">%s</xliff:g> διαγραφές."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index d127f9c..ee28403 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"No se ha podido acceder al archivo."</string>
     <string name="httpErrorFileNotFound">"No se ha encontrado el archivo solicitado."</string>
     <string name="httpErrorTooManyRequests">"Se están procesando demasiadas solicitudes. Vuelve a intentarlo más tarde."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Sincronización"</string>
     <string name="contentServiceSyncNotificationTitle">"Sincronización"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Demasiadas eliminaciones de <xliff:g id="CONTENT_TYPE">%s</xliff:g>"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 47bdd53..f3ff316 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"No se ha podido acceder al archivo."</string>
     <string name="httpErrorFileNotFound">"No se ha encontrado el archivo solicitado."</string>
     <string name="httpErrorTooManyRequests">"Se están procesando demasiadas solicitudes. Vuelve a intentarlo más tarde."</string>
-    <string name="certificateSaved">"El certificado se guarda en el almacén de claves del sistema."</string>
     <string name="contentServiceSync">"Sincronización"</string>
     <string name="contentServiceSyncNotificationTitle">"Sincronización"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Demasiadas eliminaciones de <xliff:g id="CONTENT_TYPE">%s</xliff:g>"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4c1af4c..ae3c807 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"Impossible d\'accéder au fichier."</string>
     <string name="httpErrorFileNotFound">"Le fichier demandé est introuvable."</string>
     <string name="httpErrorTooManyRequests">"Trop de requêtes sont en cours de traitement. Veuillez réessayer ultérieurement."</string>
-    <string name="certificateSaved">"Le certificat est enregistré dans le magasin de clés du système."</string>
     <string name="contentServiceSync">"Synchroniser"</string>
     <string name="contentServiceSyncNotificationTitle">"Synchronisation"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Trop de contenus supprimés (<xliff:g id="CONTENT_TYPE">%s</xliff:g>)."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index e05fdb1..778faac 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"Impossibile accedere al file."</string>
     <string name="httpErrorFileNotFound">"Impossibile trovare il file richiesto."</string>
     <string name="httpErrorTooManyRequests">"Troppe richieste in fase di elaborazione. Riprova più tardi."</string>
-    <string name="certificateSaved">"Il certificato viene salvato nell\'archivio chiavi del sistema."</string>
     <string name="contentServiceSync">"Sinc"</string>
     <string name="contentServiceSyncNotificationTitle">"Sincronizzazione"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Troppe eliminazioni di <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 75ab0e8..4ad87d7 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"ファイルにアクセスできませんでした。"</string>
     <string name="httpErrorFileNotFound">"要求されたファイルが見つかりませんでした。"</string>
     <string name="httpErrorTooManyRequests">"処理中のリクエストが多すぎます。しばらくしてからもう一度試してください。"</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"同期"</string>
     <string name="contentServiceSyncNotificationTitle">"同期"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"<xliff:g id="CONTENT_TYPE">%s</xliff:g>での削除が多すぎます。"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 099f19c..c3a9c70 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"파일에 액세스할 수 없습니다."</string>
     <string name="httpErrorFileNotFound">"요청한 파일을 찾을 수 없습니다."</string>
     <string name="httpErrorTooManyRequests">"처리 중인 요청이 너무 많습니다. 잠시 후에 다시 시도해 주세요."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"동기화"</string>
     <string name="contentServiceSyncNotificationTitle">"동기화"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"<xliff:g id="CONTENT_TYPE">%s</xliff:g> 삭제가 너무 많습니다."</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 875b4bc..dff943c 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Kunne ikke åpne filen."</string>
     <string name="httpErrorFileNotFound">"Fant ikke den forespurte filen."</string>
     <string name="httpErrorTooManyRequests">"For mange forespørsler blir behandlet. Prøv igjen senere."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Synkronisering"</string>
     <string name="contentServiceSyncNotificationTitle">"Synkronisering"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"For mange slettinger av <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5aa1615..2bbd02d 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"Het bestand kan niet worden geopend."</string>
     <string name="httpErrorFileNotFound">"Het opgevraagde bestand is niet gevonden."</string>
     <string name="httpErrorTooManyRequests">"Er worden te veel aanvragen verwerkt. Probeer het later opnieuw."</string>
-    <string name="certificateSaved">"Het certificaat is opgeslagen in de opslagruimte voor sleutels van het systeem."</string>
     <string name="contentServiceSync">"Synchroniseren"</string>
     <string name="contentServiceSyncNotificationTitle">"Synchroniseren"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Te veel verwijderen voor <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 6c65869..3f7921d 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"Nie można uzyskać dostępu do pliku."</string>
     <string name="httpErrorFileNotFound">"Nie znaleziono żądanego pliku."</string>
     <string name="httpErrorTooManyRequests">"Zbyt wiele żądań jest przetwarzanych. Spróbuj ponownie później."</string>
-    <string name="certificateSaved">"Certyfikat jest zapisywany w magazynie kluczy systemu."</string>
     <string name="contentServiceSync">"Synchronizacja"</string>
     <string name="contentServiceSyncNotificationTitle">"Synchronizuj"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Zbyt wiele usuwanych <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 313347b..5b75aad 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Não foi possível aceder ao ficheiro."</string>
     <string name="httpErrorFileNotFound">"Não foi possível localizar o ficheiro pedido."</string>
     <string name="httpErrorTooManyRequests">"Existem demasiados pedidos em processamento. Tente novamente mais tarde."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Sincronização"</string>
     <string name="contentServiceSyncNotificationTitle">"Sincronização"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Demasiadas eliminações de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 214a0ea..4f84872 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Não foi possível acessar o arquivo."</string>
     <string name="httpErrorFileNotFound">"O arquivo solicitado não foi encontrado."</string>
     <string name="httpErrorTooManyRequests">"Há muitas solicitações sendo processadas. Tente novamente mais tarde."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Sincronizar"</string>
     <string name="contentServiceSyncNotificationTitle">"Sincronizar"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Muitas exclusões de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 1078809..22120f6 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Не удается получить доступ к файлу."</string>
     <string name="httpErrorFileNotFound">"Не удалось найти указанные файлы."</string>
     <string name="httpErrorTooManyRequests">"Обрабатывается слишком много запросов. Повторите попытку позднее."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Синхр."</string>
     <string name="contentServiceSyncNotificationTitle">"Синхр."</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Слишком много удалений <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 567932f..40d2500 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Det gick inte att komma åt filen."</string>
     <string name="httpErrorFileNotFound">"Den begärda filen hittades inte."</string>
     <string name="httpErrorTooManyRequests">"För många begäranden bearbetas. Försök igen senare."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Synkronisera"</string>
     <string name="contentServiceSyncNotificationTitle">"Synkronisera"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"För många <xliff:g id="CONTENT_TYPE">%s</xliff:g>-borttagningar."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index ecf7e41..bda67c7 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"Dosyaya erişilemedi."</string>
     <string name="httpErrorFileNotFound">"İstenen dosya bulunamadı."</string>
     <string name="httpErrorTooManyRequests">"Çok fazla sayıda istek işleniyor. Daha sonra yeniden deneyin."</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"Senk."</string>
     <string name="contentServiceSyncNotificationTitle">"Senk."</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"Çok fazla <xliff:g id="CONTENT_TYPE">%s</xliff:g> silme var."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 0c651c9..6741b3b 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -134,8 +134,6 @@
     <string name="httpErrorFile">"无法访问该文件。"</string>
     <string name="httpErrorFileNotFound">"找不到请求的文件。"</string>
     <string name="httpErrorTooManyRequests">"正在处理的请求太多,请稍后重试。"</string>
-    <!-- no translation found for certificateSaved (2832076323378077191) -->
-    <skip />
     <string name="contentServiceSync">"同步"</string>
     <string name="contentServiceSyncNotificationTitle">"同步"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"太多<xliff:g id="CONTENT_TYPE">%s</xliff:g>删除项。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index a611532..f355a71 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -111,7 +111,6 @@
     <string name="httpErrorFile">"無法存取此檔案。"</string>
     <string name="httpErrorFileNotFound">"找不到要求的檔案。"</string>
     <string name="httpErrorTooManyRequests">"太多執行要求。請稍後再試一次。"</string>
-    <string name="certificateSaved">"憑證已儲存在系統的金鑰存放區。"</string>
     <string name="contentServiceSync">"同步處理"</string>
     <string name="contentServiceSyncNotificationTitle">"同步處理"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc">"同時刪除太多 <xliff:g id="CONTENT_TYPE">%s</xliff:g>。"</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d9fec3d..0e848398 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -228,8 +228,6 @@
     <string name="httpErrorFileNotFound">The requested file was not found.</string>
     <!-- Displayed when a request failed because there are too many requests right now. -->
     <string name="httpErrorTooManyRequests">Too many requests are being processed. Try again later.</string>
-    <!-- Displayed a toast that a certificate is saved in the keystore -->
-    <string name="certificateSaved">The certificate is saved in the system\'s key store.</string>
 
     <!-- Account notifications --> <skip />
     <!-- A notification is shown when the AccountManager is unable to
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index df659ef..bb19229 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -30,11 +30,11 @@
     /**
      * Indicates that the bitmap was created for an unknown pixel density.
      *
-     * @see Bitmap#getDensityScale()
-     * @see Bitmap#setDensityScale(float)
+     * @see Bitmap#getDensity()
+     * @see Bitmap#setDensity(int)
      */
-    public static final float DENSITY_SCALE_UNKNOWN = -1.0f;
-
+    public static final int DENSITY_NONE = 0;
+    
     // Note:  mNativeBitmap is used by FaceDetector_jni.cpp
     // Don't change/rename without updating FaceDetector_jni.cpp
     private final int mNativeBitmap;
@@ -45,10 +45,10 @@
     private int mHeight = -1;
     private boolean mRecycled;
 
-    private static volatile Matrix sScaleMatrix;
+    // Package-scoped for fast access.
+    /*package*/ int mDensity = DENSITY_NONE;
 
-    private float mDensityScale = DENSITY_SCALE_UNKNOWN;
-    private boolean mAutoScaling;
+    private static volatile Matrix sScaleMatrix;
 
     /**
      * @noinspection UnusedDeclaration
@@ -70,84 +70,39 @@
     }
 
     /**
-     * <p>Returns the density scale for this bitmap, expressed as a factor of
-     * the default density (160.) For instance, a bitmap designed for
-     * displays with a density of 240 will have a density scale of 1.5 whereas a bitmap
-     * designed for a density of 160 will have a density scale of 1.0.</p>
+     * <p>Returns the density for this bitmap.</p>
      *
-     * <p>The default density scale is {@link #DENSITY_SCALE_UNKNOWN}.</p>
+     * <p>The default density scale is {@link #DENSITY_NONE}.</p>
      *
-     * @return A scaling factor of the default density (160) or {@link #DENSITY_SCALE_UNKNOWN}
+     * @return A scaling factor of the default density (160) or {@link #DENSITY_NONE}
      *         if the scaling factor is unknown.
      *
-     * @see #setDensityScale(float)
-     * @see #isAutoScalingEnabled()
-     * @see #setAutoScalingEnabled(boolean)
+     * @see #setDensity(int)
      * @see android.util.DisplayMetrics#DENSITY_DEFAULT
-     * @see android.util.DisplayMetrics#density
-     * @see #DENSITY_SCALE_UNKNOWN
+     * @see android.util.DisplayMetrics#densityDpi
+     * @see #DENSITY_NONE
      */
-    public float getDensityScale() {
-        return mDensityScale;
+    public int getDensity() {
+        return mDensity;
     }
 
     /**
-     * <p>Specifies the density scale for this bitmap, expressed as a factor of
-     * the default density (160.) For instance, a bitmap designed for
-     * displays with a density of 240 will have a density scale of 1.5 whereas a bitmap
-     * designed for a density of 160 will have a density scale of 1.0.</p>
+     * <p>Specifies the density for this bitmap.  When the bitmap is
+     * drawn to a Canvas that also has a density, it will be scaled
+     * appropriately.</p>
      *
-     * @param densityScale The density scaling factor to use with this bitmap or
-     *        {@link #DENSITY_SCALE_UNKNOWN} if the factor is unknown.
+     * @param density The density scaling factor to use with this bitmap or
+     *        {@link #DENSITY_NONE} if the density is unknown.
      *
-     * @see #getDensityScale()
-     * @see #isAutoScalingEnabled()
-     * @see #setAutoScalingEnabled(boolean)
+     * @see #getDensity()
      * @see android.util.DisplayMetrics#DENSITY_DEFAULT
-     * @see android.util.DisplayMetrics#density
-     * @see #DENSITY_SCALE_UNKNOWN
+     * @see android.util.DisplayMetrics#densityDpi
+     * @see #DENSITY_NONE
      */
-    public void setDensityScale(float densityScale) {
-        mDensityScale = densityScale;
+    public void setDensity(int density) {
+        mDensity = density;
     }
-
-    /**
-     * </p>Indicates whether this bitmap will be automatically be scaled at the
-     * target's density at drawing time. If auto scaling is enabled, this bitmap
-     * will be drawn with the following scale factor:</p>
-     *
-     * <pre>scale = (bitmap density scale factor) / (target density scale factor)</pre>
-     *
-     * <p>Auto scaling is turned off by default. If auto scaling is enabled but the
-     * bitmap has an unknown density scale, then the bitmap will never be automatically
-     * scaled at drawing time.</p>
-     *
-     * @return True if the bitmap must be scaled at drawing time, false otherwise.
-     *
-     * @see #setAutoScalingEnabled(boolean)
-     * @see #getDensityScale()
-     * @see #setDensityScale(float)
-     */
-    public boolean isAutoScalingEnabled() {
-        return mAutoScaling;
-    }
-
-    /**
-     * <p>Enables or disables auto scaling for this bitmap. When auto scaling is enabled,
-     * the bitmap will be scaled at drawing time to accomodate the drawing target's pixel
-     * density. The final scale factor for this bitmap is thus defined:</p>
-     *
-     * <pre>scale = (bitmap density scale factor) / (target density scale factor)</pre>
-     *
-     * <p>If auto scaling is enabled but the bitmap has an unknown density scale, then
-     * the bitmap will never be automatically scaled at drawing time.</p>
-     *
-     * @param autoScalingEnabled True to scale the bitmap at drawing time, false otherwise.
-     */
-    public void setAutoScalingEnabled(boolean autoScalingEnabled) {
-        mAutoScaling = autoScalingEnabled;
-    }
-
+    
     /**
      * Sets the nine patch chunk.
      *
@@ -455,9 +410,8 @@
         canvas.drawBitmap(source, srcR, dstR, paint);
 
         // The new bitmap was created from a known bitmap source so assume that
-        // they use the same density scale
-        bitmap.mDensityScale = source.mDensityScale;
-        bitmap.mAutoScaling = source.mAutoScaling;
+        // they use the same density
+        bitmap.mDensity = source.mDensity;
 
         return bitmap;
     }
@@ -603,65 +557,71 @@
     }
 
     /**
-     * Convenience method that returns the width of this bitmap divided
-     * by the density scale factor.
-     *
-     * @param canvas The Canvas the bitmap will be drawn to.
-     * @return The scaled width of this bitmap, according to the density scale factor.
+     * Convenience for calling {@link #getScaledWidth(int)} with the target
+     * density of the given {@link Canvas}.
      */
     public int getScaledWidth(Canvas canvas) {
-        final float scale = mDensityScale;
-        if (!mAutoScaling || scale < 0) {
-            return getWidth();
-        }
-        return (int)(getWidth() * canvas.getDensityScale() / scale);
+        return scaleFromDensity(getWidth(), mDensity, canvas.mDensity);
     }
 
     /**
-     * Convenience method that returns the height of this bitmap divided
-     * by the density scale factor.
-     *
-     * @param canvas The Canvas the bitmap will be drawn to.
-     * @return The scaled height of this bitmap, according to the density scale factor.
+     * Convenience for calling {@link #getScaledHeight(int)} with the target
+     * density of the given {@link Canvas}.
      */
     public int getScaledHeight(Canvas canvas) {
-        final float scale = mDensityScale;
-        if (!mAutoScaling || scale < 0) {
-            return getHeight();
-        }
-        return (int)(getHeight() * canvas.getDensityScale() / scale);
+        return scaleFromDensity(getHeight(), mDensity, canvas.mDensity);
+    }
+
+    /**
+     * Convenience for calling {@link #getScaledWidth(int)} with the target
+     * density of the given {@link DisplayMetrics}.
+     */
+    public int getScaledWidth(DisplayMetrics metrics) {
+        return scaleFromDensity(getWidth(), mDensity, metrics.densityDpi);
+    }
+
+    /**
+     * Convenience for calling {@link #getScaledHeight(int)} with the target
+     * density of the given {@link DisplayMetrics}.
+     */
+    public int getScaledHeight(DisplayMetrics metrics) {
+        return scaleFromDensity(getHeight(), mDensity, metrics.densityDpi);
     }
 
     /**
      * Convenience method that returns the width of this bitmap divided
      * by the density scale factor.
      *
-     * @param metrics The target display metrics.
+     * @param targetDensity The density of the target canvas of the bitmap.
      * @return The scaled width of this bitmap, according to the density scale factor.
      */
-    public int getScaledWidth(DisplayMetrics metrics) {
-        final float scale = mDensityScale;
-        if (!mAutoScaling || scale < 0) {
-            return getWidth();
-        }
-        return (int)(getWidth() * metrics.density / scale);
+    public int getScaledWidth(int targetDensity) {
+        return scaleFromDensity(getWidth(), mDensity, targetDensity);
     }
 
     /**
      * Convenience method that returns the height of this bitmap divided
      * by the density scale factor.
      *
-     * @param metrics The target display metrics.
+     * @param targetDensity The density of the target canvas of the bitmap.
      * @return The scaled height of this bitmap, according to the density scale factor.
      */
-    public int getScaledHeight(DisplayMetrics metrics) {
-        final float scale = mDensityScale;
-        if (!mAutoScaling || scale < 0) {
-            return getHeight();
-        }
-        return (int)(getHeight() * metrics.density / scale);
+    public int getScaledHeight(int targetDensity) {
+        return scaleFromDensity(getHeight(), mDensity, targetDensity);
     }
-
+    
+    /**
+     * @hide
+     */
+    static public int scaleFromDensity(int size, int sdensity, int tdensity) {
+        if (sdensity == DENSITY_NONE || sdensity == tdensity) {
+            return size;
+        }
+        
+        // Scale by tdensity / sdensity, rounding up.
+        return ( (size * tdensity) + (sdensity >> 1) ) / sdensity;
+    }
+    
     /**
      * Return the number of bytes between rows in the bitmap's pixels. Note that
      * this refers to the pixels as stored natively by the bitmap. If you call
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 975bc1a..076cd0c 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -40,7 +40,6 @@
          */
         public Options() {
             inDither = true;
-            inDensity = 0;
             inScaled = true;
         }
 
@@ -80,22 +79,87 @@
         public boolean inDither;
 
         /**
-         * The desired pixel density of the bitmap.
+         * The pixel density to use for the bitmap.  This will always result
+         * in the returned bitmap having a density set for it (see
+         * {@link Bitmap#setDensity(int) Bitmap.setDensity(int)).  In addition,
+         * if {@link #inScaled} is set (which it is by default} and this
+         * density does not match {@link #inTargetDensity}, then the bitmap
+         * will be scaled to the target density before being returned.
+         * 
+         * <p>If this is 0,
+         * {@link BitmapFactory#decodeResource(Resources, int)}, 
+         * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
+         * and {@link BitmapFactory#decodeResourceStream}
+         * will fill in the density associated with the resource.  The other
+         * functions will leave it as-is and no density will be applied.
          *
-         * @see android.util.DisplayMetrics#DENSITY_DEFAULT
-         * @see android.util.DisplayMetrics#density
+         * @see #inTargetDensity
+         * @see #inScreenDensity
+         * @see #inScaled
+         * @see Bitmap#setDensity(int)
+         * @see android.util.DisplayMetrics#densityDpi
          */
         public int inDensity;
 
         /**
-         * </p>If the bitmap is loaded from {@link android.content.res.Resources} and
-         * this flag is turned on, the bitmap will be scaled to match the default
-         * display's pixel density.</p>
+         * The pixel density of the destination this bitmap will be drawn to.
+         * This is used in conjunction with {@link #inDensity} and
+         * {@link #inScaled} to determine if and how to scale the bitmap before
+         * returning it.
+         * 
+         * <p>If this is 0,
+         * {@link BitmapFactory#decodeResource(Resources, int)}, 
+         * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
+         * and {@link BitmapFactory#decodeResourceStream}
+         * will fill in the density associated the Resources object's
+         * DisplayMetrics.  The other
+         * functions will leave it as-is and no scaling for density will be
+         * performed.
+         * 
+         * @see #inDensity
+         * @see #inScreenDensity
+         * @see #inScaled
+         * @see android.util.DisplayMetrics#densityDpi
+         */
+        public int inTargetDensity;
+        
+        /**
+         * The pixel density of the actual screen that is being used.  This is
+         * purely for applications running in density compatibility code, where
+         * {@link #inTargetDensity} is actually the density the application
+         * sees rather than the real screen density.
+         * 
+         * <p>By setting this, you
+         * allow the loading code to avoid scaling a bitmap that is currently
+         * in the screen density up/down to the compatibility density.  Instead,
+         * if {@link #inDensity} is the same as {@link #inScreenDensity}, the
+         * bitmap will be left as-is.  Anything using the resulting bitmap
+         * must also used {@link Bitmap#getScaledWidth(int)
+         * Bitmap.getScaledWidth} and {@link Bitmap#getScaledHeight
+         * Bitmap.getScaledHeight} to account for any different between the
+         * bitmap's density and the target's density.
+         * 
+         * <p>This is never set automatically for the caller by
+         * {@link BitmapFactory} itself.  It must be explicitly set, since the
+         * caller must deal with the resulting bitmap in a density-aware way.
+         * 
+         * @see #inDensity
+         * @see #inTargetDensity
+         * @see #inScaled
+         * @see android.util.DisplayMetrics#densityDpi
+         */
+        public int inScreenDensity;
+        
+        /**
+         * When this flag is set, if {@link #inDensity} and
+         * {@link #inTargetDensity} are not 0, the
+         * bitmap will be scaled to match {@link #inTargetDensity} when loaded,
+         * rather than relying on the graphics system scaling it each time it
+         * is drawn to a Canvas.
          *
-         * </p>This flag is turned on by default and should be turned off if you need
-         * a non-scaled version of the bitmap. In this case,
-         * {@link android.graphics.Bitmap#setAutoScalingEnabled(boolean)} can be used
-         * to properly scale the bitmap at drawing time.</p>
+         * <p>This flag is turned on by default and should be turned off if you need
+         * a non-scaled version of the bitmap.  Nine-patch bitmaps ignore this
+         * flag and are always scaled.
          */
         public boolean inScaled;
 
@@ -236,58 +300,32 @@
      * Decode a new Bitmap from an InputStream. This InputStream was obtained from
      * resources, which we pass to be able to scale the bitmap accordingly.
      */
-    public static Bitmap decodeStream(Resources res, TypedValue value, InputStream is,
-            Rect pad, Options opts) {
+    public static Bitmap decodeResourceStream(Resources res, TypedValue value,
+            InputStream is, Rect pad, Options opts) {
 
         if (opts == null) {
             opts = new Options();
         }
 
-        Bitmap bm = decodeStream(is, pad, opts);
-
-        if (bm != null && res != null && value != null) {
+        if (opts.inDensity == 0 && value != null) {
             final int density = value.density;
-            if (density == TypedValue.DENSITY_NONE) {
-                return bm;
-            }
-            
-            byte[] np = bm.getNinePatchChunk();
-            final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
-
-            if (opts.inDensity == 0) {
-                opts.inDensity = density == TypedValue.DENSITY_DEFAULT ?
-                        DisplayMetrics.DENSITY_DEFAULT : density;
-            }
-            float scale = opts.inDensity / (float) DisplayMetrics.DENSITY_DEFAULT;
-
-            if (opts.inScaled || isNinePatch) {
-                bm.setDensityScale(1.0f);
-                bm.setAutoScalingEnabled(false);
-                // Assume we are going to prescale for the screen
-                scale = res.getDisplayMetrics().density / scale;
-                if (scale != 1.0f) {
-                    // TODO: This is very inefficient and should be done in native by Skia
-                    final Bitmap oldBitmap = bm;
-                    bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f),
-                            (int) (bm.getHeight() * scale + 0.5f), true);
-                    oldBitmap.recycle();
-
-                    if (isNinePatch) {
-                        np = nativeScaleNinePatch(np, scale, pad);
-                        bm.setNinePatchChunk(np);
-                    }
-                }
-            } else {
-                bm.setDensityScale(scale);
-                bm.setAutoScalingEnabled(true);
+            if (density == TypedValue.DENSITY_DEFAULT) {
+                opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
+            } else if (density != TypedValue.DENSITY_NONE) {
+                opts.inDensity = density;
             }
         }
-
-        return bm;
+        
+        if (opts.inTargetDensity == 0 && res != null) {
+            opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
+        }
+        
+        return decodeStream(is, pad, opts);
     }
 
     /**
-     * Decode an image referenced by a resource ID.
+     * Synonym for opening the given resource and calling
+     * {@link #decodeResourceStream}.
      *
      * @param res   The resources object containing the image data
      * @param id The resource id of the image data
@@ -304,7 +342,7 @@
             final TypedValue value = new TypedValue();
             final InputStream is = res.openRawResource(id, value);
 
-            bm = decodeStream(res, value, is, null, opts);
+            bm = decodeResourceStream(res, value, is, null, opts);
             is.close();
         } catch (java.io.IOException e) {
             /*  do nothing.
@@ -316,7 +354,8 @@
     }
 
     /**
-     * Decode an image referenced by a resource ID.
+     * Synonym for {@link #decodeResource(Resources, int, android.graphics.BitmapFactory.Options)}
+     * will null Options.
      *
      * @param res The resources object containing the image data
      * @param id The resource id of the image data
@@ -413,6 +452,39 @@
             bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
         }
 
+        if (bm == null || opts == null) {
+            return bm;
+        }
+        
+        final int density = opts.inDensity;
+        if (density == 0) {
+            return bm;
+        }
+        
+        bm.setDensity(density);
+        final int targetDensity = opts.inTargetDensity;
+        if (targetDensity == 0 || density == targetDensity
+                || density == opts.inScreenDensity) {
+            return bm;
+        }
+        
+        byte[] np = bm.getNinePatchChunk();
+        final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
+        if (opts.inScaled || isNinePatch) {
+            float scale = targetDensity / (float)density;
+            // TODO: This is very inefficient and should be done in native by Skia
+            final Bitmap oldBitmap = bm;
+            bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f),
+                    (int) (bm.getHeight() * scale + 0.5f), true);
+            oldBitmap.recycle();
+
+            if (isNinePatch) {
+                np = nativeScaleNinePatch(np, scale, outPadding);
+                bm.setNinePatchChunk(np);
+            }
+            bm.setDensity(targetDensity);
+        }
+        
         return bm;
     }
 
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index da73597..8ecbfbd 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -20,6 +20,7 @@
 import android.text.SpannedString;
 import android.text.SpannableString;
 import android.text.GraphicsOperations;
+import android.util.DisplayMetrics;
 
 import javax.microedition.khronos.opengles.GL;
 
@@ -47,11 +48,12 @@
     // optional field set by the caller
     private DrawFilter  mDrawFilter;
 
+    // Package-scoped for quick access.
+    /*package*/ int mDensity = DisplayMetrics.DENSITY_DEFAULT;
+    
     // Used by native code
     @SuppressWarnings({"UnusedDeclaration"})
     private int         mSurfaceFormat;
-    @SuppressWarnings({"UnusedDeclaration"})
-    private float       mDensityScale = 1.0f;
 
     /**
      * Construct an empty raster canvas. Use setBitmap() to specify a bitmap to
@@ -76,8 +78,9 @@
         throwIfRecycled(bitmap);
         mNativeCanvas = initRaster(bitmap.ni());
         mBitmap = bitmap;
-        mDensityScale = bitmap.getDensityScale();
-        if (mDensityScale == Bitmap.DENSITY_SCALE_UNKNOWN) mDensityScale = 1.0f;
+        final int density = bitmap.mDensity;
+        mDensity = density == Bitmap.DENSITY_NONE
+                ? DisplayMetrics.DENSITY_DEFAULT : density;
     }
     
     /*package*/ Canvas(int nativeCanvas) {
@@ -132,8 +135,9 @@
 
         native_setBitmap(mNativeCanvas, bitmap.ni());
         mBitmap = bitmap;
-        mDensityScale = bitmap.getDensityScale();
-        if (mDensityScale == Bitmap.DENSITY_SCALE_UNKNOWN) mDensityScale = 1.0f;
+        final int density = bitmap.mDensity;
+        mDensity = density == Bitmap.DENSITY_NONE
+                ? DisplayMetrics.DENSITY_DEFAULT : density;
     }
     
     /**
@@ -172,44 +176,34 @@
     public native int getHeight();
 
     /**
-     * <p>Returns the density scale for this Canvas' backing bitmap, expressed as a
-     * factor of the default density (160dpi.) For instance, a bitmap designed for
-     * 240dpi displays will have a density scale of 1.5 whereas a bitmap
-     * designed for 160dpi will have a density scale of 1.0.</p>
+     * <p>Returns the density for this Canvas' backing bitmap.</p>
      *
-     * <p>The default density scale is {@link Bitmap#DENSITY_SCALE_UNKNOWN}.</p>
+     * <p>The default density scale is {@link Bitmap#DENSITY_NONE}.</p>
      *
      * @return A scaling factor of the default density (160dpi) or
-     *        {@link Bitmap#DENSITY_SCALE_UNKNOWN} if the scaling factor is unknown.
+     *        {@link Bitmap#DENSITY_NONE} if the scaling factor is unknown.
      *
-     * @see #setDensityScale(float)
-     * @see Bitmap#getDensityScale() 
+     * @see #setDensity(int)
+     * @see Bitmap#getDensity() 
      */
-    public float getDensityScale() {
-        if (mBitmap != null) {
-            return mBitmap.getDensityScale();
-        }
-        return mDensityScale;
+    public int getDensity() {
+        return mDensity;
     }
 
     /**
-     * <p>Specifies the density scale for this Canvas' backing bitmap, expressed as a
-     * factor of the default density (160dpi.) For instance, a bitmap designed for
-     * 240dpi displays will have a density scale of 1.5 whereas a bitmap
-     * designed for 160dpi will have a density scale of 1.0.</p>
+     * <p>Specifies the density for this Canvas' backing bitmap.
      *
-     * @param densityScale The density scaling factor to use with this bitmap or
-     *        {@link Bitmap#DENSITY_SCALE_UNKNOWN} if the factor is unknown.
+     * @param density The density scaling factor to use with this bitmap or
+     *        {@link Bitmap#DENSITY_NONE} if the factor is unknown.
      *
-     * @see #getDensityScale()
-     * @see Bitmap#setDensityScale(float) 
+     * @see #getDensity()
+     * @see Bitmap#setDensity(int) 
      */
-    public void setDensityScale(float densityScale) {
+    public void setDensity(int density) {
         if (mBitmap != null) {
-            mBitmap.setDensityScale(densityScale);
+            mBitmap.setDensity(density);
         }
-        mDensityScale = densityScale;
-        if (mDensityScale == Bitmap.DENSITY_SCALE_UNKNOWN) mDensityScale = 1.0f;
+        mDensity = density;
     }
 
     // the SAVE_FLAG constants must match their native equivalents
@@ -945,12 +939,17 @@
     /**
      * Draw the specified bitmap, with its top/left corner at (x,y), using
      * the specified paint, transformed by the current matrix.
-     * Note: if the paint contains a maskfilter that generates a mask which
+     * 
+     * <p>Note: if the paint contains a maskfilter that generates a mask which
      * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
      * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
      * Thus the color outside of the original width/height will be the edge
      * color replicated.
      *
+     * <p>If the bitmap and canvas have different densities, this function
+     * will take care of automatically scaling the bitmap to draw at the
+     * same density as the canvas.
+     * 
      * @param bitmap The bitmap to be drawn
      * @param left   The position of the left side of the bitmap being drawn
      * @param top    The position of the top side of the bitmap being drawn
@@ -959,20 +958,25 @@
     public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
         throwIfRecycled(bitmap);
         native_drawBitmap(mNativeCanvas, bitmap.ni(), left, top,
-                paint != null ? paint.mNativePaint : 0, bitmap.isAutoScalingEnabled(),
-                bitmap.getDensityScale());
+                paint != null ? paint.mNativePaint : 0, mDensity, bitmap.mDensity);
     }
 
     /**
      * Draw the specified bitmap, scaling/translating automatically to fill
      * the destination rectangle. If the source rectangle is not null, it
      * specifies the subset of the bitmap to draw.
-     * Note: if the paint contains a maskfilter that generates a mask which
+     * 
+     * <p>Note: if the paint contains a maskfilter that generates a mask which
      * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
      * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
      * Thus the color outside of the original width/height will be the edge
      * color replicated.
      *
+     * <p>This function <em>ignores the density associated with the bitmap</em>.
+     * This is because the source and destination rectangle coordinate
+     * spaces are in their respective densities, so must already have the
+     * appropriate scaling factor applied.
+     * 
      * @param bitmap The bitmap to be drawn
      * @param src    May be null. The subset of the bitmap to be drawn
      * @param dst    The rectangle that the bitmap will be scaled/translated
@@ -992,12 +996,18 @@
      * Draw the specified bitmap, scaling/translating automatically to fill
      * the destination rectangle. If the source rectangle is not null, it
      * specifies the subset of the bitmap to draw.
-     * Note: if the paint contains a maskfilter that generates a mask which
+     * 
+     * <p>Note: if the paint contains a maskfilter that generates a mask which
      * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
      * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
      * Thus the color outside of the original width/height will be the edge
      * color replicated.
      *
+     * <p>This function <em>ignores the density associated with the bitmap</em>.
+     * This is because the source and destination rectangle coordinate
+     * spaces are in their respective densities, so must already have the
+     * appropriate scaling factor applied.
+     * 
      * @param bitmap The bitmap to be drawn
      * @param src    May be null. The subset of the bitmap to be drawn
      * @param dst    The rectangle that the bitmap will be scaled/translated
@@ -1489,8 +1499,8 @@
                                                int paint);
     private native void native_drawBitmap(int nativeCanvas, int bitmap,
                                                  float left, float top,
-                                                 int nativePaintOrZero, boolean autoScale,
-                                                 float densityScale);
+                                                 int nativePaintOrZero,
+                                                 int canvasDensity, int bitmapDensity);
     private native void native_drawBitmap(int nativeCanvas, int bitmap,
                                                  Rect src, RectF dst,
                                                  int nativePaintOrZero);
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 778c903..88dfd67 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -68,7 +68,7 @@
     }
     
     /** 
-     * Draw a bitmap to nine patches.
+     * Draw a bitmap of nine patches.
      *
      * @param canvas    A container for the current matrix and clip used to draw the bitmap.
      * @param location  Where to draw the bitmap.
@@ -76,23 +76,25 @@
     public void draw(Canvas canvas, RectF location) {
         nativeDraw(canvas.mNativeCanvas, location,
                    mBitmap.ni(), mChunk,
-                   mPaint != null ? mPaint.mNativePaint : 0);
+                   mPaint != null ? mPaint.mNativePaint : 0,
+                   canvas.mDensity, mBitmap.mDensity);
     }
     
     /** 
-     * Draw a bitmap to nine patches.
+     * Draw a bitmap of nine patches.
      *
      * @param canvas    A container for the current matrix and clip used to draw the bitmap.
      * @param location  Where to draw the bitmap.
      */
     public void draw(Canvas canvas, Rect location) {
         nativeDraw(canvas.mNativeCanvas, location,
-                   mBitmap.ni(), mChunk,
-                   mPaint != null ? mPaint.mNativePaint : 0);
+                mBitmap.ni(), mChunk,
+                mPaint != null ? mPaint.mNativePaint : 0,
+                canvas.mDensity, mBitmap.mDensity);
     }
 
     /** 
-     * Draw a bitmap to nine patches.
+     * Draw a bitmap of nine patches.
      *
      * @param canvas    A container for the current matrix and clip used to draw the bitmap.
      * @param location  Where to draw the bitmap.
@@ -100,9 +102,18 @@
      */
     public void draw(Canvas canvas, Rect location, Paint paint) {
         nativeDraw(canvas.mNativeCanvas, location,
-                   mBitmap.ni(), mChunk, paint != null ? paint.mNativePaint : 0);
+                mBitmap.ni(), mChunk, paint != null ? paint.mNativePaint : 0,
+                canvas.mDensity, mBitmap.mDensity);
     }
 
+    /**
+     * Return the underlying bitmap's density, as per
+     * {@link Bitmap#getDensity() Bitmap.getDensity()}.
+     */
+    public int getDensity() {
+        return mBitmap.mDensity;
+    }
+    
     public int getWidth() {
         return mBitmap.getWidth();
     }
@@ -129,9 +140,11 @@
 
     private static native void validateNinePatchChunk(int bitmap, byte[] chunk);
     private static native void nativeDraw(int canvas_instance, RectF loc, int bitmap_instance,
-                                          byte[] c, int paint_instance_or_null);
+                                          byte[] c, int paint_instance_or_null,
+                                          int destDensity, int srcDensity);
     private static native void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance,
-                                          byte[] c, int paint_instance_or_null);
+                                          byte[] c, int paint_instance_or_null,
+                                          int destDensity, int srcDensity);
     private static native int nativeGetTransparentRegion(
             int bitmap, byte[] chunk, Rect location);
 }
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 5b32246..eade73a 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -63,18 +63,56 @@
 
     private boolean mApplyGravity;
     private boolean mRebuildShader;
+    private boolean mMutated;
+    
+    private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
+
+    // These are scaled to match the target density.
     private int mBitmapWidth;
     private int mBitmapHeight;
-    private boolean mMutated;
-
+    
+    /**
+     * Create an empty drawable, not dealing with density.
+     * @deprecated Use {@link #BitmapDrawable(Resources)} to ensure
+     * that the drawable has correctly set its target density.
+     */
     public BitmapDrawable() {
         mBitmapState = new BitmapState((Bitmap) null);
     }
 
+    /**
+     * Create an empty drawable, setting initial target density based on
+     * the display metrics of the resources.
+     */
+    public BitmapDrawable(Resources res) {
+        mBitmapState = new BitmapState((Bitmap) null);
+        if (res != null) {
+            setTargetDensity(res.getDisplayMetrics());
+            mBitmapState.mTargetDensity = mTargetDensity;
+        }
+    }
+
+    /**
+     * Create drawable from a bitmap, not dealing with density.
+     * @deprecated Use {@link #BitmapDrawable(Resources, Bitmap)} to ensure
+     * that the drawable has correctly set its target density.
+     */
     public BitmapDrawable(Bitmap bitmap) {
         this(new BitmapState(bitmap));
     }
 
+    /**
+     * Create drawable from a bitmap, setting initial target density based on
+     * the display metrics of the resources.
+     */
+    public BitmapDrawable(Resources res, Bitmap bitmap) {
+        this(new BitmapState(bitmap));
+        if (res != null) {
+            setTargetDensity(res.getDisplayMetrics());
+            mBitmapState.mTargetDensity = mTargetDensity;
+        }
+    }
+
     public BitmapDrawable(String filepath) {
         this(new BitmapState(BitmapFactory.decodeFile(filepath)));
         if (mBitmap == null) {
@@ -97,11 +135,15 @@
         return mBitmap;
     }
 
+    private void computeBitmapSize() {
+        mBitmapWidth = mBitmap.getScaledWidth(mTargetDensity);
+        mBitmapHeight = mBitmap.getScaledHeight(mTargetDensity);
+    }
+    
     private void setBitmap(Bitmap bitmap) {
         mBitmap = bitmap;
         if (bitmap != null) {
-            mBitmapWidth = bitmap.getWidth();
-            mBitmapHeight = bitmap.getHeight();
+            computeBitmapSize();
         } else {
             mBitmapWidth = mBitmapHeight = -1;
         }
@@ -114,13 +156,11 @@
      *
      * @param canvas The Canvas from which the density scale must be obtained.
      *
-     * @see android.graphics.Bitmap#setDensityScale(float) 
-     * @see android.graphics.Bitmap#getDensityScale()
-     *
-     * @hide pending API council approval
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
      */
-    public void setDensityScale(Canvas canvas) {
-        setDensityScale(canvas.getDensityScale());
+    public void setTargetDensity(Canvas canvas) {
+        setTargetDensity(canvas.getDensity());
     }
 
     /**
@@ -128,32 +168,33 @@
      *
      * @param metrics The DisplayMetrics indicating the density scale for this drawable.
      *
-     * @see android.graphics.Bitmap#setDensityScale(float)
-     * @see android.graphics.Bitmap#getDensityScale()
-     *
-     * @hide pending API council approval
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
      */
-    public void setDensityScale(DisplayMetrics metrics) {
-        setDensityScale(metrics.density);
+    public void setTargetDensity(DisplayMetrics metrics) {
+        mTargetDensity = metrics.densityDpi;
+        if (mBitmap != null) {
+            computeBitmapSize();
+        }
     }
 
     /**
-     * Set the density scale at which this drawable will be rendered.
+     * Set the density at which this drawable will be rendered.
      *
      * @param density The density scale for this drawable.
      *
-     * @see android.graphics.Bitmap#setDensityScale(float)
-     * @see android.graphics.Bitmap#getDensityScale()
-     *
-     * @hide pending API council approval
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
      */
-    public void setDensityScale(float density) {
-        density = (density == Bitmap.DENSITY_SCALE_UNKNOWN ? 1.0f : density);
-        mBitmapState.mTargetDensityScale = density;
+    public void setTargetDensity(int density) {
+        mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
+        if (mBitmap != null) {
+            computeBitmapSize();
+        }
     }
 
     /** Get the gravity used to position/stretch the bitmap within its bounds.
-        See android.view.Gravity
+     * See android.view.Gravity
      * @return the gravity applied to the bitmap
      */
     public int getGravity() {
@@ -302,7 +343,7 @@
         }
         mBitmapState.mBitmap = bitmap;
         setBitmap(bitmap);
-        setDensityScale(r.getDisplayMetrics());
+        setTargetDensity(r.getDisplayMetrics());
 
         final Paint paint = mBitmapState.mPaint;
         paint.setAntiAlias(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_antialias,
@@ -332,29 +373,12 @@
 
     @Override
     public int getIntrinsicWidth() {
-        final Bitmap bitmap = mBitmap;
-        final BitmapState state = mBitmapState;
-
-        if (!state.mAutoScale || state.mBitmapScale == Bitmap.DENSITY_SCALE_UNKNOWN) {
-            return mBitmapWidth;
-        } else {
-            return bitmap != null ? (int) (mBitmapWidth /
-                    (state.mBitmapScale / state.mTargetDensityScale) + 0.5f) : -1;
-
-        }
+        return mBitmapWidth;
     }
 
     @Override
     public int getIntrinsicHeight() {
-        final Bitmap bitmap = mBitmap;
-        final BitmapState state = mBitmapState;
-
-        if (!state.mAutoScale || state.mBitmapScale == Bitmap.DENSITY_SCALE_UNKNOWN) {
-            return mBitmapHeight;
-        } else {
-            return bitmap != null ? (int) (mBitmapHeight /
-                    (state.mBitmapScale / state.mTargetDensityScale) + 0.5f) : -1;
-        }
+        return mBitmapHeight;
     }
 
     @Override
@@ -380,19 +404,10 @@
         Paint mPaint = new Paint(DEFAULT_PAINT_FLAGS);
         Shader.TileMode mTileModeX;
         Shader.TileMode mTileModeY;
-        boolean mAutoScale;
-        float mBitmapScale;
-        float mTargetDensityScale = 1.0f;
+        int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
 
         BitmapState(Bitmap bitmap) {
             mBitmap = bitmap;
-            if (bitmap != null) {
-                mBitmapScale = bitmap.getDensityScale();
-                mAutoScale = bitmap.isAutoScalingEnabled();
-            } else {
-                mBitmapScale = 1.0f;
-                mAutoScale = false;
-            }
         }
 
         BitmapState(BitmapState bitmapState) {
@@ -401,7 +416,7 @@
             mGravity = bitmapState.mGravity;
             mTileModeX = bitmapState.mTileModeX;
             mTileModeY = bitmapState.mTileModeY;
-            mTargetDensityScale = bitmapState.mTargetDensityScale;
+            mTargetDensity = bitmapState.mTargetDensity;
             mPaint = new Paint(bitmapState.mPaint);
         }
 
@@ -418,6 +433,7 @@
 
     private BitmapDrawable(BitmapState state) {
         mBitmapState = state;
+        mTargetDensity = state.mTargetDensity;
         setBitmap(state.mBitmap);
     }
 }
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 4f58a0c..193f399 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -27,6 +27,7 @@
 import android.content.res.TypedArray;
 import android.graphics.*;
 import android.util.AttributeSet;
+import android.util.DisplayMetrics;
 import android.util.StateSet;
 import android.util.Xml;
 import android.util.TypedValue;
@@ -657,9 +658,8 @@
     }
 
     /**
-     * Create a drawable from an inputstream
-     *
-     * @hide pending API council approval
+     * Create a drawable from an inputstream, using the given resources and
+     * value to determine density information.
      */
     public static Drawable createFromResourceStream(Resources res, TypedValue value,
             InputStream is, String srcName) {
@@ -675,7 +675,17 @@
             Rects only to drop them on the floor.
         */
         Rect pad = new Rect();
-        Bitmap  bm = BitmapFactory.decodeStream(res, value, is, pad, null);
+        
+        // Special stuff for compatibility mode: if the target density is not
+        // the same as the display density, but the resource -is- the same as
+        // the display density, then don't scale it down to the target density.
+        // This allows us to load the system's density-correct resources into
+        // an application in compatibility mode, without scaling those down
+        // to the compatibility density only to have them scaled back up when
+        // drawn to the screen.
+        BitmapFactory.Options opts = new BitmapFactory.Options();
+        opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
+        Bitmap  bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
         if (bm != null) {
             byte[] np = bm.getNinePatchChunk();
             if (np == null || !NinePatch.isNinePatchChunk(np)) {
@@ -754,10 +764,13 @@
         } else if (name.equals("bitmap")) {
             drawable = new BitmapDrawable();
             if (r != null) {
-               ((BitmapDrawable) drawable).setDensityScale(r.getDisplayMetrics());
+               ((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
             }
         } else if (name.equals("nine-patch")) {
             drawable = new NinePatchDrawable();
+            if (r != null) {
+                ((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
+             }
         } else {
             throw new XmlPullParserException(parser.getPositionDescription() +
                     ": invalid drawable tag " + name);
@@ -812,15 +825,10 @@
             Rect pad, String srcName) {
 
         if (np != null) {
-            return new NinePatchDrawable(bm, np, pad, srcName);
+            return new NinePatchDrawable(res, bm, np, pad, srcName);
         }
 
-        final BitmapDrawable drawable = new BitmapDrawable(bm);
-        if (res != null) {
-            drawable.setDensityScale(res.getDisplayMetrics());
-        }
-
-        return drawable;
+        return new BitmapDrawable(res, bm);
     }
 }
 
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index dace96c..d5c8a08 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -20,6 +20,7 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
+import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -41,24 +42,122 @@
     private Paint mPaint;
     private boolean mMutated;
 
+    private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
+
+    // These are scaled to match the target density.
+    private int mBitmapWidth;
+    private int mBitmapHeight;
+    
     NinePatchDrawable() {
     }
 
+    /**
+     * Create drawable from raw nine-patch data, not dealing with density.
+     * @deprecated Use {@link #NinePatchDrawable(Resources, Bitmap, byte[], Rect, String)}
+     * to ensure that the drawable has correctly set its target density.
+     */
     public NinePatchDrawable(Bitmap bitmap, byte[] chunk, Rect padding, String srcName) {
         this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding));
     }
     
+    /**
+     * Create drawable from raw nine-patch data, setting initial target density
+     * based on the display metrics of the resources.
+     */
+    public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk,
+            Rect padding, String srcName) {
+        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding));
+        if (res != null) {
+            setTargetDensity(res.getDisplayMetrics());
+            mNinePatchState.mTargetDensity = mTargetDensity;
+        }
+    }
+    
+    /**
+     * Create drawable from existing nine-patch, not dealing with density.
+     * @deprecated Use {@link #NinePatchDrawable(Resources, NinePatch)}
+     * to ensure that the drawable has correctly set its target density.
+     */
     public NinePatchDrawable(NinePatch patch) {
         this(new NinePatchState(patch, null));
     }
 
+    /**
+     * Create drawable from existing nine-patch, setting initial target density
+     * based on the display metrics of the resources.
+     */
+    public NinePatchDrawable(Resources res, NinePatch patch) {
+        this(new NinePatchState(patch, null));
+        if (res != null) {
+            setTargetDensity(res.getDisplayMetrics());
+            mNinePatchState.mTargetDensity = mTargetDensity;
+        }
+    }
+
     private void setNinePatchState(NinePatchState state) {
         mNinePatchState = state;
         mNinePatch = state.mNinePatch;
         mPadding = state.mPadding;
+        mTargetDensity = state.mTargetDensity;
         if (state.mDither) setDither(state.mDither);
+        if (mNinePatch != null) {
+            computeBitmapSize();
+        }
     }
 
+    /**
+     * Set the density scale at which this drawable will be rendered. This
+     * method assumes the drawable will be rendered at the same density as the
+     * specified canvas.
+     *
+     * @param canvas The Canvas from which the density scale must be obtained.
+     *
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
+     */
+    public void setTargetDensity(Canvas canvas) {
+        setTargetDensity(canvas.getDensity());
+    }
+
+    /**
+     * Set the density scale at which this drawable will be rendered.
+     *
+     * @param metrics The DisplayMetrics indicating the density scale for this drawable.
+     *
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
+     */
+    public void setTargetDensity(DisplayMetrics metrics) {
+        mTargetDensity = metrics.densityDpi;
+        if (mNinePatch != null) {
+            computeBitmapSize();
+        }
+    }
+
+    /**
+     * Set the density at which this drawable will be rendered.
+     *
+     * @param density The density scale for this drawable.
+     *
+     * @see android.graphics.Bitmap#setDensity(int)
+     * @see android.graphics.Bitmap#getDensity()
+     */
+    public void setTargetDensity(int density) {
+        mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
+        if (mNinePatch != null) {
+            computeBitmapSize();
+        }
+    }
+
+    private void computeBitmapSize() {
+        final int sdensity = mNinePatch.getDensity();
+        final int tdensity = mTargetDensity;
+        mBitmapWidth = Bitmap.scaleFromDensity(mNinePatch.getWidth(),
+                sdensity, tdensity);
+        mBitmapHeight = Bitmap.scaleFromDensity(mNinePatch.getHeight(),
+                sdensity, tdensity);
+    }
+    
     // overrides
 
     @Override
@@ -111,6 +210,7 @@
         if (dither) {
             options.inDither = false;
         }
+        options.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
 
         final Rect padding = new Rect();        
         Bitmap bitmap = null;
@@ -119,7 +219,7 @@
             final TypedValue value = new TypedValue();
             final InputStream is = r.openRawResource(id, value);
 
-            bitmap = BitmapFactory.decodeStream(r, value, is, padding, options);
+            bitmap = BitmapFactory.decodeResourceStream(r, value, is, padding, options);
 
             is.close();
         } catch (IOException e) {
@@ -136,6 +236,7 @@
 
         setNinePatchState(new NinePatchState(
                 new NinePatch(bitmap, bitmap.getNinePatchChunk(), "XML 9-patch"), padding, dither));
+        mNinePatchState.mTargetDensity = mTargetDensity;
 
         a.recycle();
     }
@@ -153,7 +254,7 @@
      */
     @Override
     public int getIntrinsicWidth() {
-        return mNinePatch.getWidth();
+        return mBitmapWidth;
     }
 
     /**
@@ -161,17 +262,17 @@
      */
     @Override
     public int getIntrinsicHeight() {
-        return mNinePatch.getHeight();
+        return mBitmapHeight;
     }
 
     @Override
     public int getMinimumWidth() {
-        return mNinePatch.getWidth();
+        return mBitmapWidth;
     }
 
     @Override
     public int getMinimumHeight() {
-        return mNinePatch.getHeight();
+        return mBitmapHeight;
     }
 
     /**
@@ -211,6 +312,7 @@
         final Rect mPadding;
         final boolean mDither;
         int mChangingConfigurations;
+        int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
 
         NinePatchState(NinePatch ninePatch, Rect padding) {
             this(ninePatch, padding, false);
@@ -225,8 +327,9 @@
         NinePatchState(NinePatchState state) {
             mNinePatch = new NinePatch(state.mNinePatch);
             mPadding = new Rect(state.mPadding);
-            mChangingConfigurations = state.mChangingConfigurations;
             mDither = state.mDither;
+            mChangingConfigurations = state.mChangingConfigurations;
+            mTargetDensity = state.mTargetDensity;
         }
 
         @Override
diff --git a/keystore/java/android/security/CertTool.java b/keystore/java/android/security/CertTool.java
index 79418bd..1de007d 100644
--- a/keystore/java/android/security/CertTool.java
+++ b/keystore/java/android/security/CertTool.java
@@ -72,7 +72,7 @@
     private native String getPkcs12PrivateKey(int handle);
     private native String popPkcs12CertificateStack(int handle);
     private native void freePkcs12Handle(int handle);
-    private native String generateCertificateRequest(int bits, String subject);
+    private native String generateCertificateRequest(int bits, String challenge);
     private native boolean isPkcs12Keystore(byte[] data);
     private native int generateX509Certificate(byte[] data);
     private native boolean isCaCertificate(int handle);
@@ -124,7 +124,7 @@
     public String generateKeyPair(int keyStrengthIndex, String challenge,
             String dirName) {
         return generateCertificateRequest(getKeyLength(keyStrengthIndex),
-                dirName);
+                challenge);
     }
 
     private Intent prepareIntent(String title, byte[] data, String namespace,
diff --git a/keystore/jni/cert.c b/keystore/jni/cert.c
index 0db28fd..ea21b7d 100644
--- a/keystore/jni/cert.c
+++ b/keystore/jni/cert.c
@@ -36,17 +36,17 @@
     STR(ERR_CONSTRUCT_NEW_DATA),
     STR(ERR_RSA_KEYGEN),
     STR(ERR_X509_PROCESS),
-    STR(ERR_BIO_READ),
+    STR(ERR_SPKAC_TOO_LONG),
+    STR(ERR_INVALID_ARGS),
 };
 
-static void save_in_store(X509_REQ *req, EVP_PKEY *pkey)
+static void save_in_store(EVP_PKEY *pkey)
 {
     EVP_PKEY *newpkey = EVP_PKEY_new();
     RSA *rsa = EVP_PKEY_get1_RSA(pkey);
     EVP_PKEY_set1_RSA(newpkey, rsa);
     PKEY_STORE_free(pkey_store[store_index]);
-    pkey_store[store_index].key_len =
-    i2d_X509_PUBKEY(req->req_info->pubkey, &pkey_store[store_index].public_key);
+    pkey_store[store_index].key_len = i2d_RSAPublicKey(rsa, &pkey_store[store_index].public_key);
     pkey_store[store_index++].pkey = newpkey;
     store_index %= KEYGEN_STORE_SIZE;
     RSA_free(rsa);
@@ -69,17 +69,19 @@
     return (i == KEYGEN_STORE_SIZE) ? NULL : pkey_store[i].pkey;
 }
 
-int gen_csr(int bits, const char *organizations, char reply[REPLY_MAX])
+int gen_csr(int bits, const char *challenge, char reply[REPLY_MAX])
 {
     int len, ret_code = 0;
     BIGNUM *bn = NULL;
-    BIO *bio = NULL;
+    char *spkstr = NULL;
     EVP_PKEY *pkey = NULL;
     RSA *rsa = NULL;
-    X509_REQ *req = NULL;
-    X509_NAME *name = NULL;
+    NETSCAPE_SPKI *req = NULL;
 
-    if ((bio = BIO_new(BIO_s_mem())) == NULL) goto err;
+    if (challenge == NULL) {
+        ret_code = ERR_INVALID_ARGS;
+        goto err;
+    }
 
     if ((bits != KEYLENGTH_MEDIUM) && (bits != KEYLENGTH_MAXIMUM)) {
         ret_code = ERR_INVALID_KEY_LENGTH;
@@ -87,7 +89,7 @@
     }
 
     if (((pkey = EVP_PKEY_new()) == NULL) ||
-        ((req = X509_REQ_new()) == NULL) ||
+        ((req = NETSCAPE_SPKI_new()) == NULL) ||
         ((rsa = RSA_new()) == NULL) || ((bn = BN_new()) == NULL)) {
         ret_code = ERR_CONSTRUCT_NEW_DATA;
         goto err;
@@ -100,40 +102,26 @@
         goto err;
     }
 
-    // rsa will be part of the req, it will be freed in X509_REQ_free(req)
     rsa = NULL;
+    ASN1_STRING_set(req->spkac->challenge, challenge, (int)strlen(challenge));
+    NETSCAPE_SPKI_set_pubkey(req, pkey);
+    NETSCAPE_SPKI_sign(req, pkey, EVP_md5());
+    spkstr = NETSCAPE_SPKI_b64_encode(req);
 
-    X509_REQ_set_pubkey(req, pkey);
-    name = X509_REQ_get_subject_name(req);
-
-    X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
-                               (const unsigned char *)"US", -1, -1, 0);
-    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
-                               (const unsigned char *) ANDROID_KEYSTORE,
-                               -1, -1, 0);
-    X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
-                               (const unsigned char *)organizations, -1, -1, 0);
-
-    if (!X509_REQ_sign(req, pkey, EVP_md5()) ||
-        (PEM_write_bio_X509_REQ(bio, req) <= 0)) {
-        ret_code = ERR_X509_PROCESS;
-        goto err;
-    }
-    if ((len = BIO_read(bio, reply, REPLY_MAX - 1)) > 0) {
-      reply[len] = 0;
-      save_in_store(req, pkey);
+    if ((strlcpy(reply, spkstr, REPLY_MAX)) < REPLY_MAX) {
+        save_in_store(pkey);
     } else {
-      ret_code = ERR_BIO_READ;
+        ret_code = ERR_SPKAC_TOO_LONG;
     }
 
 err:
     if (rsa) RSA_free(rsa);
     if (bn) BN_free(bn);
-    if (req) X509_REQ_free(req);
+    if (req) NETSCAPE_SPKI_free(req);
     if (pkey) EVP_PKEY_free(pkey);
-    if (bio) BIO_free(bio);
+    if (spkstr) OPENSSL_free(spkstr);
     if ((ret_code > 0) && (ret_code < ERR_MAXIMUM)) LOGE(emsg[ret_code]);
-    return ret_code;
+    return -ret_code;
 }
 
 PKCS12 *get_p12_handle(const char *buf, int bufLen)
diff --git a/keystore/jni/cert.h b/keystore/jni/cert.h
index aaa7602..a9e1a9e 100644
--- a/keystore/jni/cert.h
+++ b/keystore/jni/cert.h
@@ -32,8 +32,9 @@
 #define ERR_CONSTRUCT_NEW_DATA  2
 #define ERR_RSA_KEYGEN          3
 #define ERR_X509_PROCESS        4
-#define ERR_BIO_READ            5
-#define ERR_MAXIMUM             6
+#define ERR_SPKAC_TOO_LONG      5
+#define ERR_INVALID_ARGS        6
+#define ERR_MAXIMUM             7
 
 typedef struct {
     EVP_PKEY *pkey;
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 8be11df..03ffc67 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -41,8 +41,9 @@
     public static final int FILE_TYPE_AWB     = 5;
     public static final int FILE_TYPE_WMA     = 6;
     public static final int FILE_TYPE_OGG     = 7;
+    public static final int FILE_TYPE_AAC     = 8;
     private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3;
-    private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_OGG;
+    private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_AAC;
 
     // MIDI file types
     public static final int FILE_TYPE_MID     = 11;
@@ -57,8 +58,9 @@
     public static final int FILE_TYPE_3GPP    = 23;
     public static final int FILE_TYPE_3GPP2   = 24;
     public static final int FILE_TYPE_WMV     = 25;
+    public static final int FILE_TYPE_ASF     = 26;
     private static final int FIRST_VIDEO_FILE_TYPE = FILE_TYPE_MP4;
-    private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_WMV;
+    private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_ASF;
     
     // Image file types
     public static final int FILE_TYPE_JPEG    = 31;
@@ -104,6 +106,7 @@
         addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma");    
         addFileType("OGG", FILE_TYPE_OGG, "application/ogg");
         addFileType("OGA", FILE_TYPE_OGG, "application/ogg");
+        addFileType("AAC", FILE_TYPE_AAC, "audio/aac");
  
         addFileType("MID", FILE_TYPE_MID, "audio/midi");
         addFileType("MIDI", FILE_TYPE_MID, "audio/midi");
@@ -121,6 +124,7 @@
         addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2");
         addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2");
         addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv");
+        addFileType("ASF", FILE_TYPE_ASF, "video/x-ms-asf");
 
         addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg");
         addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg");
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 0bb2df1..769226e 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -1266,6 +1266,13 @@
     boolean disableDataConnectivity();
 
     /**
+     * Report the current state of data connectivity (enabled or disabled)
+     * @return {@code false} if data connectivity has been explicitly disabled,
+     * {@code true} otherwise.
+     */
+    boolean isDataConnectivityEnabled();
+
+    /**
      * Enables the specified APN type. Only works for "special" APN types,
      * i.e., not the default APN.
      * @param type The desired APN type. Cannot be {@link #APN_TYPE_DEFAULT}.
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index 979f0cd..30d56da 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -614,6 +614,10 @@
         return mActivePhone.disableApnType(type);
     }
 
+    public boolean isDataConnectivityEnabled() {
+        return mActivePhone.isDataConnectivityEnabled();
+    }
+
     public boolean isDataConnectivityPossible() {
         return mActivePhone.isDataConnectivityPossible();
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index bdcea92..aec7aee 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -508,6 +508,10 @@
         return false;
     }
 
+    public boolean isDataConnectivityEnabled() {
+        return mDataConnection.getDataEnabled();
+    }
+
     public boolean isDataConnectivityPossible() {
         boolean noData = mDataConnection.getDataEnabled() &&
                 getDataConnectionState() == DataState.DISCONNECTED;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index ebbf096..6f89288 100755
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -1169,6 +1169,10 @@
         return mDataConnection.getDnsServers(apnType);
     }
 
+    public boolean isDataConnectivityEnabled() {
+        return mDataConnection.getDataEnabled();
+    }
+
     /**
      * The only circumstances under which we report that data connectivity is not
      * possible are
diff --git a/tests/DpiTest/res/drawable-hdpi/npatch240dpi.9.png b/tests/DpiTest/res/drawable-hdpi/npatch240dpi.9.png
new file mode 100644
index 0000000..a362b0f
--- /dev/null
+++ b/tests/DpiTest/res/drawable-hdpi/npatch240dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-hdpi/smlnpatch240dpi.9.png b/tests/DpiTest/res/drawable-hdpi/smlnpatch240dpi.9.png
new file mode 100644
index 0000000..84bdcb0
--- /dev/null
+++ b/tests/DpiTest/res/drawable-hdpi/smlnpatch240dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-ldpi/npatch120dpi.9.png b/tests/DpiTest/res/drawable-ldpi/npatch120dpi.9.png
new file mode 100644
index 0000000..0d8115b
--- /dev/null
+++ b/tests/DpiTest/res/drawable-ldpi/npatch120dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-ldpi/smlnpatch120dpi.9.png b/tests/DpiTest/res/drawable-ldpi/smlnpatch120dpi.9.png
new file mode 100644
index 0000000..de8d607
--- /dev/null
+++ b/tests/DpiTest/res/drawable-ldpi/smlnpatch120dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable/npatch160dpi.9.png b/tests/DpiTest/res/drawable/npatch160dpi.9.png
new file mode 100644
index 0000000..44d89a9
--- /dev/null
+++ b/tests/DpiTest/res/drawable/npatch160dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable/smlnpatch160dpi.9.png b/tests/DpiTest/res/drawable/smlnpatch160dpi.9.png
new file mode 100644
index 0000000..76c4ae8
--- /dev/null
+++ b/tests/DpiTest/res/drawable/smlnpatch160dpi.9.png
Binary files differ
diff --git a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
index dd4fae3..68220a1 100644
--- a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
+++ b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
@@ -34,6 +34,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
 import android.util.DisplayMetrics;
+import android.util.Log;
 
 public class DpiTestActivity extends Activity {
     public DpiTestActivity() {
@@ -116,6 +117,13 @@
         addLabelToRoot(root, "No-dpi resource drawable");
         addChildToRoot(root, layout);
 
+        layout = new LinearLayout(this);
+        addNinePatchResourceDrawable(layout, R.drawable.smlnpatch120dpi);
+        addNinePatchResourceDrawable(layout, R.drawable.smlnpatch160dpi);
+        addNinePatchResourceDrawable(layout, R.drawable.smlnpatch240dpi);
+        addLabelToRoot(root, "Prescaled 9-patch resource drawable");
+        addChildToRoot(root, layout);
+
         setContentView(scrollWrap(root));
     }
 
@@ -144,8 +152,8 @@
 
         View view = new View(this);
 
-        final BitmapDrawable d = new BitmapDrawable(bitmap);
-        if (!scale) d.setDensityScale(getResources().getDisplayMetrics());
+        final BitmapDrawable d = new BitmapDrawable(getResources(), bitmap);
+        if (!scale) d.setTargetDensity(getResources().getDisplayMetrics());
         view.setBackgroundDrawable(d);
 
         view.setLayoutParams(new LinearLayout.LayoutParams(d.getIntrinsicWidth(),
@@ -175,6 +183,19 @@
         layout.addView(view);
     }
 
+    private void addNinePatchResourceDrawable(LinearLayout layout, int resource) {
+        View view = new View(this);
+
+        final Drawable d = getResources().getDrawable(resource);
+        view.setBackgroundDrawable(d);
+
+        Log.i("foo", "9-patch #" + Integer.toHexString(resource)
+                + " w=" + d.getIntrinsicWidth() + " h=" + d.getIntrinsicHeight());
+        view.setLayoutParams(new LinearLayout.LayoutParams(
+                d.getIntrinsicWidth()*2, d.getIntrinsicHeight()*2));
+        layout.addView(view);
+    }
+
     private Bitmap loadAndPrintDpi(int id, boolean scale) {
         Bitmap bitmap;
         if (scale) {