Expand support for different screen sizes.

Applications can now declare that they support small, normal, or
large screens.  Resource selection can also be done based on these
sizes.  By default, pre-Donut apps are false for small and large,
and Donut or later apps are assumed to support all sizes.  In either
case they can use <supports-screens> in their manifest to declare
what they actually support.
diff --git a/api/current.xml b/api/current.xml
index 66bdb28..3c58ded 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -3452,39 +3452,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad26"
- type="int"
- transient="false"
- volatile="false"
- value="16843398"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad27"
- type="int"
- transient="false"
- volatile="false"
- value="16843397"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad28"
- type="int"
- transient="false"
- volatile="false"
- value="16843396"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="donut_resource_pad3"
  type="int"
  transient="false"
@@ -5311,6 +5278,17 @@
  visibility="public"
 >
 </field>
+<field name="largeScreens"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843398"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="launchMode"
  type="int"
  transient="false"
@@ -6191,6 +6169,17 @@
  visibility="public"
 >
 </field>
+<field name="normalScreens"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843397"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="numColumns"
  type="int"
  transient="false"
@@ -7577,6 +7566,17 @@
  visibility="public"
 >
 </field>
+<field name="smallScreens"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843396"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="smoothScrollbar"
  type="int"
  transient="false"
@@ -34821,6 +34821,17 @@
  visibility="public"
 >
 </field>
+<field name="CONFIG_SCREEN_LAYOUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="256"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="CONFIG_TOUCHSCREEN"
  type="int"
  transient="false"
@@ -35289,6 +35300,28 @@
  type="int"
  transient="false"
  volatile="false"
+ value="2048"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FLAG_SUPPORTS_NORMAL_SCREENS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FLAG_SUPPORTS_SMALL_SCREENS"
+ type="int"
+ transient="false"
+ volatile="false"
  value="512"
  static="true"
  final="true"
@@ -39488,6 +39521,50 @@
  visibility="public"
 >
 </field>
+<field name="SCREENLAYOUT_LARGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREENLAYOUT_NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREENLAYOUT_SMALL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREENLAYOUT_UNDEFINED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TOUCHSCREEN_FINGER"
  type="int"
  transient="false"
@@ -39622,6 +39699,16 @@
  visibility="public"
 >
 </field>
+<field name="screenLayout"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="touchscreen"
  type="int"
  transient="false"
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 85d877a..27783ef 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -235,6 +235,12 @@
     public static final int CONFIG_ORIENTATION = 0x0080;
     /**
      * Bit in {@link #configChanges} that indicates that the activity
+     * can itself handle changes to the screen layout.  Set from the
+     * {@link android.R.attr#configChanges} attribute.
+     */
+    public static final int CONFIG_SCREEN_LAYOUT = 0x0100;
+    /**
+     * 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
@@ -248,8 +254,8 @@
      * Contains any combination of {@link #CONFIG_FONT_SCALE},
      * {@link #CONFIG_MCC}, {@link #CONFIG_MNC},
      * {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN},
-     * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION}, and
-     * {@link #CONFIG_ORIENTATION}.  Set from the
+     * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION},
+     * {@link #CONFIG_ORIENTATION}, and {@link #CONFIG_SCREEN_LAYOUT}.  Set from the
      * {@link android.R.attr#configChanges} attribute.
      */
     public int configChanges;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 2a2cf93..bcf95b6 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -138,10 +138,27 @@
 
     /**
      * Value for {@link #flags}: true when the application's window can be
-     * expanded over default window size in target density (320x480 for
-     * 1.0 density, 480x720 for 1.5 density etc)
+     * reduced in size for smaller screens.  Corresponds to
+     * {@link android.R.styleable#AndroidManifestSupportsScreens_smallScreens
+     * android:smallScreens}.
      */
-    public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<9;
+    public static final int FLAG_SUPPORTS_SMALL_SCREENS = 1<<9;
+    
+    /**
+     * Value for {@link #flags}: true when the application's window can be
+     * displayed on normal screens.  Corresponds to
+     * {@link android.R.styleable#AndroidManifestSupportsScreens_normalScreens
+     * android:normalScreens}.
+     */
+    public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1<<10; 
+    
+    /**
+     * Value for {@link #flags}: true when the application's window can be
+     * increased in size for larger screens.  Corresponds to
+     * {@link android.R.styleable#AndroidManifestSupportsScreens_largeScreens
+     * android:smallScreens}.
+     */
+    public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<11;
     
     /**
      * Value for {@link #flags}: this is false if the application has set
@@ -149,7 +166,7 @@
      * 
      * {@hide}
      */
-    public static final int FLAG_ALLOW_BACKUP = 1<<10;
+    public static final int FLAG_ALLOW_BACKUP = 1<<12;
     
     /**
      * Indicates that the application supports any densities;
@@ -164,7 +181,9 @@
      * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
      * {@link #FLAG_ALLOW_TASK_REPARENTING}
      * {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP},
-     * {@link #FLAG_TEST_ONLY}.
+     * {@link #FLAG_TEST_ONLY}, {@link #FLAG_SUPPORTS_SMALL_SCREENS},
+     * {@link #FLAG_SUPPORTS_NORMAL_SCREENS},
+     * {@link #FLAG_SUPPORTS_LARGE_SCREENS}.
      */
     public int flags = 0;
     
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ab9518e..558b0c3 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -668,6 +668,11 @@
         }
         sa.recycle();
 
+        // Resource boolean are -1, so 1 means we don't know the value.
+        int supportsSmallScreens = 1;
+        int supportsNormalScreens = 1;
+        int supportsLargeScreens = 1;
+        
         int outerDepth = parser.getDepth();
         while ((type=parser.next()) != parser.END_DOCUMENT
                && (type != parser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -876,8 +881,24 @@
 
                 XmlUtils.skipCurrentTag(parser);
 
-            } else if (tagName.equals("expandable")) {
-                pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
+            } else if (tagName.equals("supports-screens")) {
+                sa = res.obtainAttributes(attrs,
+                        com.android.internal.R.styleable.AndroidManifestSupportsScreens);
+
+                // This is a trick to get a boolean and still able to detect
+                // if a value was actually set.
+                supportsSmallScreens = sa.getInteger(
+                        com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
+                        supportsSmallScreens);
+                supportsNormalScreens = sa.getInteger(
+                        com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
+                        supportsNormalScreens);
+                supportsLargeScreens = sa.getInteger(
+                        com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
+                        supportsLargeScreens);
+
+                sa.recycle();
+                
                 XmlUtils.skipCurrentTag(parser);
             } else {
                 Log.w(TAG, "Bad element under <manifest>: "
@@ -910,7 +931,20 @@
             pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()];
             pkg.usesLibraries.toArray(pkg.usesLibraryFiles);
         }
-        // TODO: enable all density & expandable if target sdk is higher than donut 
+        
+        if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
+                && pkg.applicationInfo.targetSdkVersion
+                        >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
+            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
+        }
+        if (supportsNormalScreens != 0) {
+            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
+        }
+        if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
+                && pkg.applicationInfo.targetSdkVersion
+                        >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
+            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
+        }
         
         int size = pkg.supportsDensityList.size();
         if (size > 0) {
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 1c91736..5c7b01f 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -601,7 +601,7 @@
     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 majorVersion);
+            int screenLayout, int majorVersion);
 
     /**
      * Retrieve the resource identifier for the given resource name.
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 179b9bd..4e6fe07 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -65,7 +65,7 @@
     /**
      *  A compatibility flags
      */
-    private int compatibilityFlags;
+    private int mCompatibilityFlags;
     
     /**
      * A flag mask to tell if the application needs scaling (when mApplicationScale != 1.0f)
@@ -101,7 +101,11 @@
      */
     public final float applicationInvertedScale;
 
-
+    /**
+     * The flags from ApplicationInfo.
+     */
+    public final int appFlags;
+    
     /**
      * Window size in Compatibility Mode, in real pixels. This is updated by
      * {@link DisplayMetrics#updateMetrics}.
@@ -117,8 +121,10 @@
     private int mXOffset;
 
     public CompatibilityInfo(ApplicationInfo appInfo) {
+        appFlags = appInfo.flags;
+        
         if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
-            compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
+            mCompatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
         }
         
         float packageDensityScale = -1.0f;
@@ -149,13 +155,16 @@
         }
         applicationInvertedScale = 1.0f / applicationScale;
         if (applicationScale != 1.0f) {
-            compatibilityFlags |= SCALING_REQUIRED;
+            mCompatibilityFlags |= SCALING_REQUIRED;
         }
     }
 
     private CompatibilityInfo() {
+        appFlags = ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS
+                | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS
+                | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
         applicationScale = applicationInvertedScale = 1.0f;
-        compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
+        mCompatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
     }
 
     /**
@@ -175,9 +184,9 @@
      */
     public void setExpandable(boolean expandable) {
         if (expandable) {
-            compatibilityFlags |= CompatibilityInfo.EXPANDABLE;
+            mCompatibilityFlags |= CompatibilityInfo.EXPANDABLE;
         } else {
-            compatibilityFlags &= ~CompatibilityInfo.EXPANDABLE;
+            mCompatibilityFlags &= ~CompatibilityInfo.EXPANDABLE;
         }
     }
 
@@ -185,20 +194,20 @@
      * @return true if the application is configured to be expandable.
      */
     public boolean isConfiguredExpandable() {
-        return (compatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0;
+        return (mCompatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0;
     }
 
     /**
      * @return true if the scaling is required
      */
     public boolean isScalingRequired() {
-        return (compatibilityFlags & SCALING_REQUIRED) != 0;
+        return (mCompatibilityFlags & SCALING_REQUIRED) != 0;
     }
     
     @Override
     public String toString() {
         return "CompatibilityInfo{scale=" + applicationScale +
-                ", compatibility flag=" + compatibilityFlags + "}"; 
+                ", compatibility flag=" + mCompatibilityFlags + "}"; 
     }
 
     /**
@@ -222,13 +231,13 @@
      * @param params the window's parameter
      */
     public Translator getTranslator(WindowManager.LayoutParams params) {
-        if ( (compatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK)
+        if ( (mCompatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK)
                 == CompatibilityInfo.EXPANDABLE) {
             if (DBG) Log.d(TAG, "no translation required");
             return null;
         }
         
-        if ((compatibilityFlags & CompatibilityInfo.EXPANDABLE) == 0) {
+        if ((mCompatibilityFlags & CompatibilityInfo.EXPANDABLE) == 0) {
             if ((params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) {
                 if (DBG) Log.d(TAG, "translation for surface view selected");
                 return new Translator(X_SHIFT_WINDOW, false, 1.0f, 1.0f);
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index bb3486c..577aa60 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -116,6 +116,18 @@
      */
     public int orientation;
     
+    public static final int SCREENLAYOUT_UNDEFINED = 0;
+    public static final int SCREENLAYOUT_SMALL = 1;
+    public static final int SCREENLAYOUT_NORMAL = 2;
+    public static final int SCREENLAYOUT_LARGE = 3;
+    
+    /**
+     * Overall layout of the screen.  May be one of
+     * {@link #SCREENLAYOUT_SMALL}, {@link #SCREENLAYOUT_NORMAL},
+     * or {@link #SCREENLAYOUT_LARGE}.
+     */
+    public int screenLayout;
+    
     /**
      * Construct an invalid Configuration.  You must call {@link #setToDefaults}
      * for this object to be valid.  {@more}
@@ -141,6 +153,7 @@
         hardKeyboardHidden = o.hardKeyboardHidden;
         navigation = o.navigation;
         orientation = o.orientation;
+        screenLayout = o.screenLayout;
     }
 
     public String toString() {
@@ -165,6 +178,8 @@
         sb.append(navigation);
         sb.append(" orien=");
         sb.append(orientation);
+        sb.append(" layout=");
+        sb.append(screenLayout);
         sb.append('}');
         return sb.toString();
     }
@@ -183,6 +198,7 @@
         hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
         navigation = NAVIGATION_UNDEFINED;
         orientation = ORIENTATION_UNDEFINED;
+        screenLayout = SCREENLAYOUT_UNDEFINED;
     }
 
     /** {@hide} */
@@ -253,6 +269,11 @@
             changed |= ActivityInfo.CONFIG_ORIENTATION;
             orientation = delta.orientation;
         }
+        if (delta.screenLayout != SCREENLAYOUT_UNDEFINED
+                && screenLayout != delta.screenLayout) {
+            changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
+            screenLayout = delta.screenLayout;
+        }
         
         return changed;
     }
@@ -276,9 +297,11 @@
      * {@link android.content.pm.ActivityInfo#CONFIG_KEYBOARD
      * PackageManager.ActivityInfo.CONFIG_KEYBOARD},
      * {@link android.content.pm.ActivityInfo#CONFIG_NAVIGATION
-     * PackageManager.ActivityInfo.CONFIG_NAVIGATION}, or
+     * PackageManager.ActivityInfo.CONFIG_NAVIGATION},
      * {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION
-     * PackageManager.ActivityInfo.CONFIG_ORIENTATION}.
+     * PackageManager.ActivityInfo.CONFIG_ORIENTATION}, or
+     * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
+     * PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}.
      */
     public int diff(Configuration delta) {
         int changed = 0;
@@ -319,6 +342,10 @@
                 && orientation != delta.orientation) {
             changed |= ActivityInfo.CONFIG_ORIENTATION;
         }
+        if (delta.screenLayout != SCREENLAYOUT_UNDEFINED
+                && screenLayout != delta.screenLayout) {
+            changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
+        }
         
         return changed;
     }
@@ -368,6 +395,7 @@
         dest.writeInt(hardKeyboardHidden);
         dest.writeInt(navigation);
         dest.writeInt(orientation);
+        dest.writeInt(screenLayout);
     }
 
     public static final Parcelable.Creator<Configuration> CREATOR
@@ -399,6 +427,7 @@
         hardKeyboardHidden = source.readInt();
         navigation = source.readInt();
         orientation = source.readInt();
+        screenLayout = source.readInt();
     }
 
     public int compareTo(Configuration that) {
@@ -428,6 +457,8 @@
         n = this.navigation - that.navigation;
         if (n != 0) return n;
         n = this.orientation - that.orientation;
+        if (n != 0) return n;
+        n = this.screenLayout - that.screenLayout;
         //if (n != 0) return n;
         return n;
     }
@@ -450,6 +481,6 @@
         return ((int)this.fontScale) + this.mcc + this.mnc
                 + this.locale.hashCode() + this.touchscreen
                 + this.keyboard + this.keyboardHidden + this.hardKeyboardHidden
-                + this.navigation + this.orientation;
+                + this.navigation + this.orientation + this.screenLayout;
     }
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index cb9d46e..d7512bb 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1267,7 +1267,8 @@
             }
             if (metrics != null) {
                 mMetrics.setTo(metrics);
-                mMetrics.updateMetrics(mCompatibilityInfo, mConfiguration.orientation);
+                mMetrics.updateMetrics(mCompatibilityInfo,
+                        mConfiguration.orientation, mConfiguration.screenLayout);
             }
             mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
 
@@ -1299,7 +1300,7 @@
                     mConfiguration.touchscreen,
                     (int)(mMetrics.density*160), mConfiguration.keyboard,
                     keyboardHidden, mConfiguration.navigation, width, height,
-                    sSdkVersion);
+                    mConfiguration.screenLayout, sSdkVersion);
             int N = mDrawableCache.size();
             if (DEBUG_CONFIG) {
                 Log.d(TAG, "Cleaning up drawables config changes: 0x"
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index d89ada0..4179edb 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -103,40 +103,43 @@
 
     /**
      * Update the display metrics based on the compatibility info and orientation
+     * NOTE: DO NOT EXPOSE THIS API!  It is introducing a circular dependency
+     * with the higher-level android.res package.
      * {@hide}
      */
-    public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation) {
+    public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation,
+            int screenLayout) {
         int xOffset = 0;
         if (!compatibilityInfo.isConfiguredExpandable()) {
             // Note: this assume that configuration is updated before calling
             // updateMetrics method.
-            int defaultWidth;
-            int defaultHeight;
-            switch (orientation) {
-                case Configuration.ORIENTATION_LANDSCAPE: {
-                    defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
-                    defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
-                    break;
-                }
-                case Configuration.ORIENTATION_PORTRAIT:
-                case Configuration.ORIENTATION_SQUARE:
-                default: {
-                    defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
-                    defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
-                    break;
-                }
-                case Configuration.ORIENTATION_UNDEFINED: {
-                    // don't change
-                    return;
-                }
-            }
-            
-            if (defaultWidth == widthPixels && defaultHeight == heightPixels) {
-                // the screen size is same as expected size. make it expandable
-                compatibilityInfo.setExpandable(true);
-            } else {
+            if (screenLayout == Configuration.SCREENLAYOUT_LARGE) {
+                // This is a large screen device and the app is not 
+                // compatible with large screens, to diddle it.
+                
                 compatibilityInfo.setExpandable(false);
-                // adjust the size only when the device's screen is bigger.
+                // Figure out the compatibility width and height of the screen.
+                int defaultWidth;
+                int defaultHeight;
+                switch (orientation) {
+                    case Configuration.ORIENTATION_LANDSCAPE: {
+                        defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
+                        defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
+                        break;
+                    }
+                    case Configuration.ORIENTATION_PORTRAIT:
+                    case Configuration.ORIENTATION_SQUARE:
+                    default: {
+                        defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
+                        defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
+                        break;
+                    }
+                    case Configuration.ORIENTATION_UNDEFINED: {
+                        // don't change
+                        return;
+                    }
+                }
+                
                 if (defaultWidth < widthPixels) {
                     // content/window's x offset in original pixels
                     xOffset = ((widthPixels - defaultWidth) / 2);
@@ -145,6 +148,10 @@
                 if (defaultHeight < heightPixels) {
                     heightPixels = defaultHeight;
                 }
+                
+            } else {
+                // the screen size is same as expected size. make it expandable
+                compatibilityInfo.setExpandable(true);
             }
         }
         compatibilityInfo.setVisibleRect(xOffset, widthPixels, heightPixels);
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index d147bcc..2d90ba4 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -535,7 +535,7 @@
                                                           jint keyboard, jint keyboardHidden,
                                                           jint navigation,
                                                           jint screenWidth, jint screenHeight,
-                                                          jint sdkVersion)
+                                                          jint screenLayout, jint sdkVersion)
 {
     AssetManager* am = assetManagerForJavaObject(env, clazz);
     if (am == NULL) {
@@ -557,6 +557,7 @@
     config.navigation = (uint8_t)navigation;
     config.screenWidth = (uint16_t)screenWidth;
     config.screenHeight = (uint16_t)screenHeight;
+    config.screenLayout = (uint8_t)screenLayout;
     config.sdkVersion = (uint16_t)sdkVersion;
     config.minorVersion = 0;
     am->setConfiguration(config, locale8);
@@ -1567,7 +1568,7 @@
         (void*) android_content_AssetManager_setLocale },
     { "getLocales",      "()[Ljava/lang/String;",
         (void*) android_content_AssetManager_getLocales },
-    { "setConfiguration", "(IILjava/lang/String;IIIIIIIII)V",
+    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIII)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/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 91cd9fd..7571e24 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -512,6 +512,9 @@
         <!-- The screen orientation has changed, that is the user has
              rotated the device. -->
         <flag name="orientation" value="0x0080" />
+        <!-- The screen orientation has changed, that is the user has
+             rotated the device. -->
+        <flag name="screenLayout" value="0x0100" />
         <!-- The font scaling factor has changed, that is the user has
              selected a new global font size. -->
         <flag name="fontScale" value="0x40000000" />
@@ -829,8 +832,59 @@
          <p>This appears as a child tag of the
          {@link #AndroidManifest manifest} tag. -->
     <declare-styleable name="AndroidManifestSupportsDensity" parent="AndroidManifest">
-        <!-- Required value of the density in dip (device independent pixel). -->
-        <attr name="density" format="integer" />
+        <!-- Required value of the density in dip (device independent pixel).
+             You should use one of the pre-defined constants for the standard
+             screen densities defined here.
+        -->
+        <attr name="density" format="integer">
+            <!-- A low density screen, such as a QVGA or WQVGA screen in a
+                 typical hand-held phone.  The constant for this is 120. -->
+            <enum name="low" value="120" />
+            <!-- A medium density screen, such as an HVGA screen in a
+                 typical hand-held phone.  The constant for this is 160. -->
+            <enum name="medium" value="160" />
+            <!-- A high density screen, such as a VGA or WVGA screen in a
+                 typical hand-held phone.  The constant for this is 240. -->
+            <enum name="high" value="240" />
+        </attr>
+    </declare-styleable>
+
+    <!-- The <code>supports-screens</code> specifies the screen dimensions an
+         application supports.  By default a modern application supports all
+         screen sizes and must explicitly disable certain screen sizes here;
+         older applications are assumed to only support the traditional normal
+         (HVGA) screen size.  Note that screen size is a separate axis from
+         density, and is determined as the available pixels to an application
+         after density scaling has been applied.
+         
+         <p>This appears as a child tag of the
+         {@link #AndroidManifest manifest} tag. -->
+    <declare-styleable name="AndroidManifestSupportsScreens" parent="AndroidManifest">
+        <!-- Indicates whether the application supports smaller screen form-factors.
+             A small screen is defined as one with a smaller aspect ratio than
+             the traditional HVGA screen; that is, for a portrait screen, less
+             tall than an HVGA screen.  In practice, this means a QVGA low
+             density or VGA high density screen.  An application that does
+             not support small screens <em>will not be available</em> for
+             small screen devices, since there is little the platform can do
+             to make such an application work on a smaller screen. -->
+        <attr name="smallScreens" format="boolean" />
+        <!-- Indicates whether an application supports the normal screen
+             form-factors.  Traditionally this is an HVGA normal density
+             screen, but WQVGA low density and WVGA high density are also
+             considered to be normal.  This attribute is true by default,
+             and applications currently should leave it that way. -->
+        <attr name="normalScreens" format="boolean" />
+        <!-- Indicates whether the application supports larger screen form-factors.
+             A large screen is defined as a screen that is significantly larger
+             than a normal phone screen, and thus may require some special care
+             on the application's part to make good use of it.  An example would
+             be a VGA <em>normal density</em> screen, though even larger screens
+             are certainly possible.  An application that does not support
+             large screens will be placed as a postage stamp on such a
+             screen, so that it retains the dimensions it was originally
+             designed for. -->
+        <attr name="largeScreens" format="boolean" />
     </declare-styleable>
 
     <!-- The <code>expandable</code> specifies if this package supports screen metrics
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 4634b50..14d8dbe 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1117,6 +1117,9 @@
   <public type="attr" name="glEsVersion" />
   <public type="attr" name="queryAfterZeroResults" />
   <public type="attr" name="dropDownHeight" />
+  <public type="attr" name="smallScreens" />
+  <public type="attr" name="normalScreens" />
+  <public type="attr" name="largeScreens" />
 
   <public-padding type="attr" name="donut_resource_pad" end="0x0101029f" />
 
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index f1029b7..5c41ead 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -866,7 +866,7 @@
             uint8_t keyboard;
             uint8_t navigation;
             uint8_t inputFlags;
-            uint8_t pad0;
+            uint8_t inputPad0;
         };
         uint32_t input;
     };
@@ -905,6 +905,23 @@
         uint32_t version;
     };
     
+    enum {
+        SCREENLAYOUT_ANY  = 0x0000,
+        SCREENLAYOUT_SMALL = 0x0001,
+        SCREENLAYOUT_NORMAL = 0x0002,
+        SCREENLAYOUT_LARGE = 0x0003,
+    };
+    
+    union {
+        struct {
+            uint8_t screenLayout;
+            uint8_t screenConfigPad0;
+            uint8_t screenConfigPad1;
+            uint8_t screenConfigPad2;
+        };
+        uint32_t screenConfig;
+    };
+    
     inline void copyFromDeviceNoSwap(const ResTable_config& o) {
         const size_t size = dtohl(o.size);
         if (size >= sizeof(ResTable_config)) {
@@ -950,6 +967,8 @@
         diff = (int32_t)(screenSize - o.screenSize);
         if (diff != 0) return diff;
         diff = (int32_t)(version - o.version);
+        if (diff != 0) return diff;
+        diff = (int32_t)(screenLayout - o.screenLayout);
         return (int)diff;
     }
     
@@ -967,7 +986,8 @@
         CONFIG_ORIENTATION = 0x0080,
         CONFIG_DENSITY = 0x0100,
         CONFIG_SCREEN_SIZE = 0x0200,
-        CONFIG_VERSION = 0x0400
+        CONFIG_VERSION = 0x0400,
+        CONFIG_SCREEN_LAYOUT = 0x0800
     };
     
     // Compare two configuration, returning CONFIG_* flags set for each value
@@ -985,6 +1005,7 @@
         if (navigation != o.navigation) diffs |= CONFIG_NAVIGATION;
         if (screenSize != o.screenSize) diffs |= CONFIG_SCREEN_SIZE;
         if (version != o.version) diffs |= CONFIG_VERSION;
+        if (screenLayout != o.screenLayout) diffs |= CONFIG_SCREEN_LAYOUT;
         return diffs;
     }
     
@@ -1062,6 +1083,13 @@
             }
         }
 
+        if (screenConfig || o.screenConfig) {
+            if (screenLayout != o.screenLayout) {
+                if (!screenLayout) return false;
+                if (!o.screenLayout) return true;
+            }
+        }
+
         if (version || o.version) {
             if (sdkVersion != o.sdkVersion) {
                 if (!sdkVersion) return false;
@@ -1191,6 +1219,12 @@
                 }
             }
 
+            if (screenConfig || o.screenConfig) {
+                if ((screenLayout != o.screenLayout) && requested->screenLayout) {
+                    return (screenLayout);
+                }
+            }
+
             if (version || o.version) {
                 if ((sdkVersion != o.sdkVersion) && requested->sdkVersion) {
                     return (sdkVersion);
@@ -1282,6 +1316,12 @@
                 return false;
             }
         }
+        if (screenConfig != 0) {
+            if (settings.screenLayout != 0 && screenLayout != 0
+                && screenLayout != settings.screenLayout) {
+                return false;
+            }
+        }
         if (version != 0) {
             if (settings.sdkVersion != 0 && sdkVersion != 0
                 && sdkVersion != settings.sdkVersion) {
@@ -1310,13 +1350,13 @@
 
     String8 toString() const {
         char buf[200];
-        sprintf(buf, "imsi=%d/%d lang=%c%c reg=%c%c orient=0x%02x touch=0x%02x dens=0x%02x "
-                "kbd=0x%02x nav=0x%02x input=0x%02x screenW=0x%04x screenH=0x%04x vers=%d.%d",
+        sprintf(buf, "imsi=%d/%d lang=%c%c reg=%c%c orient=%d touch=%d dens=%d "
+                "kbd=%d nav=%d input=%d scrnW=%d scrnH=%d layout=%d vers=%d.%d",
                 mcc, mnc,
                 language[0] ? language[0] : '-', language[1] ? language[1] : '-',
                 country[0] ? country[0] : '-', country[1] ? country[1] : '-',
                 orientation, touchscreen, density, keyboard, navigation, inputFlags,
-                screenWidth, screenHeight, sdkVersion, minorVersion);
+                screenWidth, screenHeight, screenLayout, sdkVersion, minorVersion);
         return String8(buf);
     }
 };
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index e4f9f0f..7a33220 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -3919,7 +3919,7 @@
                         printf("      NON-INTEGER ResTable_type ADDRESS: %p\n", type);
                         continue;
                     }
-                    printf("      config %d lang=%c%c cnt=%c%c orien=%d touch=%d density=%d key=%d infl=%d nav=%d w=%d h=%d\n",
+                    printf("      config %d lang=%c%c cnt=%c%c orien=%d touch=%d density=%d key=%d infl=%d nav=%d w=%d h=%d lyt=%d\n",
                            (int)configIndex,
                            type->config.language[0] ? type->config.language[0] : '-',
                            type->config.language[1] ? type->config.language[1] : '-',
@@ -3932,7 +3932,8 @@
                            type->config.inputFlags,
                            type->config.navigation,
                            dtohs(type->config.screenWidth),
-                           dtohs(type->config.screenHeight));
+                           dtohs(type->config.screenHeight),
+                           type->config.screenLayout);
                     size_t entryCount = dtohl(type->entryCount);
                     uint32_t entriesStart = dtohl(type->entriesStart);
                     if ((entriesStart&0x3) != 0) {
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index fef3598..68bf4fb 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -504,6 +504,7 @@
                 if (mPhoneMemMonitor.checkLocked(curTime, mPhonePid,
                         mPhonePss)) {
                     // Just kill the phone process and let it restart.
+                    Log.i(TAG, "Watchdog is killing the phone process");
                     Process.killProcess(mPhonePid);
                 }
             } else {
@@ -848,6 +849,7 @@
 
             // Only kill the process if the debugger is not attached.
             if (!Debug.isDebuggerConnected()) {
+                Log.i(TAG, "Watchdog is killing the system process");
                 Process.killProcess(Process.myPid());
             }
         }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 3b47ae7..5ea7504 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -77,6 +77,7 @@
 import android.os.SystemProperties;
 import android.os.TokenWatcher;
 import android.provider.Settings;
+import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.SparseIntArray;
@@ -415,7 +416,8 @@
     final Rect mTempRect = new Rect();
 
     final Configuration mTempConfiguration = new Configuration();
-
+    int screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
+    
     public static WindowManagerService main(Context context,
             PowerManagerService pm, boolean haveInputMethods) {
         WMThread thr = new WMThread(context, pm, haveInputMethods);
@@ -3724,6 +3726,40 @@
             orientation = Configuration.ORIENTATION_LANDSCAPE;
         }
         config.orientation = orientation;
+        
+        if (screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
+            // Note we only do this once because at this point we don't
+            // expect the screen to change in this way at runtime, and want
+            // to avoid all of this computation for every config change.
+            DisplayMetrics dm = new DisplayMetrics();
+            mDisplay.getMetrics(dm);
+            int longSize = dw;
+            int shortSize = dh;
+            if (longSize < shortSize) {
+                int tmp = longSize;
+                longSize = shortSize;
+                shortSize = tmp;
+            }
+            longSize = (int)(longSize/dm.density);
+            shortSize = (int)(shortSize/dm.density);
+            
+            // These semi-magic numbers define our compatibility modes for
+            // applications with different screens.  Don't change unless you
+            // make sure to test lots and lots of apps!
+            if (longSize < 470) {
+                // This is shorter than an HVGA normal density screen (which
+                // is 480 pixels on its long side).
+                screenLayout = Configuration.SCREENLAYOUT_SMALL;
+            } else if (longSize > 490 && shortSize > 330) {
+                // This is larger than an HVGA normal density screen (which
+                // is 480x320 pixels).
+                screenLayout = Configuration.SCREENLAYOUT_LARGE;
+            } else {
+                screenLayout = Configuration.SCREENLAYOUT_NORMAL;
+            }
+        }
+        config.screenLayout = screenLayout;
+        
         config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
         config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
         mPolicy.adjustConfigurationLw(config);
diff --git a/tests/DpiTest/AndroidManifest.xml b/tests/DpiTest/AndroidManifest.xml
index f71cff2..64ad7be 100644
--- a/tests/DpiTest/AndroidManifest.xml
+++ b/tests/DpiTest/AndroidManifest.xml
@@ -16,6 +16,8 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.google.android.test.dpi">
+    <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="3" />
+    <supports-screens android:smallScreens="true" />
     <application android:label="DpiTest">
         <activity android:name="DpiTestActivity" android:label="DpiTest">
             <intent-filter>
diff --git a/tests/DpiTest/res/values-largeScreen/strings.xml b/tests/DpiTest/res/values-largeScreen/strings.xml
new file mode 100644
index 0000000..f4dd543
--- /dev/null
+++ b/tests/DpiTest/res/values-largeScreen/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="act_title">DpiTest: Large Screen</string>
+</resources>
diff --git a/tests/DpiTest/res/values-normalScreen/strings.xml b/tests/DpiTest/res/values-normalScreen/strings.xml
new file mode 100644
index 0000000..256d696
--- /dev/null
+++ b/tests/DpiTest/res/values-normalScreen/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="act_title">DpiTest: Normal Screen</string>
+</resources>
diff --git a/tests/DpiTest/res/values-smallScreen/strings.xml b/tests/DpiTest/res/values-smallScreen/strings.xml
new file mode 100644
index 0000000..cdb4ac9
--- /dev/null
+++ b/tests/DpiTest/res/values-smallScreen/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="act_title">DpiTest: Small Screen</string>
+</resources>
diff --git a/tests/DpiTest/res/values/strings.xml b/tests/DpiTest/res/values/strings.xml
new file mode 100644
index 0000000..ef924ac
--- /dev/null
+++ b/tests/DpiTest/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="act_title">DpiTest: Unknown Screen</string>
+</resources>
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 3759622..5a9f3f5 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 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        this.setTitle(R.string.act_title);
         LinearLayout root = new LinearLayout(this);
         root.setOrientation(LinearLayout.VERTICAL);
 
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 6bc1ee6..67af116 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -187,6 +187,13 @@
         return 0;
     }
 
+    // screen layout
+    if (getScreenLayoutName(part.string(), &config)) {
+        *axis = AXIS_SCREENLAYOUT;
+        *value = config.screenLayout;
+        return 0;
+    }
+
     // version
     if (getVersionName(part.string(), &config)) {
         *axis = AXIS_VERSION;
@@ -202,7 +209,7 @@
 {
     Vector<String8> parts;
 
-    String8 mcc, mnc, loc, orient, den, touch, key, keysHidden, nav, size, vers;
+    String8 mcc, mnc, loc, orient, den, touch, key, keysHidden, nav, size, layout, vers;
 
     const char *p = dir;
     const char *q;
@@ -378,6 +385,18 @@
         //printf("not screen size: %s\n", part.string());
     }
 
+    if (getScreenLayoutName(part.string())) {
+        layout = part;
+
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index];
+    } else {
+        //printf("not screen layout: %s\n", part.string());
+    }
+
     if (getVersionName(part.string())) {
         vers = part;
 
@@ -404,6 +423,7 @@
     this->keyboard = key;
     this->navigation = nav;
     this->screenSize = size;
+    this->screenLayout = layout;
     this->version = vers;
 
     // what is this anyway?
@@ -435,6 +455,8 @@
     s += ",";
     s += screenSize;
     s += ",";
+    s += screenLayout;
+    s += ",";
     s += version;
     return s;
 }
@@ -483,6 +505,10 @@
         s += "-";
         s += screenSize;
     }
+    if (this->screenLayout != "") {
+        s += "-";
+        s += screenLayout;
+    }
     if (this->version != "") {
         s += "-";
         s += version;
@@ -786,6 +812,26 @@
     return true;
 }
 
+bool AaptGroupEntry::getScreenLayoutName(const char* name,
+                                     ResTable_config* out)
+{
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->screenLayout = out->SCREENLAYOUT_ANY;
+        return true;
+    } else if (strcmp(name, "smallscreen") == 0) {
+        if (out) out->screenLayout = out->SCREENLAYOUT_SMALL;
+        return true;
+    } else if (strcmp(name, "normalscreen") == 0) {
+        if (out) out->screenLayout = out->SCREENLAYOUT_NORMAL;
+        return true;
+    } else if (strcmp(name, "largescreen") == 0) {
+        if (out) out->screenLayout = out->SCREENLAYOUT_LARGE;
+        return true;
+    }
+
+    return false;
+}
+
 bool AaptGroupEntry::getVersionName(const char* name,
                                     ResTable_config* out)
 {
@@ -828,6 +874,7 @@
     if (v == 0) v = keyboard.compare(o.keyboard);
     if (v == 0) v = navigation.compare(o.navigation);
     if (v == 0) v = screenSize.compare(o.screenSize);
+    if (v == 0) v = screenLayout.compare(o.screenLayout);
     if (v == 0) v = version.compare(o.version);
     return v;
 }
@@ -846,6 +893,7 @@
     getKeyboardName(keyboard.string(), &params);
     getNavigationName(navigation.string(), &params);
     getScreenSizeName(screenSize.string(), &params);
+    getScreenLayoutName(screenLayout.string(), &params);
     getVersionName(version.string(), &params);
     return params;
 }
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 01c8140..3b96412 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -37,6 +37,7 @@
     AXIS_KEYBOARD,
     AXIS_NAVIGATION,
     AXIS_SCREENSIZE,
+    AXIS_SCREENLAYOUT,
     AXIS_VERSION
 };
 
@@ -62,6 +63,7 @@
     String8 keyboard;
     String8 navigation;
     String8 screenSize;
+    String8 screenLayout;
     String8 version;
 
     bool initFromDirName(const char* dir, String8* resType);
@@ -78,6 +80,7 @@
     static bool getKeyboardName(const char* name, ResTable_config* out = NULL);
     static bool getNavigationName(const char* name, ResTable_config* out = NULL);
     static bool getScreenSizeName(const char* name, ResTable_config* out = NULL);
+    static bool getScreenLayoutName(const char* name, ResTable_config* out = NULL);
     static bool getVersionName(const char* name, ResTable_config* out = NULL);
 
     int compare(const AaptGroupEntry& o) const;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 503f661..e04491d 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -329,6 +329,9 @@
     TARGET_SDK_VERSION_ATTR = 0x01010270,
     TEST_ONLY_ATTR = 0x01010272,
     DENSITY_ATTR = 0x0101026c,
+    SMALL_SCREEN_ATTR = 0x01010284,
+    NORMAL_SCREEN_ATTR = 0x01010285,
+    LARGE_SCREEN_ATTR = 0x01010286,
 };
 
 const char *getComponentName(String8 &pkgName, String8 &componentName) {
@@ -499,6 +502,10 @@
             bool isLauncherActivity = false;
             bool withinApplication = false;
             bool withinReceiver = false;
+            int targetSdk = 0;
+            int smallScreen = 1;
+            int normalScreen = 1;
+            int largeScreen = 1;
             String8 pkg;
             String8 activityName;
             String8 activityLabel;
@@ -572,8 +579,10 @@
                                         error.string());
                                 goto bail;
                             }
+                            if (name == "Donut") targetSdk = 4;
                             printf("sdkVersion:'%s'\n", name.string());
                         } else if (code != -1) {
+                            targetSdk = code;
                             printf("sdkVersion:'%d'\n", code);
                         }
                         code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error);
@@ -585,8 +594,12 @@
                                         error.string());
                                 goto bail;
                             }
+                            if (name == "Donut" && targetSdk < 4) targetSdk = 4;
                             printf("targetSdkVersion:'%s'\n", name.string());
                         } else if (code != -1) {
+                            if (targetSdk < code) {
+                                targetSdk = code;
+                            }
                             printf("targetSdkVersion:'%d'\n", code);
                         }
                     } else if (tag == "uses-configuration") {
@@ -625,6 +638,13 @@
                             goto bail;
                         }
                         printf("supports-density:'%d'\n", dens);
+                    } else if (tag == "supports-screens") {
+                        smallScreen = getIntegerAttribute(tree,
+                                SMALL_SCREEN_ATTR, NULL, 1);
+                        normalScreen = getIntegerAttribute(tree,
+                                NORMAL_SCREEN_ATTR, NULL, 1);
+                        largeScreen = getIntegerAttribute(tree,
+                                LARGE_SCREEN_ATTR, NULL, 1);
                     }
                 } else if (depth == 3 && withinApplication) {
                     withinActivity = false;
@@ -733,6 +753,25 @@
                 }
             }
             
+            // Determine default values for any unspecified screen sizes,
+            // based on the target SDK of the package.  As of 4 (donut)
+            // the screen size support was introduced, so all default to
+            // enabled.
+            if (smallScreen > 0) {
+                smallScreen = targetSdk >= 4 ? -1 : 0;
+            }
+            if (normalScreen > 0) {
+                normalScreen = -1;
+            }
+            if (largeScreen > 0) {
+                largeScreen = targetSdk >= 4 ? -1 : 0;
+            }
+            printf("supports-screens:");
+            if (smallScreen != 0) printf(" 'small'");
+            if (normalScreen != 0) printf(" 'normal'");
+            if (largeScreen != 0) printf(" 'large'");
+            printf("\n");
+            
             printf("locales:");
             Vector<String8> locales;
             res.getLocales(&locales);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
index 1fa11af..06dd96f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
@@ -59,7 +59,7 @@
     public 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 version)  {
+            int screenLayout, int version)  {
         
         Configuration c = new Configuration();
         c.mcc = mcc;
@@ -70,5 +70,6 @@
         c.keyboardHidden = keyboardHidden;
         c.navigation = navigation;
         c.orientation = orientation;
+        c.screenLayout = screenLayout;
     }
 }