Add new "-swNNNdp" resource qualifier.

Change-Id: I0101e88ca9d8d44138bdcaf571f24b0352f4f6ce
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 64c437d..4285388 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -340,6 +340,12 @@
     public static final int CONFIG_SCREEN_SIZE = 0x0400;
     /**
      * Bit in {@link #configChanges} that indicates that the activity
+     * can itself handle the smallest screen size. Set from the
+     * {@link android.R.attr#configChanges} attribute.
+     */
+    public static final int CONFIG_SMALLEST_SCREEN_SIZE = 0x0800;
+    /**
+     * Bit in {@link #configChanges} that indicates that the activity
      * can itself handle changes to the font scaling factor.  Set from the
      * {@link android.R.attr#configChanges} attribute.  This is
      * not a core resource configutation, but a higher-level value, so its
@@ -364,6 +370,7 @@
         0x0800, // SCREEN LAYOUT
         0x1000, // UI MODE
         0x0200, // SCREEN SIZE
+        0x2000, // SMALLEST SCREEN SIZE
     };
     /** @hide
      * Convert Java change bits to native.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 2a61c56..10799a4 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -396,7 +396,7 @@
             int cookie = assmgr.addAssetPath(mArchiveSourcePath);
             if (cookie != 0) {
                 res = new Resources(assmgr, metrics, null);
-                assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                         Build.VERSION.RESOURCES_SDK_INT);
                 parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
                 assetError = false;
@@ -596,7 +596,7 @@
         AssetManager assmgr = null;
         try {
             assmgr = new AssetManager();
-            assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                     Build.VERSION.RESOURCES_SDK_INT);
             int cookie = assmgr.addAssetPath(packageFilePath);
             parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
@@ -1933,7 +1933,8 @@
                     0);
             if (owner.applicationInfo.targetSdkVersion
                         < android.os.Build.VERSION_CODES.HONEYCOMB_MR2) {
-                a.info.configChanges |= ActivityInfo.CONFIG_SCREEN_SIZE;
+                a.info.configChanges |= ActivityInfo.CONFIG_SCREEN_SIZE
+                        | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
             }
             a.info.softInputMode = sa.getInt(
                     com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode,
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index afa68c3..72fca0a 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -652,8 +652,8 @@
     public native final void setConfiguration(int mcc, int mnc, String locale,
             int orientation, int touchscreen, int density, int keyboard,
             int keyboardHidden, int navigation, int screenWidth, int screenHeight,
-            int screenWidthDp, int screenHeightDp, int screenLayout, int uiMode,
-            int majorVersion);
+            int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp,
+            int screenLayout, int uiMode, int majorVersion);
 
     /**
      * Retrieve the resource identifier for the given resource name.
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 0de08f2..12ec258 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -259,6 +259,15 @@
      */
     public int screenHeightDp;
 
+    public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
+
+    /**
+     * The smallest screen size an application will see in normal operation.
+     * This is the smallest value of both screenWidthDp and screenHeightDp
+     * in both portrait and landscape.
+     */
+    public int smallestScreenWidthDp;
+
     /**
      * @hide Internal book-keeping.
      */
@@ -298,6 +307,7 @@
         uiMode = o.uiMode;
         screenWidthDp = o.screenWidthDp;
         screenHeightDp = o.screenHeightDp;
+        smallestScreenWidthDp = o.smallestScreenWidthDp;
         seq = o.seq;
     }
     
@@ -315,6 +325,56 @@
         } else {
             sb.append(" (no locale)");
         }
+        if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
+            sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
+        } else {
+            sb.append("?swdp");
+        }
+        if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
+            sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
+        } else {
+            sb.append("?wdp");
+        }
+        if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
+            sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
+        } else {
+            sb.append("?hdp");
+        }
+        switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
+            case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
+            case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
+            case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
+            case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
+            case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
+            default: sb.append(" layoutSize=");
+                    sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
+        }
+        switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
+            case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
+            case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
+            case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
+            default: sb.append(" layoutLong=");
+                    sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
+        }
+        switch (orientation) {
+            case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
+            case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
+            case ORIENTATION_PORTRAIT: sb.append(" port"); break;
+            default: sb.append(" orien="); sb.append(orientation); break;
+        }
+        switch ((uiMode&UI_MODE_TYPE_MASK)) {
+            case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
+            case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
+            case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
+            case UI_MODE_TYPE_CAR: sb.append(" car"); break;
+            default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
+        }
+        switch ((uiMode&UI_MODE_NIGHT_MASK)) {
+            case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
+            case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
+            case UI_MODE_NIGHT_YES: sb.append(" night"); break;
+            default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
+        }
         switch (touchscreen) {
             case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
             case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
@@ -356,51 +416,6 @@
             case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
             default: sb.append("/"); sb.append(navigationHidden); break;
         }
-        switch (orientation) {
-            case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
-            case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
-            case ORIENTATION_PORTRAIT: sb.append(" port"); break;
-            default: sb.append(" orien="); sb.append(orientation); break;
-        }
-        switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
-            case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
-            case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
-            case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
-            case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
-            case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
-            default: sb.append(" layoutSize=");
-                    sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
-        }
-        switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
-            case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
-            case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
-            case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
-            default: sb.append(" layoutLong=");
-                    sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
-        }
-        switch ((uiMode&UI_MODE_TYPE_MASK)) {
-            case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
-            case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
-            case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
-            case UI_MODE_TYPE_CAR: sb.append(" car"); break;
-            default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
-        }
-        switch ((uiMode&UI_MODE_NIGHT_MASK)) {
-            case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
-            case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
-            case UI_MODE_NIGHT_YES: sb.append(" night"); break;
-            default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
-        }
-        if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
-            sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
-        } else {
-            sb.append("?wdp");
-        }
-        if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
-            sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
-        } else {
-            sb.append("?hdp");
-        }
         if (seq != 0) {
             sb.append(" s.");
             sb.append(seq);
@@ -428,6 +443,7 @@
         uiMode = UI_MODE_TYPE_UNDEFINED;
         screenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
         screenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
+        smallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
         seq = 0;
     }
 
@@ -531,6 +547,11 @@
             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
             screenHeightDp = delta.screenHeightDp;
         }
+        if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
+                && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
+            changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+            smallestScreenWidthDp = delta.smallestScreenWidthDp;
+        }
         
         if (delta.seq != 0) {
             seq = delta.seq;
@@ -564,7 +585,9 @@
      * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
      * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
      * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
-     * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}.
+     * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
+     * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
+     * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
      */
     public int diff(Configuration delta) {
         int changed = 0;
@@ -625,6 +648,10 @@
                 && screenHeightDp != delta.screenHeightDp) {
             changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
         }
+        if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
+                && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
+            changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+        }
         
         return changed;
     }
@@ -708,6 +735,7 @@
         dest.writeInt(uiMode);
         dest.writeInt(screenWidthDp);
         dest.writeInt(screenHeightDp);
+        dest.writeInt(smallestScreenWidthDp);
         dest.writeInt(seq);
     }
 
@@ -731,6 +759,7 @@
         uiMode = source.readInt();
         screenWidthDp = source.readInt();
         screenHeightDp = source.readInt();
+        smallestScreenWidthDp = source.readInt();
         seq = source.readInt();
     }
     
@@ -795,6 +824,8 @@
         n = this.screenWidthDp - that.screenWidthDp;
         if (n != 0) return n;
         n = this.screenHeightDp - that.screenHeightDp;
+        if (n != 0) return n;
+        n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
         //if (n != 0) return n;
         return n;
     }
@@ -830,6 +861,7 @@
         result = 31 * result + uiMode;
         result = 31 * result + screenWidthDp;
         result = 31 * result + screenHeightDp;
+        result = 31 * result + smallestScreenWidthDp;
         return result;
     }
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 540f704..a072e94 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1458,6 +1458,7 @@
                     mConfiguration.touchscreen,
                     (int)(mMetrics.density*160), mConfiguration.keyboard,
                     keyboardHidden, mConfiguration.navigation, width, height,
+                    mConfiguration.smallestScreenWidthDp,
                     mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
                     mConfiguration.screenLayout, mConfiguration.uiMode,
                     Build.VERSION.RESOURCES_SDK_INT);
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index c7cf459..086ed5a 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -464,16 +464,34 @@
     public int getMaxWallpaperLayer();
     
     /**
-     * Return the display width available after excluding the window
-     * decor.
+     * Return the display width available after excluding any screen
+     * decorations that can never be removed.  That is, system bar or
+     * button bar.
      */
-    public int getNonDecorDisplayWidth(int fullWidth);
+    public int getNonDecorDisplayWidth(int rotation, int fullWidth);
 
     /**
-     * Return the display height available after excluding the screen
-     * decor.
+     * Return the display height available after excluding any screen
+     * decorations that can never be removed.  That is, system bar or
+     * button bar.
      */
-    public int getNonDecorDisplayHeight(int fullHeight);
+    public int getNonDecorDisplayHeight(int rotation, int fullHeight);
+
+    /**
+     * Return the available screen width that we should report for the
+     * configuration.  This must be no larger than
+     * {@link #getNonDecorDisplayWidth(int, int)}; it may be smaller than
+     * that to account for more transient decoration like a status bar.
+     */
+    public int getConfigDisplayWidth(int rotation, int fullWidth);
+
+    /**
+     * Return the available screen height that we should report for the
+     * configuration.  This must be no larger than
+     * {@link #getNonDecorDisplayHeight(int, int)}; it may be smaller than
+     * that to account for more transient decoration like a status bar.
+     */
+    public int getConfigDisplayHeight(int rotation, int fullHeight);
 
     /**
      * Return whether the given window should forcibly hide everything
diff --git a/core/jni/android_content_res_Configuration.cpp b/core/jni/android_content_res_Configuration.cpp
index 28a43ab..5e09b38 100644
--- a/core/jni/android_content_res_Configuration.cpp
+++ b/core/jni/android_content_res_Configuration.cpp
@@ -40,6 +40,9 @@
     jfieldID navigationHidden;
     jfieldID orientation;
     jfieldID uiMode;
+    jfieldID screenWidthDp;
+    jfieldID screenHeightDp;
+    jfieldID smallestScreenWidthDp;
 } gConfigurationClassInfo;
 
 void android_Configuration_getFromJava(
@@ -62,6 +65,11 @@
 
     out->orientation = env->GetIntField(clazz, gConfigurationClassInfo.orientation);
     out->uiMode = env->GetIntField(clazz, gConfigurationClassInfo.uiMode);
+
+    out->screenWidthDp = env->GetIntField(clazz, gConfigurationClassInfo.screenWidthDp);
+    out->screenHeightDp = env->GetIntField(clazz, gConfigurationClassInfo.screenHeightDp);
+    out->smallestScreenWidthDp = env->GetIntField(clazz,
+            gConfigurationClassInfo.smallestScreenWidthDp);
 }
 
 /*
@@ -110,6 +118,12 @@
             "orientation", "I");
     GET_FIELD_ID(gConfigurationClassInfo.uiMode, gConfigurationClassInfo.clazz,
             "uiMode", "I");
+    GET_FIELD_ID(gConfigurationClassInfo.screenWidthDp, gConfigurationClassInfo.clazz,
+            "screenWidthDp", "I");
+    GET_FIELD_ID(gConfigurationClassInfo.screenHeightDp, gConfigurationClassInfo.clazz,
+            "screenHeightDp", "I");
+    GET_FIELD_ID(gConfigurationClassInfo.smallestScreenWidthDp, gConfigurationClassInfo.clazz,
+            "smallestScreenWidthDp", "I");
 
     return AndroidRuntime::registerNativeMethods(env, "android/content/res/Configuration", gMethods,
             NELEM(gMethods));
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 7a2d020..636d257 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -532,6 +532,7 @@
                                                           jint keyboard, jint keyboardHidden,
                                                           jint navigation,
                                                           jint screenWidth, jint screenHeight,
+                                                          jint smallestScreenWidthDp,
                                                           jint screenWidthDp, jint screenHeightDp,
                                                           jint screenLayout, jint uiMode,
                                                           jint sdkVersion)
@@ -556,6 +557,7 @@
     config.navigation = (uint8_t)navigation;
     config.screenWidth = (uint16_t)screenWidth;
     config.screenHeight = (uint16_t)screenHeight;
+    config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
     config.screenWidthDp = (uint16_t)screenWidthDp;
     config.screenHeightDp = (uint16_t)screenHeightDp;
     config.screenLayout = (uint8_t)screenLayout;
@@ -1696,7 +1698,7 @@
         (void*) android_content_AssetManager_setLocale },
     { "getLocales",      "()[Ljava/lang/String;",
         (void*) android_content_AssetManager_getLocales },
-    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIII)V",
+    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
         (void*) android_content_AssetManager_setConfiguration },
     { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
         (void*) android_content_AssetManager_getResourceIdentifier },
diff --git a/core/res/res/values-large/dimens.xml b/core/res/res/values-large/dimens.xml
index ab6e36d..1944029 100644
--- a/core/res/res/values-large/dimens.xml
+++ b/core/res/res/values-large/dimens.xml
@@ -24,10 +24,6 @@
     <!-- Size of the giant number (unread count) in the notifications -->
     <dimen name="status_bar_content_number_size">48sp</dimen>
 
-    <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
-    <!-- Margin for permanent screen decorations at the bottom. -->
-    <dimen name="screen_margin_bottom">48dip</dimen>
-
     <!-- Default height of a key in the password keyboard for alpha -->
     <dimen name="password_keyboard_key_height_alpha">75dip</dimen>
     <!-- Default height of a key in the password keyboard for numeric -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 70c4c86..ceb7752 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -590,11 +590,21 @@
         <!-- The global user interface mode has changed.  For example,
              going in or out of car mode, night mode changing, etc. -->
         <flag name="uiMode" value="0x0200" />
+        <!-- The current available screen size has changed.  If applications don't
+             target at least {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2}
+             then the activity will always handle this itself (the change
+             will not result in a restart).  This represents a change in the
+             currently available size, so will change when the user switches
+             between landscape and portrait. -->
+        <flag name="screenSize" value="0x0400" />
         <!-- The physical screen size has changed.  If applications don't
              target at least {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2}
              then the activity will always handle this itself (the change
-             will not result in a restart). -->
-        <flag name="screenSize" value="0x0400" />
+             will not result in a restart).  This represents a change in size
+             regardless of orientation, so will only change when the actual
+             physical screen size has changed such as switching to an external
+             display. -->
+        <flag name="smallestScreenSize" value="0x0800" />
         <!-- The font scaling factor has changed, that is the user has
              selected a new global font size. -->
         <flag name="fontScale" value="0x40000000" />
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 02193c3..1782f02 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -36,8 +36,6 @@
     <dimen name="status_bar_icon_size">25dip</dimen>
     <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
     <dimen name="status_bar_edge_ignore">5dp</dimen>
-    <!-- Margin for permanent screen decorations at the bottom. -->
-    <dimen name="screen_margin_bottom">0dip</dimen>
     <!-- Size of the fastscroll hint letter -->
     <dimen name="fastscroll_overlay_size">104dp</dimen>
     <!-- Width of the fastscroll thumb -->