Merge change 8109

* changes:
  Add a flag to set whether the overlay has been initialized.  Commit needs to be called at least once on each overlay, and it appears that sometimes this doesn't happen because the visibility never changes.  With this change the overlay parameter and position will be committed when either the visibility of the window changes, or on the first call to visibility resolved, if it hasn't already been done.
diff --git a/api/current.xml b/api/current.xml
index 3e3a855..9248ccb 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -2297,6 +2297,17 @@
  visibility="public"
 >
 </field>
+<field name="anyDensity"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843372"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="apiKey"
  type="int"
  transient="false"
@@ -3155,17 +3166,6 @@
  visibility="public"
 >
 </field>
-<field name="density"
- type="int"
- transient="false"
- volatile="false"
- value="16843372"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="dependency"
  type="int"
  transient="false"
@@ -3463,17 +3463,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad19"
- type="int"
- transient="false"
- volatile="false"
- value="16843405"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="donut_resource_pad2"
  type="int"
  transient="false"
@@ -7038,6 +7027,17 @@
  visibility="public"
 >
 </field>
+<field name="resizeable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843405"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="resource"
  type="int"
  transient="false"
@@ -25978,6 +25978,50 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_DATA_KEY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;intent_extra_data_key&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INTENT_ACTION_SEARCHABLES_CHANGED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.search.action.SEARCHABLES_CHANGED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INTENT_ACTION_SEARCH_SETTINGS_CHANGED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.search.action.SETTINGS_CHANGED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INTENT_ACTION_WEB_SEARCH_SETTINGS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.search.action.WEB_SEARCH_SETTINGS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MENU_KEY"
  type="char"
  transient="false"
@@ -26011,6 +26055,17 @@
  visibility="public"
 >
 </field>
+<field name="SHORTCUT_MIME_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;vnd.android.cursor.item/vnd.android.search.suggest&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SUGGEST_COLUMN_FORMAT"
  type="java.lang.String"
  transient="false"
@@ -26077,6 +26132,17 @@
  visibility="public"
 >
 </field>
+<field name="SUGGEST_COLUMN_INTENT_EXTRA_DATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;suggest_intent_extra_data&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SUGGEST_COLUMN_QUERY"
  type="java.lang.String"
  transient="false"
@@ -26088,6 +26154,28 @@
  visibility="public"
 >
 </field>
+<field name="SUGGEST_COLUMN_SHORTCUT_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;suggest_shortcut_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;suggest_spinner_while_refreshing&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SUGGEST_COLUMN_TEXT_1"
  type="java.lang.String"
  transient="false"
@@ -26121,6 +26209,17 @@
  visibility="public"
 >
 </field>
+<field name="SUGGEST_NEVER_MAKE_SHORTCUT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;_-1&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SUGGEST_URI_PATH_QUERY"
  type="java.lang.String"
  transient="false"
@@ -26132,6 +26231,17 @@
  visibility="public"
 >
 </field>
+<field name="SUGGEST_URI_PATH_SHORTCUT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;search_suggest_shortcut&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="USER_QUERY"
  type="java.lang.String"
  transient="false"
@@ -39032,6 +39142,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_RESIZEABLE_FOR_SCREENS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4096"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_SUPPORTS_LARGE_SCREENS"
  type="int"
  transient="false"
@@ -39054,6 +39175,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_SUPPORTS_SCREEN_DENSITIES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8192"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_SUPPORTS_SMALL_SCREENS"
  type="int"
  transient="false"
@@ -39209,17 +39341,6 @@
  visibility="public"
 >
 </field>
-<field name="supportsDensities"
- type="int[]"
- transient="false"
- volatile="false"
- value="null"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="targetSdkVersion"
  type="int"
  transient="false"
@@ -41131,17 +41252,6 @@
  visibility="public"
 >
 </field>
-<field name="GET_SUPPORTS_DENSITIES"
- type="int"
- transient="false"
- volatile="false"
- value="32768"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="GET_UNINSTALLED_PACKAGES"
  type="int"
  transient="false"
@@ -43348,7 +43458,51 @@
  visibility="public"
 >
 </field>
-<field name="SCREENLAYOUT_LARGE"
+<field name="SCREENLAYOUT_LONG_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="48"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREENLAYOUT_LONG_NO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREENLAYOUT_LONG_UNDEFINED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREENLAYOUT_LONG_YES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREENLAYOUT_SIZE_LARGE"
  type="int"
  transient="false"
  volatile="false"
@@ -43359,7 +43513,18 @@
  visibility="public"
 >
 </field>
-<field name="SCREENLAYOUT_NORMAL"
+<field name="SCREENLAYOUT_SIZE_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="15"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCREENLAYOUT_SIZE_NORMAL"
  type="int"
  transient="false"
  volatile="false"
@@ -43370,7 +43535,7 @@
  visibility="public"
 >
 </field>
-<field name="SCREENLAYOUT_SMALL"
+<field name="SCREENLAYOUT_SIZE_SMALL"
  type="int"
  transient="false"
  volatile="false"
@@ -43381,7 +43546,7 @@
  visibility="public"
 >
 </field>
-<field name="SCREENLAYOUT_UNDEFINED"
+<field name="SCREENLAYOUT_SIZE_UNDEFINED"
  type="int"
  transient="false"
  volatile="false"
@@ -144426,6 +144591,21 @@
 <parameter name="pos" type="int">
 </parameter>
 </method>
+<method name="getHistoricalPressure"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointer" type="int">
+</parameter>
+<parameter name="pos" type="int">
+</parameter>
+</method>
 <method name="getHistoricalSize"
  return="float"
  abstract="false"
@@ -144439,6 +144619,34 @@
 <parameter name="pos" type="int">
 </parameter>
 </method>
+<method name="getHistoricalSize"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointer" type="int">
+</parameter>
+<parameter name="pos" type="int">
+</parameter>
+</method>
+<method name="getHistoricalX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pos" type="int">
+</parameter>
+</method>
 <method name="getHistoricalX"
  return="float"
  abstract="false"
@@ -144449,6 +144657,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="pointer" type="int">
+</parameter>
 <parameter name="pos" type="int">
 </parameter>
 </method>
@@ -144465,6 +144675,21 @@
 <parameter name="pos" type="int">
 </parameter>
 </method>
+<method name="getHistoricalY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointer" type="int">
+</parameter>
+<parameter name="pos" type="int">
+</parameter>
+</method>
 <method name="getHistorySize"
  return="int"
  abstract="false"
@@ -144487,6 +144712,17 @@
  visibility="public"
 >
 </method>
+<method name="getPointerCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getPressure"
  return="float"
  abstract="false"
@@ -144498,6 +144734,19 @@
  visibility="public"
 >
 </method>
+<method name="getPressure"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointer" type="int">
+</parameter>
+</method>
 <method name="getRawX"
  return="float"
  abstract="false"
@@ -144531,6 +144780,19 @@
  visibility="public"
 >
 </method>
+<method name="getSize"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointer" type="int">
+</parameter>
+</method>
 <method name="getX"
  return="float"
  abstract="false"
@@ -144542,6 +144804,19 @@
  visibility="public"
 >
 </method>
+<method name="getX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointer" type="int">
+</parameter>
+</method>
 <method name="getXPrecision"
  return="float"
  abstract="false"
@@ -144564,6 +144839,19 @@
  visibility="public"
 >
 </method>
+<method name="getY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pointer" type="int">
+</parameter>
+</method>
 <method name="getYPrecision"
  return="float"
  abstract="false"
@@ -144626,6 +144914,43 @@
 </parameter>
 <parameter name="action" type="int">
 </parameter>
+<parameter name="pointers" type="int">
+</parameter>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="pressure" type="float">
+</parameter>
+<parameter name="size" type="float">
+</parameter>
+<parameter name="metaState" type="int">
+</parameter>
+<parameter name="xPrecision" type="float">
+</parameter>
+<parameter name="yPrecision" type="float">
+</parameter>
+<parameter name="deviceId" type="int">
+</parameter>
+<parameter name="edgeFlags" type="int">
+</parameter>
+</method>
+<method name="obtain"
+ return="android.view.MotionEvent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="downTime" type="long">
+</parameter>
+<parameter name="eventTime" type="long">
+</parameter>
+<parameter name="action" type="int">
+</parameter>
 <parameter name="x" type="float">
 </parameter>
 <parameter name="y" type="float">
@@ -144750,6 +145075,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="255"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_MOVE"
  type="int"
  transient="false"
@@ -144772,6 +145108,116 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_POINTER_1_DOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POINTER_1_UP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POINTER_2_DOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="261"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POINTER_2_UP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="262"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POINTER_3_DOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="517"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POINTER_3_UP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="518"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POINTER_DOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POINTER_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="65280"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POINTER_SHIFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POINTER_UP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_UP"
  type="int"
  transient="false"
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 3782136..0b4f25e 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -23,16 +23,19 @@
 import android.app.IInstrumentationWatcher;
 import android.app.Instrumentation;
 import android.content.ComponentName;
+import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.util.AndroidException;
 import android.view.IWindowManager;
 
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
 import java.util.Iterator;
 import java.util.Set;
 
@@ -45,16 +48,29 @@
 
     private boolean mDebugOption = false;
 
+    // These are magic strings understood by the Eclipse plugin.
+    private static final String FATAL_ERROR_CODE = "Error type 1";
+    private static final String NO_SYSTEM_ERROR_CODE = "Error type 2";
+    private static final String NO_CLASS_ERROR_CODE = "Error type 3";
+
     /**
      * Command-line entry point.
      *
      * @param args The command-line arguments
      */
     public static void main(String[] args) {
-        (new Am()).run(args);
+        try {
+            (new Am()).run(args);
+        } catch (IllegalArgumentException e) {
+            showUsage();
+            System.err.println("Error: " + e.getMessage());
+        } catch (Exception e) {
+            System.err.println(e.toString());
+            System.exit(1);
+        }
     }
 
-    private void run(String[] args) {
+    private void run(String[] args) throws Exception {
         if (args.length < 1) {
             showUsage();
             return;
@@ -62,16 +78,14 @@
 
         mAm = ActivityManagerNative.getDefault();
         if (mAm == null) {
-            System.err.println("Error type 2");
-            System.err.println("Error: Unable to connect to activity manager; is the system running?");
-            showUsage();
-            return;
+            System.err.println(NO_SYSTEM_ERROR_CODE);
+            throw new AndroidException("Can't connect to activity manager; is the system running?");
         }
 
         mArgs = args;
-
         String op = args[0];
         mNextArg = 1;
+
         if (op.equals("start")) {
             runStart();
         } else if (op.equals("instrument")) {
@@ -81,13 +95,11 @@
         } else if (op.equals("profile")) {
             runProfile();
         } else {
-            System.err.println("Error: Unknown command: " + op);
-            showUsage();
-            return;
+            throw new IllegalArgumentException("Unknown command: " + op);
         }
     }
 
-    private Intent makeIntent() {
+    private Intent makeIntent() throws URISyntaxException {
         Intent intent = new Intent();
         boolean hasIntentInfo = false;
 
@@ -95,186 +107,146 @@
         Uri data = null;
         String type = null;
 
-        try {
-            String opt;
-            while ((opt=nextOption()) != null) {
-                if (opt.equals("-a")) {
-                    intent.setAction(nextOptionData());
-                    hasIntentInfo = true;
-                } else if (opt.equals("-d")) {
-                    data = Uri.parse(nextOptionData());
-                    hasIntentInfo = true;
-                } else if (opt.equals("-t")) {
-                    type = nextOptionData();
-                    hasIntentInfo = true;
-                } else if (opt.equals("-c")) {
-                    intent.addCategory(nextOptionData());
-                    hasIntentInfo = true;
-                } else if (opt.equals("-e") || opt.equals("--es")) {
-                    String key = nextOptionData();
-                    String value = nextOptionData();
-                    intent.putExtra(key, value);
-                    hasIntentInfo = true;
-                } else if (opt.equals("--ei")) {
-                    String key = nextOptionData();
-                    String value = nextOptionData();
-                    intent.putExtra(key, Integer.valueOf(value));
-                    hasIntentInfo = true;
-                } else if (opt.equals("--ez")) {
-                    String key = nextOptionData();
-                    String value = nextOptionData();
-                    intent.putExtra(key, Boolean.valueOf(value));
-                    hasIntentInfo = true;
-                } else if (opt.equals("-n")) {
-                    String str = nextOptionData();
-                    ComponentName cn = ComponentName.unflattenFromString(str);
-                    if (cn == null) {
-                        System.err.println("Error: Bad component name: " + str);
-                        showUsage();
-                        return null;
-                    }
-                    intent.setComponent(cn);
-                    hasIntentInfo = true;
-                } else if (opt.equals("-f")) {
-                    String str = nextOptionData();
-                    intent.setFlags(Integer.decode(str).intValue());
-                } else if (opt.equals("-D")) {
-                    mDebugOption = true;
-                } else {
-                    System.err.println("Error: Unknown option: " + opt);
-                    showUsage();
-                    return null;
-                }
+        String opt;
+        while ((opt=nextOption()) != null) {
+            if (opt.equals("-a")) {
+                intent.setAction(nextArgRequired());
+                hasIntentInfo = true;
+            } else if (opt.equals("-d")) {
+                data = Uri.parse(nextArgRequired());
+                hasIntentInfo = true;
+            } else if (opt.equals("-t")) {
+                type = nextArgRequired();
+                hasIntentInfo = true;
+            } else if (opt.equals("-c")) {
+                intent.addCategory(nextArgRequired());
+                hasIntentInfo = true;
+            } else if (opt.equals("-e") || opt.equals("--es")) {
+                String key = nextArgRequired();
+                String value = nextArgRequired();
+                intent.putExtra(key, value);
+                hasIntentInfo = true;
+            } else if (opt.equals("--ei")) {
+                String key = nextArgRequired();
+                String value = nextArgRequired();
+                intent.putExtra(key, Integer.valueOf(value));
+                hasIntentInfo = true;
+            } else if (opt.equals("--ez")) {
+                String key = nextArgRequired();
+                String value = nextArgRequired();
+                intent.putExtra(key, Boolean.valueOf(value));
+                hasIntentInfo = true;
+            } else if (opt.equals("-n")) {
+                String str = nextArgRequired();
+                ComponentName cn = ComponentName.unflattenFromString(str);
+                if (cn == null) throw new IllegalArgumentException("Bad component name: " + str);
+                intent.setComponent(cn);
+                hasIntentInfo = true;
+            } else if (opt.equals("-f")) {
+                String str = nextArgRequired();
+                intent.setFlags(Integer.decode(str).intValue());
+            } else if (opt.equals("-D")) {
+                mDebugOption = true;
+            } else {
+                System.err.println("Error: Unknown option: " + opt);
+                showUsage();
+                return null;
             }
-        } catch (RuntimeException ex) {
-            System.err.println("Error: " + ex.toString());
-            showUsage();
-            return null;
         }
         intent.setDataAndType(data, type);
 
         String uri = nextArg();
         if (uri != null) {
-            try {
-                Intent oldIntent = intent;
-                try {
-                    intent = Intent.getIntent(uri);
-                } catch (java.net.URISyntaxException ex) {
-                    System.err.println("Bad URI: " + uri);
-                    showUsage();
-                    return null;
-                }
-                if (oldIntent.getAction() != null) {
-                    intent.setAction(oldIntent.getAction());
-                }
-                if (oldIntent.getData() != null || oldIntent.getType() != null) {
-                    intent.setDataAndType(oldIntent.getData(), oldIntent.getType());
-                }
-                Set cats = oldIntent.getCategories();
-                if (cats != null) {
-                    Iterator it = cats.iterator();
-                    while (it.hasNext()) {
-                        intent.addCategory((String)it.next());
-                    }
-                }
-            } catch (RuntimeException ex) {
-                System.err.println("Error creating from URI: " + ex.toString());
-                showUsage();
-                return null;
+            Intent oldIntent = intent;
+            intent = Intent.getIntent(uri);
+            if (oldIntent.getAction() != null) {
+                intent.setAction(oldIntent.getAction());
             }
-        } else if (!hasIntentInfo) {
-            System.err.println("Error: No intent supplied");
-            showUsage();
-            return null;
+            if (oldIntent.getData() != null || oldIntent.getType() != null) {
+                intent.setDataAndType(oldIntent.getData(), oldIntent.getType());
+            }
+            Set cats = oldIntent.getCategories();
+            if (cats != null) {
+                Iterator it = cats.iterator();
+                while (it.hasNext()) {
+                    intent.addCategory((String)it.next());
+                }
+            }
+            hasIntentInfo = true;
         }
 
+        if (!hasIntentInfo) throw new IllegalArgumentException("No intent supplied");
         return intent;
     }
 
-    private void runStart() {
+    private void runStart() throws Exception {
         Intent intent = makeIntent();
-        
-        if (intent != null) {
-            System.out.println("Starting: " + intent);
-            try {
-                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                // XXX should do something to determine the MIME type.
-                int res = mAm.startActivity(null, intent, intent.getType(),
-                        null, 0, null, null, 0, false, mDebugOption);
-                switch (res) {
-                    case IActivityManager.START_SUCCESS:
-                        break;
-                    case IActivityManager.START_SWITCHES_CANCELED:
-                        System.err.println(
-                                "Warning: Activity not started because the "
-                                + " current activity is being kept for the user.");
-                        break;
-                    case IActivityManager.START_DELIVERED_TO_TOP:
-                        System.err.println(
-                                "Warning: Activity not started, intent has "
-                                + "been delivered to currently running "
-                                + "top-most instance.");
-                        break;
-                    case IActivityManager.START_RETURN_INTENT_TO_CALLER:
-                        System.err.println(
-                                "Warning: Activity not started because intent "
-                                + "should be handled by the caller");
-                        break;
-                    case IActivityManager.START_TASK_TO_FRONT:
-                        System.err.println(
-                                "Warning: Activity not started, its current "
-                                + "task has been brought to the front");
-                        break;
-                    case IActivityManager.START_INTENT_NOT_RESOLVED:
-                        System.err.println(
-                                "Error: Activity not started, unable to "
-                                + "resolve " + intent.toString());
-                        break;
-                    case IActivityManager.START_CLASS_NOT_FOUND:
-                        System.err.println("Error type 3");
-                        System.err.println("Error: Activity class " +
-                                intent.getComponent().toShortString()
-                                + " does not exist.");
-                        break;
-                    case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
-                        System.err.println(
-                                "Error: Activity not started, you requested to "
-                                + "both forward and receive its result");
-                        break;
-                    case IActivityManager.START_PERMISSION_DENIED:
-                        System.err.println(
-                                "Error: Activity not started, you do not "
-                                + "have permission to access it.");
-                        break;
-                    default:
-                        System.err.println(
-                                "Error: Activity not started, unknown error "
-                                + "code " + res);
-                        break;
-                }
-            } catch (RemoteException e) {
-                System.err.println("Error type 1");
+        System.out.println("Starting: " + intent);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        // XXX should do something to determine the MIME type.
+        int res = mAm.startActivity(null, intent, intent.getType(),
+                null, 0, null, null, 0, false, mDebugOption);
+        switch (res) {
+            case IActivityManager.START_SUCCESS:
+                break;
+            case IActivityManager.START_SWITCHES_CANCELED:
+                System.err.println(
+                        "Warning: Activity not started because the "
+                        + " current activity is being kept for the user.");
+                break;
+            case IActivityManager.START_DELIVERED_TO_TOP:
+                System.err.println(
+                        "Warning: Activity not started, intent has "
+                        + "been delivered to currently running "
+                        + "top-most instance.");
+                break;
+            case IActivityManager.START_RETURN_INTENT_TO_CALLER:
+                System.err.println(
+                        "Warning: Activity not started because intent "
+                        + "should be handled by the caller");
+                break;
+            case IActivityManager.START_TASK_TO_FRONT:
+                System.err.println(
+                        "Warning: Activity not started, its current "
+                        + "task has been brought to the front");
+                break;
+            case IActivityManager.START_INTENT_NOT_RESOLVED:
                 System.err.println(
                         "Error: Activity not started, unable to "
-                        + "call on to activity manager service");
-            }
+                        + "resolve " + intent.toString());
+                break;
+            case IActivityManager.START_CLASS_NOT_FOUND:
+                System.err.println(NO_CLASS_ERROR_CODE);
+                System.err.println("Error: Activity class " +
+                        intent.getComponent().toShortString()
+                        + " does not exist.");
+                break;
+            case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
+                System.err.println(
+                        "Error: Activity not started, you requested to "
+                        + "both forward and receive its result");
+                break;
+            case IActivityManager.START_PERMISSION_DENIED:
+                System.err.println(
+                        "Error: Activity not started, you do not "
+                        + "have permission to access it.");
+                break;
+            default:
+                System.err.println(
+                        "Error: Activity not started, unknown error code " + res);
+                break;
         }
     }
 
-    private void sendBroadcast() {
+    private void sendBroadcast() throws Exception {
         Intent intent = makeIntent();
-        
-        if (intent != null) {
-            System.out.println("Broadcasting: " + intent);
-            try {
-                mAm.broadcastIntent(null, intent, null, null, 0, null, null,
-                        null, true, false);
-            } catch (RemoteException e) {
-            }
-        }
+        IntentReceiver receiver = new IntentReceiver();
+        System.out.println("Broadcasting: " + intent);
+        mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, null, true, false);
+        receiver.waitForFinish();
     }
 
-    private void runInstrument() {
+    private void runInstrument() throws Exception {
         String profileFile = null;
         boolean wait = false;
         boolean rawMode = false;
@@ -283,46 +255,30 @@
         String argKey = null, argValue = null;
         IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
 
-        try {
-            String opt;
-            while ((opt=nextOption()) != null) {
-                if (opt.equals("-p")) {
-                    profileFile = nextOptionData();
-                } else if (opt.equals("-w")) {
-                    wait = true;
-                } else if (opt.equals("-r")) {
-                    rawMode = true;
-                } else if (opt.equals("-e")) {
-                    argKey = nextOptionData();
-                    argValue = nextOptionData();
-                    args.putString(argKey, argValue);
-                } else if (opt.equals("--no_window_animation")) {
-                    no_window_animation = true;
-                } else {
-                    System.err.println("Error: Unknown option: " + opt);
-                    showUsage();
-                    return;
-                }
+        String opt;
+        while ((opt=nextOption()) != null) {
+            if (opt.equals("-p")) {
+                profileFile = nextArgRequired();
+            } else if (opt.equals("-w")) {
+                wait = true;
+            } else if (opt.equals("-r")) {
+                rawMode = true;
+            } else if (opt.equals("-e")) {
+                argKey = nextArgRequired();
+                argValue = nextArgRequired();
+                args.putString(argKey, argValue);
+            } else if (opt.equals("--no_window_animation")) {
+                no_window_animation = true;
+            } else {
+                System.err.println("Error: Unknown option: " + opt);
+                showUsage();
+                return;
             }
-        } catch (RuntimeException ex) {
-            System.err.println("Error: " + ex.toString());
-            showUsage();
-            return;
         }
 
-        String cnArg = nextArg();
-        if (cnArg == null) {
-            System.err.println("Error: No instrumentation component supplied");
-            showUsage();
-            return;
-        }
-        
+        String cnArg = nextArgRequired();
         ComponentName cn = ComponentName.unflattenFromString(cnArg);
-        if (cn == null) {
-            System.err.println("Error: Bad component name: " + cnArg);
-            showUsage();
-            return;
-        }
+        if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
 
         InstrumentationWatcher watcher = null;
         if (wait) {
@@ -331,22 +287,13 @@
         }
         float[] oldAnims = null;
         if (no_window_animation) {
-            try {
-                oldAnims = wm.getAnimationScales();
-                wm.setAnimationScale(0, 0.0f);
-                wm.setAnimationScale(1, 0.0f);
-            } catch (RemoteException e) {
-            }
+            oldAnims = wm.getAnimationScales();
+            wm.setAnimationScale(0, 0.0f);
+            wm.setAnimationScale(1, 0.0f);
         }
 
-        try {
-            if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) {
-                System.out.println("INSTRUMENTATION_FAILED: " +
-                        cn.flattenToString());
-                showUsage();
-                return;
-            }
-        } catch (RemoteException e) {
+        if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher)) {
+            throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
         }
 
         if (watcher != null) {
@@ -356,9 +303,57 @@
         }
 
         if (oldAnims != null) {
+            wm.setAnimationScales(oldAnims);
+        }
+    }
+
+    private void runProfile() throws Exception {
+        String profileFile = null;
+        boolean start = false;
+        String process = nextArgRequired();
+        ParcelFileDescriptor fd = null;
+
+        String cmd = nextArgRequired();
+        if ("start".equals(cmd)) {
+            start = true;
+            profileFile = nextArgRequired();
             try {
-                wm.setAnimationScales(oldAnims);
-            } catch (RemoteException e) {
+                fd = ParcelFileDescriptor.open(
+                        new File(profileFile),
+                        ParcelFileDescriptor.MODE_CREATE |
+                        ParcelFileDescriptor.MODE_TRUNCATE |
+                        ParcelFileDescriptor.MODE_READ_WRITE);
+            } catch (FileNotFoundException e) {
+                System.err.println("Error: Unable to open file: " + profileFile);
+                return;
+            }
+        } else if (!"stop".equals(cmd)) {
+            throw new IllegalArgumentException("Profile command " + cmd + " not valid");
+        }
+
+        if (!mAm.profileControl(process, start, profileFile, fd)) {
+            throw new AndroidException("PROFILE FAILED on process " + process);
+        }
+    }
+
+    private class IntentReceiver extends IIntentReceiver.Stub {
+        private boolean mFinished = false;
+
+        public synchronized void performReceive(
+                Intent intent, int rc, String data, Bundle ext, boolean ord) {
+            String line = "Broadcast completed: result=" + rc;
+            if (data != null) line = line + ", data=\"" + data + "\"";
+            if (ext != null) line = line + ", extras: " + ext;
+            System.out.println(line);
+            mFinished = true;
+            notifyAll();
+        }
+
+        public synchronized void waitForFinish() {
+            try {
+                while (!mFinished) wait();
+            } catch (InterruptedException e) {
+                throw new IllegalStateException(e);
             }
         }
     }
@@ -366,7 +361,7 @@
     private class InstrumentationWatcher extends IInstrumentationWatcher.Stub {
         private boolean mFinished = false;
         private boolean mRawMode = false;
-        
+
         /**
          * Set or reset "raw mode".  In "raw mode", all bundles are dumped.  In "pretty mode", 
          * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that.
@@ -375,7 +370,7 @@
         public void setRawOutput(boolean rawMode) {
             mRawMode = rawMode;
         }
-        
+
         public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
             synchronized (this) {
                 // pretty printer mode?
@@ -431,6 +426,7 @@
                         }
                         wait(1000);
                     } catch (InterruptedException e) {
+                        throw new IllegalStateException(e);
                     }
                 }
             }
@@ -438,62 +434,11 @@
         }
     }
 
-    private void runProfile() {
-        String profileFile = null;
-        boolean start = false;
-
-        String process = nextArg();
-        if (process == null) {
-            System.err.println("Error: No profile process supplied");
-            showUsage();
-            return;
-        }
-        
-        ParcelFileDescriptor fd = null;
-        
-        String cmd = nextArg();
-        if ("start".equals(cmd)) {
-            start = true;
-            profileFile = nextArg();
-            if (profileFile == null) {
-                System.err.println("Error: No profile file path supplied");
-                showUsage();
-                return;
-            }
-            try {
-                fd = ParcelFileDescriptor.open(
-                        new File(profileFile),
-                        ParcelFileDescriptor.MODE_CREATE |
-                        ParcelFileDescriptor.MODE_TRUNCATE |
-                        ParcelFileDescriptor.MODE_READ_WRITE);
-            } catch (FileNotFoundException e) {
-                System.err.println("Error: Unable to open file: " + profileFile);
-                return;
-            }
-        } else if (!"stop".equals(cmd)) {
-            System.err.println("Error: Profile command " + cmd + " not valid");
-            showUsage();
-            return;
-        }
-        
-        try {
-            if (!mAm.profileControl(process, start, profileFile, fd)) {
-                System.err.println("PROFILE FAILED on process " + process);
-                return;
-            }
-        } catch (IllegalArgumentException e) {
-            System.out.println("PROFILE FAILED: " + e.getMessage());
-            return;
-        } catch (IllegalStateException e) {
-            System.out.println("PROFILE FAILED: " + e.getMessage());
-            return;
-        } catch (RemoteException e) {
-            System.out.println("PROFILE FAILED: activity manager gone");
-            return;
-        }
-    }
-
     private String nextOption() {
+        if (mCurArgData != null) {
+            String prev = mArgs[mNextArg - 1];
+            throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
+        }
         if (mNextArg >= mArgs.length) {
             return null;
         }
@@ -518,41 +463,52 @@
         return arg;
     }
 
-    private String nextOptionData() {
+    private String nextArg() {
         if (mCurArgData != null) {
-            return mCurArgData;
-        }
-        if (mNextArg >= mArgs.length) {
+            String arg = mCurArgData;
+            mCurArgData = null;
+            return arg;
+        } else if (mNextArg < mArgs.length) {
+            return mArgs[mNextArg++];
+        } else {
             return null;
         }
-        String data = mArgs[mNextArg];
-        mNextArg++;
-        return data;
     }
 
-    private String nextArg() {
-        if (mNextArg >= mArgs.length) {
-            return null;
+    private String nextArgRequired() {
+        String arg = nextArg();
+        if (arg == null) {
+            String prev = mArgs[mNextArg - 1];
+            throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
         }
-        String arg = mArgs[mNextArg];
-        mNextArg++;
         return arg;
     }
 
-    private void showUsage() {
-        System.err.println("usage: am [start|broadcast|instrument|profile]");
-        System.err.println("       am start [-D] INTENT");
-        System.err.println("       am broadcast INTENT");
-        System.err.println("       am instrument [-r] [-e <ARG_NAME> <ARG_VALUE>] [-p <PROF_FILE>]");
-        System.err.println("                [-w] <COMPONENT> ");
-        System.err.println("       am profile <PROCESS> [start <PROF_FILE>|stop]");
-        System.err.println("");
-        System.err.println("       INTENT is described with:");
-        System.err.println("                [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]");
-        System.err.println("                [-c <CATEGORY> [-c <CATEGORY>] ...]");
-        System.err.println("                [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]");
-        System.err.println("                [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]");
-        System.err.println("                [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]");
-        System.err.println("                [-n <COMPONENT>] [-f <FLAGS>] [<URI>]");
+    private static void showUsage() {
+        System.err.println(
+                "usage: am [subcommand] [options]\n" +
+                "\n" +
+                "    start an Activity: am start [-D] <INTENT>\n" +
+                "        -D: enable debugging\n" +
+                "\n" +
+                "    send a broadcast Intent: am broadcast <INTENT>\n" +
+                "\n" +
+                "    start an Instrumentation: am instrument [flags] <COMPONENT>\n" +
+                "        -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)\n" +
+                "        -e <NAME> <VALUE>: set argument <NAME> to <VALUE>\n" +
+                "        -p <FILE>: write profiling data to <FILE>\n" +
+                "        -w: wait for instrumentation to finish before returning\n" +
+                "\n" +
+                "    start profiling: am profile <PROCESS> start <FILE>\n" +
+                "    stop profiling: am profile <PROCESS> stop\n" +
+                "\n" +
+                "    <INTENT> specifications include these flags:\n" +
+                "        [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
+                "        [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
+                "        [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
+                "        [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
+                "        [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
+                "        [-n <COMPONENT>] [-f <FLAGS>] [<URI>]\n"
+                );
     }
 }
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 444f222..9432755 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -788,6 +788,11 @@
         final SearchManager searchManager = (SearchManager) mContext
                 .getSystemService(Context.SEARCH_SERVICE);
 
+        // can't start search without an associated activity (e.g a system dialog)
+        if (!searchManager.hasIdent()) {
+            return false;
+        }
+
         // associate search with owner activity if possible (otherwise it will default to
         // global search).
         final ComponentName appName = mOwnerActivity == null ? null
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 27c6376..26b5b7a 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -34,7 +34,10 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
 import android.os.SystemClock;
+import android.provider.Browser;
 import android.server.search.SearchableInfo;
 import android.speech.RecognizerIntent;
 import android.text.Editable;
@@ -42,6 +45,7 @@
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.text.util.Regex;
+import android.util.AndroidRuntimeException;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
@@ -537,6 +541,8 @@
             mSearchAutoComplete.setDropDownAlwaysVisible(false);
         }
 
+        mSearchAutoComplete.setForceIgnoreOutsideTouch(true);
+
         // attach the suggestions adapter, if suggestions are available
         // The existence of a suggestions authority is the proxy for "suggestions available here"
         if (mSearchable.getSuggestAuthority() != null) {
@@ -1093,7 +1099,8 @@
      */
     protected void launchQuerySearch(int actionKey, String actionMsg)  {
         String query = mSearchAutoComplete.getText().toString();
-        Intent intent = createIntent(Intent.ACTION_SEARCH, null, null, query, null,
+        String action = mGlobalSearchMode ? Intent.ACTION_WEB_SEARCH : Intent.ACTION_SEARCH;
+        Intent intent = createIntent(action, null, null, query, null,
                 actionKey, actionMsg);
         launchIntent(intent);
     }
@@ -1245,16 +1252,127 @@
             return;
         }
         Log.d(LOG_TAG, "launching " + intent);
-        getContext().startActivity(intent);
-
-        // in global search mode, SearchDialogWrapper#performActivityResuming will handle hiding
-        // the dialog when the next activity starts, but for in-app search, we still need to
-        // dismiss the dialog.
-        if (!mGlobalSearchMode) {
-            dismiss();
+        try {
+            // in global search mode, we send the activity straight to the original suggestion
+            // source. this is because GlobalSearch may not have permission to launch the
+            // intent, and to avoid the extra step of going through GlobalSearch.
+            if (mGlobalSearchMode) {
+                launchGlobalSearchIntent(intent);
+            } else {
+                getContext().startActivity(intent);
+                // in global search mode, SearchDialogWrapper#performActivityResuming
+                // will handle hiding the dialog when the next activity starts, but for
+                // in-app search, we still need to dismiss the dialog.
+                dismiss();
+            }
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "Failed launch activity: " + intent, ex);
         }
     }
-    
+
+    private void launchGlobalSearchIntent(Intent intent) {
+        final String packageName;
+        // GlobalSearch puts the original source of the suggestion in the
+        // 'component name' column. If set, we send the intent to that activity.
+        // We trust GlobalSearch to always set this to the suggestion source.
+        String intentComponent = intent.getStringExtra(SearchManager.COMPONENT_NAME_KEY);
+        if (intentComponent != null) {
+            ComponentName componentName = ComponentName.unflattenFromString(intentComponent);
+            intent.setComponent(componentName);
+            intent.removeExtra(SearchManager.COMPONENT_NAME_KEY);
+            // Launch the intent as the suggestion source.
+            // This prevents sources from using the search dialog to launch
+            // intents that they don't have permission for themselves.
+            packageName = componentName.getPackageName();
+        } else {
+            // If there is no component in the suggestion, it must be a built-in suggestion
+            // from GlobalSearch (e.g. "Search the web for") or the intent
+            // launched when pressing the search/go button in the search dialog.
+            // Launch the intent with the permissions of GlobalSearch.
+            packageName = mSearchable.getSearchActivity().getPackageName();
+        }
+
+        // Launch all global search suggestions as new tasks, since they don't relate
+        // to the current task.
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        setBrowserApplicationId(intent);
+
+        if (DBG) Log.d(LOG_TAG, "Launching intent " + intent.toURI() + " as " + packageName);
+        startActivityInPackage(intent, packageName);
+    }
+
+    /**
+     * If the intent is to open an HTTP or HTTPS URL, we set
+     * {@link Browser#EXTRA_APPLICATION_ID} so that any existing browser window that
+     * has been opened by us for the same URL will be reused.
+     */
+    private void setBrowserApplicationId(Intent intent) {
+        Uri data = intent.getData();
+        if (Intent.ACTION_VIEW.equals(intent.getAction()) && data != null) {
+            String scheme = data.getScheme();
+            if (scheme != null && scheme.startsWith("http")) {
+                intent.putExtra(Browser.EXTRA_APPLICATION_ID, data.toString());
+            }
+        }
+    }
+
+    /**
+     * Starts an activity as if it had been started by the given package.
+     *
+     * @param intent The description of the activity to start.
+     * @param packageName
+     * @throws ActivityNotFoundException If the intent could not be resolved to
+     *         and existing activity.
+     * @throws SecurityException If the package does not have permission to start
+     *         start the activity.
+     * @throws AndroidRuntimeException If some other error occurs.
+     */
+    private void startActivityInPackage(Intent intent, String packageName) {
+        try {
+            int uid = ActivityThread.getPackageManager().getPackageUid(packageName);
+            if (uid < 0) {
+                throw new AndroidRuntimeException("Package UID not found " + packageName);
+            }
+            String resolvedType = intent.resolveTypeIfNeeded(getContext().getContentResolver());
+            IBinder resultTo = null;
+            String resultWho = null;
+            int requestCode = -1;
+            boolean onlyIfNeeded = false;
+            int result = ActivityManagerNative.getDefault().startActivityInPackage(
+                    uid, intent, resolvedType, resultTo, resultWho, requestCode, onlyIfNeeded);
+            checkStartActivityResult(result, intent);
+        } catch (RemoteException ex) {
+            throw new AndroidRuntimeException(ex);
+        }
+    }
+
+    // Stolen from Instrumentation.checkStartActivityResult()
+    private static void checkStartActivityResult(int res, Intent intent) {
+        if (res >= IActivityManager.START_SUCCESS) {
+            return;
+        }
+        switch (res) {
+            case IActivityManager.START_INTENT_NOT_RESOLVED:
+            case IActivityManager.START_CLASS_NOT_FOUND:
+                if (intent.getComponent() != null)
+                    throw new ActivityNotFoundException(
+                            "Unable to find explicit activity class "
+                            + intent.getComponent().toShortString()
+                            + "; have you declared this activity in your AndroidManifest.xml?");
+                throw new ActivityNotFoundException(
+                        "No Activity found to handle " + intent);
+            case IActivityManager.START_PERMISSION_DENIED:
+                throw new SecurityException("Not allowed to start activity "
+                        + intent);
+            case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
+                throw new AndroidRuntimeException(
+                        "FORWARD_RESULT_FLAG used while also requesting a result");
+            default:
+                throw new AndroidRuntimeException("Unknown error code "
+                        + res + " when starting " + intent);
+        }
+    }
+
     /**
      * Handles the special intent actions declared in {@link SearchManager}.
      * 
@@ -1460,8 +1578,10 @@
             intent.putExtra(SearchManager.ACTION_KEY, actionKey);
             intent.putExtra(SearchManager.ACTION_MSG, actionMsg);
         }
-        // attempt to enforce security requirement (no 3rd-party intents)
-        intent.setComponent(mSearchable.getSearchActivity());
+        // Only allow 3rd-party intents from GlobalSearch
+        if (!mGlobalSearchMode) {
+            intent.setComponent(mSearchable.getSearchActivity());
+        }
         return intent;
     }
     
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 325c207..0631ad5 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1188,8 +1188,6 @@
     /**
      * Intent extra data key: This key will be used for the extra populated by the
      * {@link #SUGGEST_COLUMN_INTENT_EXTRA_DATA} column.
-     *
-     * {@hide}
      */
     public final static String EXTRA_DATA_KEY = "intent_extra_data_key";
 
@@ -1269,16 +1267,12 @@
      * result indicates the shortcut refers to a no longer valid sugggestion.
      *
      * @see #SUGGEST_COLUMN_SHORTCUT_ID
-     * 
-     * @hide pending API council approval
      */
     public final static String SUGGEST_URI_PATH_SHORTCUT = "search_suggest_shortcut";
     
     /**
      * MIME type for shortcut validation.  You'll use this in your suggestions content provider
      * in the getType() function.
-     *
-     * @hide pending API council approval
      */
     public final static String SHORTCUT_MIME_TYPE = 
             "vnd.android.cursor.item/vnd.android.search.suggest";
@@ -1389,9 +1383,7 @@
      * this element exists at the given row, this is the data that will be used when
      * forming the suggestion's intent. If not provided, the Intent's extra data field will be null.
      * This column allows suggestions to provide additional arbitrary data which will be included as
-     * an extra under the key EXTRA_DATA_KEY.
-     *
-     * @hide Pending API council approval.
+     * an extra under the key {@link #EXTRA_DATA_KEY}.
      */
     public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data";
     /**
@@ -1425,8 +1417,6 @@
      * {@link #SUGGEST_NEVER_MAKE_SHORTCUT}, the result will not be stored as a shortcut.
      * Otherwise, the shortcut id will be used to check back for validation via
      * {@link #SUGGEST_URI_PATH_SHORTCUT}.
-     *
-     * @hide Pending API council approval.
      */
     public final static String SUGGEST_COLUMN_SHORTCUT_ID = "suggest_shortcut_id";
 
@@ -1443,8 +1433,6 @@
      * Column name for suggestions cursor. <i>Optional.</i> This column is used to specify
      * that a spinner should be shown in lieu of an icon2 while the shortcut of this suggestion
      * is being refreshed.
-     * 
-     * @hide Pending API council approval.
      */
     public final static String SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING =
             "suggest_spinner_while_refreshing";
@@ -1452,8 +1440,6 @@
     /**
      * Column value for suggestion column {@link #SUGGEST_COLUMN_SHORTCUT_ID} when a suggestion
      * should not be stored as a shortcut in global search.
-     *
-     * @hide Pending API council approval.
      */
     public final static String SUGGEST_NEVER_MAKE_SHORTCUT = "_-1";
 
@@ -1500,8 +1486,6 @@
      * Intent action for starting a web search provider's settings activity.
      * Web search providers should handle this intent if they have provider-specific
      * settings to implement.
-     * 
-     * @hide Pending API council approval.
      */
     public final static String INTENT_ACTION_WEB_SEARCH_SETTINGS
             = "android.search.action.WEB_SEARCH_SETTINGS";
@@ -1510,11 +1494,17 @@
      * Intent action broadcasted to inform that the searchables list or default have changed.
      * Components should handle this intent if they cache any searchable data and wish to stay
      * up to date on changes.
-     *
-     * @hide Pending API council approval.
      */
     public final static String INTENT_ACTION_SEARCHABLES_CHANGED
             = "android.search.action.SEARCHABLES_CHANGED";
+    
+    /**
+     * Intent action broadcasted to inform that the search settings have changed in some way.
+     * Either searchables have been enabled or disabled, or a different web search provider
+     * has been chosen.
+     */
+    public final static String INTENT_ACTION_SEARCH_SETTINGS_CHANGED
+            = "android.search.action.SETTINGS_CHANGED";
 
     /**
      * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION},
@@ -1546,6 +1536,10 @@
         mService = ISearchManager.Stub.asInterface(
                 ServiceManager.getService(Context.SEARCH_SERVICE));
     }
+
+    /*package*/ boolean hasIdent() {
+        return mIdent != 0;
+    }
     
     /*package*/ void setIdent(int ident) {
         if (mIdent != 0) {
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 593b7b7..54061ae 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -27,6 +27,7 @@
 import android.database.Cursor;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableContainer;
 import android.graphics.drawable.StateListDrawable;
 import android.net.Uri;
 import android.os.Bundle;
diff --git a/core/java/android/content/AbstractTableMerger.java b/core/java/android/content/AbstractTableMerger.java
index 3266c07..a3daa01e 100644
--- a/core/java/android/content/AbstractTableMerger.java
+++ b/core/java/android/content/AbstractTableMerger.java
@@ -369,30 +369,33 @@
                     // An existing server item has changed
                     // If serverSyncVersion is null, there is no edit URL;
                     // server won't let this change be written.
-                    // Just hold onto it, I guess, in case the server permissions
-                    // change later.
-                    if (serverSyncVersion != null) {
-                        boolean recordChanged = (localSyncVersion == null) ||
-                                !serverSyncVersion.equals(localSyncVersion);
-                        if (recordChanged) {
-                            if (localSyncDirty) {
-                                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                                    Log.v(TAG, "remote record " + serverSyncId
-                                            + " conflicts with local _sync_id " + localSyncID
-                                            + ", local _id " + localRowId);
-                                }
-                                conflict = true;
-                            } else {
-                                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                                    Log.v(TAG,
-                                            "remote record " +
-                                                    serverSyncId +
-                                            " updates local _sync_id " +
-                                            localSyncID + ", local _id " +
-                                            localRowId);
-                                }
-                                update = true;
+                    boolean recordChanged = (localSyncVersion == null) ||
+                            (serverSyncVersion == null) ||
+                            !serverSyncVersion.equals(localSyncVersion);
+                    if (recordChanged) {
+                        if (localSyncDirty) {
+                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                                Log.v(TAG, "remote record " + serverSyncId
+                                        + " conflicts with local _sync_id " + localSyncID
+                                        + ", local _id " + localRowId);
                             }
+                            conflict = true;
+                        } else {
+                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                                Log.v(TAG,
+                                        "remote record " +
+                                                serverSyncId +
+                                                " updates local _sync_id " +
+                                                localSyncID + ", local _id " +
+                                                localRowId);
+                            }
+                            update = true;
+                        }
+                    } else {
+                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                            Log.v(TAG,
+                                    "Skipping update: localSyncVersion: " + localSyncVersion +
+                                    ", serverSyncVersion: " + serverSyncVersion);
                         }
                     }
                 } else {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 5be8100..66b507d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4535,6 +4535,9 @@
      * and {@link #FILL_IN_COMPONENT} to override the restriction where the
      * corresponding field will not be replaced if it is already set.
      *
+     * <p>Note: The component field will only be copied if {@link #FILL_IN_COMPONENT} is explicitly
+     * specified.
+     *
      * <p>For example, consider Intent A with {data="foo", categories="bar"}
      * and Intent B with {action="gotit", data-type="some/thing",
      * categories="one","two"}.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 0d00f21..9ca11cd 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -161,21 +161,30 @@
     public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<11;
     
     /**
+     * Value for {@link #flags}: true when the application knows how to adjust
+     * its UI for different screen sizes.  Corresponds to
+     * {@link android.R.styleable#AndroidManifestSupportsScreens_resizeable
+     * android:resizeable}.
+     */
+    public static final int FLAG_RESIZEABLE_FOR_SCREENS = 1<<12;
+    
+    /**
+     * Value for {@link #flags}: true when the application knows how to
+     * accomodate different screen densities.  Corresponds to
+     * {@link android.R.styleable#AndroidManifestSupportsScreens_anyDensity
+     * android:anyDensity}.
+     */
+    public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 1<<13;
+    
+    /**
      * Value for {@link #flags}: this is false if the application has set
      * its android:allowBackup to false, true otherwise.
      * 
      * {@hide}
      */
-    public static final int FLAG_ALLOW_BACKUP = 1<<12;
+    public static final int FLAG_ALLOW_BACKUP = 1<<14;
     
     /**
-     * Indicates that the application supports any densities;
-     * {@hide}
-     */
-    public static final int ANY_DENSITY = -1;
-    static final int[] ANY_DENSITIES_ARRAY = { ANY_DENSITY };
-
-    /**
      * Flags associated with the application.  Any combination of
      * {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
      * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
@@ -183,7 +192,7 @@
      * {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP},
      * {@link #FLAG_TEST_ONLY}, {@link #FLAG_SUPPORTS_SMALL_SCREENS},
      * {@link #FLAG_SUPPORTS_NORMAL_SCREENS},
-     * {@link #FLAG_SUPPORTS_LARGE_SCREENS}.
+     * {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_RESIZEABLE_FOR_SCREENS}.
      */
     public int flags = 0;
     
@@ -220,13 +229,6 @@
     public int uid;
     
     /**
-     * The list of densities in DPI that application supprots. This
-     * field is only set if the {@link PackageManager#GET_SUPPORTS_DENSITIES} flag was
-     * used when retrieving the structure.
-     */
-    public int[] supportsDensities;
-
-    /**
      * The minimum SDK version this application targets.  It may run on earilier
      * versions, but it knows how to work with any new behavior added at this
      * version.  Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
@@ -259,7 +261,6 @@
         pw.println(prefix + "enabled=" + enabled);
         pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);
         pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes));
-        pw.println(prefix + "supportsDensities=" + supportsDensities);
         super.dumpBack(pw, prefix);
     }
     
@@ -306,7 +307,6 @@
         enabled = orig.enabled;
         manageSpaceActivityName = orig.manageSpaceActivityName;
         descriptionRes = orig.descriptionRes;
-        supportsDensities = orig.supportsDensities;
     }
 
 
@@ -338,7 +338,6 @@
         dest.writeString(manageSpaceActivityName);
         dest.writeString(backupAgentName);
         dest.writeInt(descriptionRes);
-        dest.writeIntArray(supportsDensities);
     }
 
     public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -369,7 +368,6 @@
         manageSpaceActivityName = source.readString();
         backupAgentName = source.readString();
         descriptionRes = source.readInt();
-        supportsDensities = source.createIntArray();
     }
 
     /**
@@ -399,7 +397,8 @@
      * @hide
      */
     public void disableCompatibilityMode() {
-        flags |= FLAG_SUPPORTS_LARGE_SCREENS;
-        supportsDensities = ANY_DENSITIES_ARRAY;
+        flags |= (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS |
+                FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS |
+                FLAG_SUPPORTS_SCREEN_DENSITIES);
     }
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3250a87..bca1715 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -165,12 +165,6 @@
     public static final int GET_CONFIGURATIONS = 0x00004000;
 
     /**
-     * {@link ApplicationInfo} flag: return the
-     * {@link ApplicationInfo#supportsDensities} that the package supports.
-     */
-    public static final int GET_SUPPORTS_DENSITIES    = 0x00008000;
-
-    /**
      * Resolution and querying flag: if set, only filters that support the
      * {@link android.content.Intent#CATEGORY_DEFAULT} will be considered for
      * matching.  This is a synonym for including the CATEGORY_DEFAULT in your
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index cebb696..33f4b52 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -92,6 +92,8 @@
     private static final Object mSync = new Object();
     private static WeakReference<byte[]> mReadBuffer;
 
+    private static boolean sCompatibilityModeEnabled = true; 
+
     static class ParsePackageItemArgs {
         final Package owner;
         final String[] outError;
@@ -672,6 +674,8 @@
         int supportsSmallScreens = 1;
         int supportsNormalScreens = 1;
         int supportsLargeScreens = 1;
+        int resizeable = 1;
+        int anyDensity = 1;
         
         int outerDepth = parser.getDepth();
         while ((type=parser.next()) != parser.END_DOCUMENT
@@ -851,21 +855,6 @@
 
                 XmlUtils.skipCurrentTag(parser);
 
-            } else if (tagName.equals("supports-density")) {
-                sa = res.obtainAttributes(attrs,
-                        com.android.internal.R.styleable.AndroidManifestSupportsDensity);
-
-                int density = sa.getInteger(
-                        com.android.internal.R.styleable.AndroidManifestSupportsDensity_density, -1);
-
-                sa.recycle();
-
-                if (density != -1 && !pkg.supportsDensityList.contains(density)) {
-                    pkg.supportsDensityList.add(density);
-                }
-
-                XmlUtils.skipCurrentTag(parser);
-
             } else if (tagName.equals("supports-screens")) {
                 sa = res.obtainAttributes(attrs,
                         com.android.internal.R.styleable.AndroidManifestSupportsScreens);
@@ -881,6 +870,12 @@
                 supportsLargeScreens = sa.getInteger(
                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
                         supportsLargeScreens);
+                resizeable = sa.getInteger(
+                        com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
+                        supportsLargeScreens);
+                anyDensity = sa.getInteger(
+                        com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
+                        anyDensity);
 
                 sa.recycle();
                 
@@ -956,7 +951,7 @@
         
         if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
                 && pkg.applicationInfo.targetSdkVersion
-                        >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
+                        >= android.os.Build.VERSION_CODES.DONUT)) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
         }
         if (supportsNormalScreens != 0) {
@@ -964,27 +959,19 @@
         }
         if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
                 && pkg.applicationInfo.targetSdkVersion
-                        >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
+                        >= android.os.Build.VERSION_CODES.DONUT)) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
         }
-        int densities[] = null;
-        int size = pkg.supportsDensityList.size();
-        if (size > 0) {
-            densities = pkg.supportsDensities = new int[size];
-            List<Integer> densityList = pkg.supportsDensityList;
-            for (int i = 0; i < size; i++) {
-                densities[i] = densityList.get(i);
-            }
+        if (resizeable < 0 || (resizeable > 0
+                && pkg.applicationInfo.targetSdkVersion
+                        >= android.os.Build.VERSION_CODES.DONUT)) {
+            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
         }
-        /**
-         * TODO: enable this before code freeze. b/1967935
-         * *
-        if ((densities == null || densities.length == 0)
-                && (pkg.applicationInfo.targetSdkVersion
-                        >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
-            pkg.supportsDensities = ApplicationInfo.ANY_DENSITIES_ARRAY;
+        if (anyDensity < 0 || (anyDensity > 0
+                && pkg.applicationInfo.targetSdkVersion
+                        >= android.os.Build.VERSION_CODES.DONUT)) {
+            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
         }
-         */
 
         return pkg;
     }
@@ -2435,9 +2422,6 @@
         // We store the application meta-data independently to avoid multiple unwanted references
         public Bundle mAppMetaData = null;
 
-        public final ArrayList<Integer> supportsDensityList = new ArrayList<Integer>();
-        public int[] supportsDensities = null;
-
         // If this is a 3rd party app, this is the path of the zip file.
         public String mPath;
 
@@ -2619,16 +2603,17 @@
                 && p.usesLibraryFiles != null) {
             return true;
         }
-        if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0
-                && p.supportsDensities != null) {
-            return true;
-        }
         return false;
     }
 
     public static ApplicationInfo generateApplicationInfo(Package p, int flags) {
         if (p == null) return null;
         if (!copyNeeded(flags, p, null)) {
+            // CompatibilityMode is global state. It's safe to modify the instance
+            // of the package.
+            if (!sCompatibilityModeEnabled) {
+                p.applicationInfo.disableCompatibilityMode();
+            }
             return p.applicationInfo;
         }
 
@@ -2640,8 +2625,8 @@
         if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
             ai.sharedLibraryFiles = p.usesLibraryFiles;
         }
-        if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0) {
-            ai.supportsDensities = p.supportsDensities;
+        if (!sCompatibilityModeEnabled) {
+            ai.disableCompatibilityMode();
         }
         return ai;
     }
@@ -2827,4 +2812,11 @@
                 + " " + service.info.name + "}";
         }
     }
+
+    /**
+     * @hide
+     */
+    public static void setCompatibilityModeEnabled(boolean compatibilityModeEnabled) {
+        sCompatibilityModeEnabled = compatibilityModeEnabled;
+    }
 }
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 6e34cc8..e2abfd1 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -69,8 +69,8 @@
     /**
      * A flag mask to indicates that the application can expand over the original size.
      * The flag is set to true if
-     * 1) Application declares its expandable in manifest file using <expandable /> or
-     * 2) The screen size is same as (320 x 480) * density. 
+     * 1) Application declares its expandable in manifest file using <supports-screens> or
+     * 2) Configuration.SCREENLAYOUT_COMPAT_NEEDED is not set
      * {@see compatibilityFlag}
      */
     private static final int EXPANDABLE = 2;
@@ -78,11 +78,28 @@
     /**
      * A flag mask to tell if the application is configured to be expandable. This differs
      * from EXPANDABLE in that the application that is not expandable will be 
-     * marked as expandable if it runs in (320x 480) * density screen size.
+     * marked as expandable if Configuration.SCREENLAYOUT_COMPAT_NEEDED is not set.
      */
     private static final int CONFIGURED_EXPANDABLE = 4; 
 
-    private static final int SCALING_EXPANDABLE_MASK = SCALING_REQUIRED | EXPANDABLE;
+    /**
+     * A flag mask to indicates that the application supports large screens.
+     * The flag is set to true if
+     * 1) Application declares it supports large screens in manifest file using <supports-screens> or
+     * 2) The screen size is not large
+     * {@see compatibilityFlag}
+     */
+    private static final int LARGE_SCREENS = 8;
+    
+    /**
+     * A flag mask to tell if the application supports large screens. This differs
+     * from LARGE_SCREENS in that the application that does not support large
+     * screens will be marked as supporting them if the current screen is not
+     * large.
+     */
+    private static final int CONFIGURED_LARGE_SCREENS = 16; 
+
+    private static final int SCALING_EXPANDABLE_MASK = SCALING_REQUIRED | EXPANDABLE | LARGE_SCREENS;
 
     /**
      * The effective screen density we have selected for this application.
@@ -108,44 +125,21 @@
         appFlags = appInfo.flags;
         
         if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
-            mCompatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
+            mCompatibilityFlags |= LARGE_SCREENS | CONFIGURED_LARGE_SCREENS;
+        }
+        if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
+            mCompatibilityFlags |= EXPANDABLE | CONFIGURED_EXPANDABLE;
         }
         
-        float packageDensityScale = -1.0f;
-        int packageDensity = 0;
-        if (appInfo.supportsDensities != null) {
-            int minDiff = Integer.MAX_VALUE;
-            for (int density : appInfo.supportsDensities) {
-                if (density == ApplicationInfo.ANY_DENSITY) {
-                    packageDensity = DisplayMetrics.DENSITY_DEVICE;
-                    packageDensityScale = 1.0f;
-                    break;
-                }
-                int tmpDiff = Math.abs(DisplayMetrics.DENSITY_DEVICE - density);
-                if (tmpDiff == 0) {
-                    packageDensity = DisplayMetrics.DENSITY_DEVICE;
-                    packageDensityScale = 1.0f;
-                    break;
-                }
-                // prefer higher density (appScale>1.0), unless that's only option.
-                if (tmpDiff < minDiff && packageDensityScale < 1.0f) {
-                    packageDensity = density;
-                    packageDensityScale = DisplayMetrics.DENSITY_DEVICE / (float) density;
-                    minDiff = tmpDiff;
-                }
-            }
-        }
-        if (packageDensityScale > 0.0f) {
-            applicationDensity = packageDensity;
-            applicationScale = packageDensityScale;
+        if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
+            applicationDensity = DisplayMetrics.DENSITY_DEVICE;
+            applicationScale = 1.0f;
+            applicationInvertedScale = 1.0f;
         } else {
             applicationDensity = DisplayMetrics.DENSITY_DEFAULT;
-            applicationScale =
-                    DisplayMetrics.DENSITY_DEVICE / (float) DisplayMetrics.DENSITY_DEFAULT;
-        }
-
-        applicationInvertedScale = 1.0f / applicationScale;
-        if (applicationScale != 1.0f) {
+            applicationScale = DisplayMetrics.DENSITY_DEVICE
+                    / (float) DisplayMetrics.DENSITY_DEFAULT;
+            applicationInvertedScale = 1.0f / applicationScale;
             mCompatibilityFlags |= SCALING_REQUIRED;
         }
     }
@@ -162,7 +156,8 @@
     private CompatibilityInfo() {
         this(ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS
                 | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS
-                | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS,
+                | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS
+                | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS,
                 EXPANDABLE | CONFIGURED_EXPANDABLE,
                 DisplayMetrics.DENSITY_DEVICE,
                 1.0f,
@@ -190,6 +185,17 @@
     }
 
     /**
+     * Sets large screen bit in the compatibility flag.
+     */
+    public void setLargeScreens(boolean expandable) {
+        if (expandable) {
+            mCompatibilityFlags |= CompatibilityInfo.LARGE_SCREENS;
+        } else {
+            mCompatibilityFlags &= ~CompatibilityInfo.LARGE_SCREENS;
+        }
+    }
+
+    /**
      * @return true if the application is configured to be expandable.
      */
     public boolean isConfiguredExpandable() {
@@ -197,6 +203,13 @@
     }
 
     /**
+     * @return true if the application is configured to be expandable.
+     */
+    public boolean isConfiguredLargeScreens() {
+        return (mCompatibilityFlags & CompatibilityInfo.CONFIGURED_LARGE_SCREENS) != 0;
+    }
+
+    /**
      * @return true if the scaling is required
      */
     public boolean isScalingRequired() {
@@ -204,7 +217,8 @@
     }
     
     public boolean supportsScreen() {
-        return (mCompatibilityFlags & CompatibilityInfo.EXPANDABLE) != 0;
+        return (mCompatibilityFlags & (EXPANDABLE|LARGE_SCREENS))
+                == (EXPANDABLE|LARGE_SCREENS);
     }
     
     @Override
@@ -219,8 +233,8 @@
      * @param params the window's parameter
      */
     public Translator getTranslator(WindowManager.LayoutParams params) {
-        if ( (mCompatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK)
-                == CompatibilityInfo.EXPANDABLE) {
+        if ( (mCompatibilityFlags & SCALING_EXPANDABLE_MASK)
+                == (EXPANDABLE|LARGE_SCREENS)) {
             if (DBG) Log.d(TAG, "no translation required");
             return null;
         }
@@ -342,8 +356,8 @@
     public static void updateCompatibleScreenFrame(DisplayMetrics dm, int orientation,
             Rect outRect) {
         int width = dm.widthPixels;
-        int portraitHeight = (int) (DEFAULT_PORTRAIT_HEIGHT * dm.density);
-        int portraitWidth = (int) (DEFAULT_PORTRAIT_WIDTH * dm.density);
+        int portraitHeight = (int) (DEFAULT_PORTRAIT_HEIGHT * dm.density + 0.5f);
+        int portraitWidth = (int) (DEFAULT_PORTRAIT_WIDTH * dm.density + 0.5f);
         if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
             int xOffset = (width - portraitHeight) / 2 ;
             outRect.set(xOffset, 0, xOffset + portraitHeight, portraitWidth);
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 4928e93..cbf8410 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -41,6 +41,39 @@
      */
     public boolean userSetLocale;
 
+    public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
+    public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0x00;
+    public static final int SCREENLAYOUT_SIZE_SMALL = 0x01;
+    public static final int SCREENLAYOUT_SIZE_NORMAL = 0x02;
+    public static final int SCREENLAYOUT_SIZE_LARGE = 0x03;
+    
+    public static final int SCREENLAYOUT_LONG_MASK = 0x30;
+    public static final int SCREENLAYOUT_LONG_UNDEFINED = 0x00;
+    public static final int SCREENLAYOUT_LONG_NO = 0x10;
+    public static final int SCREENLAYOUT_LONG_YES = 0x20;
+    
+    /**
+     * Special flag we generate to indicate that the screen layout requires
+     * us to use a compatibility mode for apps that are not modern layout
+     * aware.
+     * @hide
+     */
+    public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
+    
+    /**
+     * Bit mask of overall layout of the screen.  Currently there are two
+     * fields:
+     * <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size
+     * of the screen.  They may be one of
+     * {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
+     * or {@link #SCREENLAYOUT_SIZE_LARGE}.
+     * 
+     * <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
+     * is wider/taller than normal.  They may be one of
+     * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.
+     */
+    public int screenLayout;
+    
     public static final int TOUCHSCREEN_UNDEFINED = 0;
     public static final int TOUCHSCREEN_NOTOUCH = 1;
     public static final int TOUCHSCREEN_STYLUS = 2;
@@ -117,18 +150,6 @@
      */
     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}
@@ -199,7 +220,7 @@
         hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
         navigation = NAVIGATION_UNDEFINED;
         orientation = ORIENTATION_UNDEFINED;
-        screenLayout = SCREENLAYOUT_UNDEFINED;
+        screenLayout = SCREENLAYOUT_SIZE_UNDEFINED;
     }
 
     /** {@hide} */
@@ -270,7 +291,7 @@
             changed |= ActivityInfo.CONFIG_ORIENTATION;
             orientation = delta.orientation;
         }
-        if (delta.screenLayout != SCREENLAYOUT_UNDEFINED
+        if (delta.screenLayout != SCREENLAYOUT_SIZE_UNDEFINED
                 && screenLayout != delta.screenLayout) {
             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
             screenLayout = delta.screenLayout;
@@ -343,7 +364,7 @@
                 && orientation != delta.orientation) {
             changed |= ActivityInfo.CONFIG_ORIENTATION;
         }
-        if (delta.screenLayout != SCREENLAYOUT_UNDEFINED
+        if (delta.screenLayout != SCREENLAYOUT_SIZE_UNDEFINED
                 && screenLayout != delta.screenLayout) {
             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
         }
diff --git a/core/java/android/database/MatrixCursor.java b/core/java/android/database/MatrixCursor.java
index cf5a573..d5c3a32 100644
--- a/core/java/android/database/MatrixCursor.java
+++ b/core/java/android/database/MatrixCursor.java
@@ -214,53 +214,64 @@
 
     // AbstractCursor implementation.
 
+    @Override
     public int getCount() {
         return rowCount;
     }
 
+    @Override
     public String[] getColumnNames() {
         return columnNames;
     }
 
+    @Override
     public String getString(int column) {
-        return String.valueOf(get(column));
+        Object value = get(column);
+        if (value == null) return null;
+        return value.toString();
     }
 
+    @Override
     public short getShort(int column) {
         Object value = get(column);
-        return (value instanceof String)
-                ? Short.valueOf((String) value)
-                : ((Number) value).shortValue();
+        if (value == null) return 0;
+        if (value instanceof Number) return ((Number) value).shortValue();
+        return Short.parseShort(value.toString());
     }
 
+    @Override
     public int getInt(int column) {
         Object value = get(column);
-        return (value instanceof String)
-                ? Integer.valueOf((String) value)
-                : ((Number) value).intValue();
+        if (value == null) return 0;
+        if (value instanceof Number) return ((Number) value).intValue();
+        return Integer.parseInt(value.toString());
     }
 
+    @Override
     public long getLong(int column) {
         Object value = get(column);
-        return (value instanceof String)
-                ? Long.valueOf((String) value)
-                : ((Number) value).longValue();
+        if (value == null) return 0;
+        if (value instanceof Number) return ((Number) value).longValue();
+        return Long.parseLong(value.toString());
     }
 
+    @Override
     public float getFloat(int column) {
         Object value = get(column);
-        return (value instanceof String)
-                ? Float.valueOf((String) value)
-                : ((Number) value).floatValue();
+        if (value == null) return 0.0f;
+        if (value instanceof Number) return ((Number) value).floatValue();
+        return Float.parseFloat(value.toString());
     }
 
+    @Override
     public double getDouble(int column) {
         Object value = get(column);
-        return (value instanceof String)
-                ? Double.valueOf((String) value)
-                : ((Number) value).doubleValue();
+        if (value == null) return 0.0d;
+        if (value instanceof Number) return ((Number) value).doubleValue();
+        return Double.parseDouble(value.toString());
     }
 
+    @Override
     public boolean isNull(int column) {
         return get(column) == null;
     }
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 7d331dc..184d6dc 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1412,8 +1412,9 @@
         StringBuilder sql = new StringBuilder(120);
         sql.append("UPDATE ");
         if (algorithm != null) {
-            sql.append(" OR ");
+            sql.append("OR ");
             sql.append(algorithm.value());
+            sql.append(" ");
         }
         
         sql.append(table);
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 8b474d5..7830cb7 100755
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -30,13 +30,13 @@
 import android.inputmethodservice.Keyboard.Key;
 import android.os.Handler;
 import android.os.Message;
-import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.view.GestureDetector;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup.LayoutParams;
 import android.widget.PopupWindow;
 import android.widget.TextView;
@@ -206,8 +206,7 @@
 
     private static final int REPEAT_INTERVAL = 50; // ~20 keys per second
     private static final int REPEAT_START_DELAY = 400;
-    private static final int LONGPRESS_TIMEOUT = 800;
-    // Deemed to be too short : ViewConfiguration.getLongPressTimeout();
+    private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout();
 
     private static int MAX_NEARBY_KEYS = 12;
     private int[] mDistances = new int[MAX_NEARBY_KEYS];
@@ -410,6 +409,9 @@
         invalidateAllKeys();
         computeProximityThreshold(keyboard);
         mMiniKeyboardCache.clear(); // Not really necessary to do every time, but will free up views
+        // Switching to a different keyboard should abort any pending keys so that the key up
+        // doesn't get delivered to the old or new keyboard
+        mAbortKey = true; // Until the next ACTION_DOWN
     }
 
     /**
diff --git a/core/java/android/net/http/Request.java b/core/java/android/net/http/Request.java
index e160ab6..1b6568e 100644
--- a/core/java/android/net/http/Request.java
+++ b/core/java/android/net/http/Request.java
@@ -417,8 +417,7 @@
         }
         return status >= HttpStatus.SC_OK
             && status != HttpStatus.SC_NO_CONTENT
-            && status != HttpStatus.SC_NOT_MODIFIED
-            && status != HttpStatus.SC_RESET_CONTENT;
+            && status != HttpStatus.SC_NOT_MODIFIED;
     }
 
     /**
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 528def5..e203fd5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -508,6 +508,19 @@
     public abstract long getBatteryUptime(long curTime);
 
     /**
+     * @deprecated use getRadioDataUptime
+     */
+    public long getRadioDataUptimeMs() {
+        return getRadioDataUptime() / 1000;
+    }
+
+    /**
+     * Returns the time that the radio was on for data transfers.
+     * @return the uptime in microseconds while unplugged
+     */
+    public abstract long getRadioDataUptime();
+
+    /**
      * Returns the current battery realtime in microseconds.
      *
      * @param curTime the amount of elapsed realtime in microseconds.
@@ -1128,7 +1141,14 @@
         }
         if (!didOne) sb.append("No activity");
         pw.println(sb.toString());
-        
+
+        sb.setLength(0);
+        sb.append(prefix);
+        sb.append("  Radio data uptime when unplugged: ");
+        sb.append(getRadioDataUptime() / 1000);
+        sb.append(" ms");
+        pw.println(sb.toString());
+
         sb.setLength(0);
         sb.append(prefix);
                 sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b779d59..69c3d41 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -19,6 +19,7 @@
 import android.content.Intent;
 import android.content.ContentProviderClient;
 import android.content.ContentProviderOperation;
+import android.content.res.Resources;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
@@ -138,8 +139,8 @@
         public static final String PHOTO_ID = "photo_id";
 
         /**
-         * Lookup value that reflects the {@link Groups#MEMBERS_VISIBLE} state
-         * of any {@link GroupMembership} for this aggregate.
+         * Lookup value that reflects the {@link Groups#GROUP_VISIBLE} state of
+         * any {@link GroupMembership} for this aggregate.
          */
         public static final String IN_VISIBLE_GROUP = "in_visible_group";
     }
@@ -162,28 +163,31 @@
 
         /**
          * The content:// style URI for this table joined with useful data from
-         * {@link Data} and {@link Presence}.
+         * {@link Data}.
          */
         public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI,
                 "aggregates_summary");
+
         /**
          * The content:// style URI used for "type-to-filter" functionality on the
-         * {@link CONTENT_SUMMARY_URI} URI. The filter string will be used to match
+         * {@link #CONTENT_SUMMARY_URI} URI. The filter string will be used to match
          * various parts of the aggregate name. The filter argument should be passed
          * as an additional path segment after this URI.
          */
         public static final Uri CONTENT_SUMMARY_FILTER_URI = Uri.withAppendedPath(
                 CONTENT_SUMMARY_URI, "filter");
+
         /**
          * The content:// style URI for this table joined with useful data from
-         * {@link Data} and {@link Presence}, filtered to include only starred aggregates
+         * {@link Data}, filtered to include only starred aggregates
          * and the most frequently contacted aggregates.
          */
         public static final Uri CONTENT_SUMMARY_STREQUENT_URI = Uri.withAppendedPath(
                 CONTENT_SUMMARY_URI, "strequent");
+
         /**
          * The content:// style URI used for "type-to-filter" functionality on the
-         * {@link CONTENT_SUMMARY_STREQUENT_URI} URI. The filter string will be used to match
+         * {@link #CONTENT_SUMMARY_STREQUENT_URI} URI. The filter string will be used to match
          * various parts of the aggregate name. The filter argument should be passed
          * as an additional path segment after this URI.
          */
@@ -192,6 +196,7 @@
 
         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.
@@ -247,43 +252,80 @@
     }
 
     /**
-     * Constants for the contacts table, which contains the base contact information.
+     * Columns that appear when each row of a table belongs to a specific
+     * account, including sync information that an account may need.
      */
-    public static final class Contacts implements BaseColumns, ContactOptionsColumns {
+    private interface SyncColumns {
         /**
-         * This utility class cannot be instantiated
-         */
-        private Contacts()  {}
-
-        /**
-         * The package name that owns this contact and all of its details. This
-         * package has control over the {@link #IS_RESTRICTED} flag, and can
-         * grant {@link RestrictionExceptions} to other packages.
-         */
-        public static final String PACKAGE = "package";
-
-        /**
-         * Flag indicating that this data entry has been restricted by the owner
-         * {@link #PACKAGE}.
-         */
-        public static final String IS_RESTRICTED = "is_restricted";
-
-        /**
-         * A reference to the name of the account to which this data belongs
+         * The name of the account instance to which this row belongs.
+         * <P>Type: TEXT</P>
          */
         public static final String ACCOUNT_NAME = "account_name";
 
         /**
-         * A reference to the type of the account to which this data belongs
+         * The type of account to which this row belongs, which when paired with
+         * {@link #ACCOUNT_NAME} identifies a specific account.
+         * <P>Type: TEXT</P>
          */
         public static final String ACCOUNT_TYPE = "account_type";
 
         /**
+         * String that uniquely identifies this row to its source account.
+         * <P>Type: TEXT</P>
+         */
+        public static final String SOURCE_ID = "sourceid";
+
+        /**
+         * Version number that is updated whenever this row or its related data
+         * changes.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String VERSION = "version";
+
+        /**
+         * Flag indicating that {@link #VERSION} has changed, and this row needs
+         * to be synchronized by its owning account.
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String DIRTY = "dirty";
+
+    }
+
+    private interface ContactsColumns {
+        /**
          * A reference to the {@link Aggregates#_ID} that this data belongs to.
+         * <P>Type: INTEGER</P>
          */
         public static final String AGGREGATE_ID = "aggregate_id";
 
         /**
+         * Flag indicating that this {@link Contacts} entry and its children has
+         * been restricted to specific platform apps.
+         * <P>Type: INTEGER (boolean)</P>
+         *
+         * @hide until finalized in future platform release
+         */
+        public static final String IS_RESTRICTED = "is_restricted";
+
+        /**
+         * The aggregation mode for this contact.
+         * <P>Type: INTEGER</P>
+         */
+        public static final String AGGREGATION_MODE = "aggregation_mode";
+    }
+
+    /**
+     * Constants for the contacts table, which contains the base contact information.
+     */
+    public static final class Contacts implements BaseColumns, ContactsColumns, SyncColumns,
+            ContactOptionsColumns {
+        /**
+         * This utility class cannot be instantiated
+         */
+        private Contacts() {
+        }
+
+        /**
          * The content:// style URI for this table
          */
         public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts");
@@ -311,28 +353,6 @@
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person";
 
         /**
-         * A string that uniquely identifies this contact to its source, which is referred to
-         * by the {@link #ACCOUNT_NAME} and {@link #ACCOUNT_TYPE}
-         */
-        public static final String SOURCE_ID = "sourceid";
-
-        /**
-         * An integer that is updated whenever this contact or its data changes.
-         */
-        public static final String VERSION = "version";
-
-        /**
-         * Set to 1 whenever the version changes
-         */
-        public static final String DIRTY = "dirty";
-
-        /**
-         * The aggregation mode for this contact.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String AGGREGATION_MODE = "aggregation_mode";
-
-        /**
          * Aggregation mode: aggregate asynchronously.
          */
         public static final int AGGREGATION_MODE_DEFAULT = 0;
@@ -357,7 +377,8 @@
             /**
              * no public constructor since this is a utility class
              */
-            private Data() {}
+            private Data() {
+            }
 
             /**
              * The directory twig for this sub-table
@@ -368,7 +389,14 @@
 
     private interface DataColumns {
         /**
-         * The mime-type of the item represented by this row.
+         * The package name to use when creating {@link Resources} objects for
+         * this data row. This value is only designed for use when building user
+         * interfaces, and should not be used to infer the owner.
+         */
+        public static final String RES_PACKAGE = "res_package";
+
+        /**
+         * The MIME type of the item represented by this row.
          */
         public static final String MIMETYPE = "mimetype";
 
@@ -419,6 +447,16 @@
         public static final String DATA9 = "data9";
         /** Generic data column, the meaning is {@link #MIMETYPE} specific */
         public static final String DATA10 = "data10";
+        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
+        public static final String DATA11 = "data11";
+        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
+        public static final String DATA12 = "data12";
+        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
+        public static final String DATA13 = "data13";
+        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
+        public static final String DATA14 = "data14";
+        /** Generic data column, the meaning is {@link #MIMETYPE} specific */
+        public static final String DATA15 = "data15";
     }
 
     /**
@@ -445,9 +483,10 @@
     }
 
     /**
-     * A table that represents the result of looking up a phone number, for example for caller ID.
-     * The table joins that data row for the phone number with the contact that owns the number.
-     * To perform a lookup you must append the number you want to find to {@link #CONTENT_URI}.
+     * A table that represents the result of looking up a phone number, for
+     * example for caller ID. The table joins that data row for the phone number
+     * with the contact that owns the number. To perform a lookup you must
+     * append the number you want to find to {@link #CONTENT_FILTER_URI}.
      */
     public static final class PhoneLookup implements BaseColumns, DataColumns, AggregatesColumns {
         /**
@@ -474,35 +513,34 @@
     private interface PresenceColumns {
         /**
          * Reference to the {@link Aggregates#_ID} this presence references.
+         * <P>Type: INTEGER</P>
          */
         public static final String AGGREGATE_ID = "aggregate_id";
 
         /**
          * Reference to the {@link Data#_ID} entry that owns this presence.
+         * <P>Type: INTEGER</P>
          */
         public static final String DATA_ID = "data_id";
 
         /**
          * The IM service the presence is coming from. Formatted using either
-         * {@link Contacts.ContactMethods#encodePredefinedImProtocol} or
-         * {@link Contacts.ContactMethods#encodeCustomImProtocol}.
-         * <p>
-         * Type: STRING
+         * {@link CommonDataKinds.Im#encodePredefinedImProtocol(int)} or
+         * {@link CommonDataKinds.Im#encodeCustomImProtocol(String)}.
+         * <P>Type: TEXT</P>
          */
         public static final String IM_PROTOCOL = "im_protocol";
 
         /**
          * The IM handle the presence item is for. The handle is scoped to the
          * {@link #IM_PROTOCOL}.
-         * <p>
-         * Type: STRING
+         * <P>Type: TEXT</P>
          */
         public static final String IM_HANDLE = "im_handle";
 
         /**
          * The IM account for the local user that the presence data came from.
-         * <p>
-         * Type: STRING
+         * <P>Type: TEXT</P>
          */
         public static final String IM_ACCOUNT = "im_account";
     }
@@ -573,8 +611,8 @@
      */
     public static final class CommonDataKinds {
         /**
-         * The {@link Data#PACKAGE} value for common data that should be shown
-         * using a default style.
+         * The {@link Data#RES_PACKAGE} value for common data that should be
+         * shown using a default style.
          */
         public static final String PACKAGE_COMMON = "common";
 
@@ -583,18 +621,19 @@
          */
         private interface BaseCommonColumns {
             /**
-             * The package name that defines this type of data.
+             * The package name to use when creating {@link Resources} objects for
+             * this data row. This value is only designed for use when building user
+             * interfaces, and should not be used to infer the owner.
              */
-            public static final String PACKAGE = "package";
+            public static final String RES_PACKAGE = "res_package";
 
             /**
-             * The mime-type of the item represented by this row.
+             * The MIME type of the item represented by this row.
              */
             public static final String MIMETYPE = "mimetype";
 
             /**
-             * A reference to the {@link android.provider.ContactsContract.Contacts#_ID} that this
-             * data belongs to.
+             * The {@link Contacts#_ID} that this data belongs to.
              */
             public static final String CONTACT_ID = "contact_id";
         }
@@ -636,10 +675,10 @@
         /**
          * Parts of the name.
          */
-        public static final class StructuredName {
+        public static final class StructuredName implements BaseCommonColumns {
             private StructuredName() {}
 
-            /** Mime-type used when storing this in data table. */
+            /** MIME type used when storing this in data table. */
             public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name";
 
             /**
@@ -699,10 +738,10 @@
         /**
          * A nickname.
          */
-        public static final class Nickname implements CommonColumns {
+        public static final class Nickname implements CommonColumns, BaseCommonColumns {
             private Nickname() {}
 
-            /** Mime-type used when storing this in data table. */
+            /** MIME type used when storing this in data table. */
             public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname";
 
             public static final int TYPE_DEFAULT = 1;
@@ -723,7 +762,7 @@
         public static final class Phone implements BaseCommonColumns, CommonColumns {
             private Phone() {}
 
-            /** Mime-type used when storing this in data table. */
+            /** MIME type used when storing this in data table. */
             public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone";
 
             /**
@@ -734,17 +773,17 @@
 
             /**
              * The content:// style URI for all data records of the
-             * {@link Phone.CONTENT_ITEM_TYPE} mimetype, combined with the associated contact
-             * and aggregate data.
+             * {@link Phone#CONTENT_ITEM_TYPE} MIME type, combined with the
+             * associated contact and aggregate data.
              */
             public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI,
                     "phones");
 
             /**
              * The content:// style URI for filtering data records of the
-             * {@link Phone.CONTENT_ITEM_TYPE} mimetype, combined with the associated contact
-             * and aggregate data. The filter argument should be passed
-             * as an additional path segment after this URI.
+             * {@link Phone#CONTENT_ITEM_TYPE} MIME type, combined with the
+             * associated contact and aggregate data. The filter argument should
+             * be passed as an additional path segment after this URI.
              */
             public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI,
                     "filter");
@@ -770,7 +809,7 @@
         public static final class Email implements BaseCommonColumns, CommonColumns {
             private Email() {}
 
-            /** Mime-type used when storing this in data table. */
+            /** MIME type used when storing this in data table. */
             public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email";
 
             public static final int TYPE_HOME = 1;
@@ -781,10 +820,11 @@
         /**
          * Common data definition for postal addresses.
          */
-        public static final class Postal implements BaseCommonColumns, CommonColumns {
-            private Postal() {}
+        public static final class StructuredPostal implements BaseCommonColumns, CommonColumns {
+            private StructuredPostal() {
+            }
 
-            /** Mime-type used when storing this in data table. */
+            /** MIME type used when storing this in data table. */
             public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/postal-address";
 
             /**
@@ -795,8 +835,7 @@
 
             /**
              * The content:// style URI for all data records of the
-             * {@link Postal.CONTENT_ITEM_TYPE} mimetype, combined with the associated contact
-             * and aggregate data.
+             * {@link StructuredPostal#CONTENT_ITEM_TYPE} MIME type.
              */
             public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI,
                     "postals");
@@ -804,6 +843,95 @@
             public static final int TYPE_HOME = 1;
             public static final int TYPE_WORK = 2;
             public static final int TYPE_OTHER = 3;
+
+            /**
+             * The full, unstructured postal address.
+             * <p>
+             * Type: TEXT
+             */
+            public static final String FORMATTED_ADDRESS = DATA;
+
+            /**
+             * The agent who actually receives the mail. Used in work addresses.
+             * Also for 'in care of' or 'c/o'.
+             * <p>
+             * Type: TEXT
+             */
+            public static final String AGENT = "data4";
+
+            /**
+             * Used in places where houses or buildings have names (and not
+             * necessarily numbers), eg. "The Pillars".
+             * <p>
+             * Type: TEXT
+             */
+            public static final String HOUSENAME = "data5";
+
+            /**
+             * Can be street, avenue, road, etc. This element also includes the
+             * house number and room/apartment/flat/floor number.
+             * <p>
+             * Type: TEXT
+             */
+            public static final String STREET = "data6";
+
+            /**
+             * Covers actual P.O. boxes, drawers, locked bags, etc. This is
+             * usually but not always mutually exclusive with street.
+             * <p>
+             * Type: TEXT
+             */
+            public static final String POBOX = "data7";
+
+            /**
+             * This is used to disambiguate a street address when a city
+             * contains more than one street with the same name, or to specify a
+             * small place whose mail is routed through a larger postal town. In
+             * China it could be a county or a minor city.
+             * <p>
+             * Type: TEXT
+             */
+            public static final String NEIGHBOHOOD = "data8";
+
+            /**
+             * Can be city, village, town, borough, etc. This is the postal town
+             * and not necessarily the place of residence or place of business.
+             * <p>
+             * Type: TEXT
+             */
+            public static final String CITY = "data9";
+
+            /**
+             * Handles administrative districts such as U.S. or U.K. counties
+             * that are not used for mail addressing purposes. Subregion is not
+             * intended for delivery addresses.
+             * <p>
+             * Type: TEXT
+             */
+            public static final String SUBREGION = "data10";
+
+            /**
+             * A state, province, county (in Ireland), Land (in Germany),
+             * departement (in France), etc.
+             * <p>
+             * Type: TEXT
+             */
+            public static final String REGION = "data11";
+
+            /**
+             * StructuredPostal code. Usually country-wide, but sometimes specific to the
+             * city (e.g. "2" in "Dublin 2, Ireland" addresses).
+             * <p>
+             * Type: TEXT
+             */
+            public static final String POSTCODE = "data12";
+
+            /**
+             * The name or code of the country.
+             * <p>
+             * Type: TEXT
+             */
+            public static final String COUNTRY = "data13";
         }
 
        /**
@@ -812,7 +940,7 @@
         public static final class Im implements BaseCommonColumns, CommonColumns {
             private Im() {}
 
-            /** Mime-type used when storing this in data table. */
+            /** MIME type used when storing this in data table. */
             public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im";
 
             public static final int TYPE_HOME = 1;
@@ -872,7 +1000,7 @@
         public static final class Organization implements BaseCommonColumns, CommonColumns {
             private Organization() {}
 
-            /** Mime-type used when storing this in data table. */
+            /** MIME type used when storing this in data table. */
             public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization";
 
             public static final int TYPE_WORK = 1;
@@ -897,7 +1025,7 @@
         public static final class Photo implements BaseCommonColumns {
             private Photo() {}
 
-            /** Mime-type used when storing this in data table. */
+            /** MIME type used when storing this in data table. */
             public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
 
             /**
@@ -915,7 +1043,7 @@
         public static final class Note implements BaseCommonColumns {
             private Note() {}
 
-            /** Mime-type used when storing this in data table. */
+            /** MIME type used when storing this in data table. */
             public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note";
 
             /**
@@ -931,7 +1059,7 @@
         public static final class GroupMembership implements BaseCommonColumns {
             private GroupMembership() {}
 
-            /** Mime-type used when storing this in data table. */
+            /** MIME type used when storing this in data table. */
             public static final String CONTENT_ITEM_TYPE =
                     "vnd.android.cursor.item/group_membership";
 
@@ -945,24 +1073,30 @@
             /**
              * The sourceid of the group that this group membership refers to.  Exactly one of
              * this or {@link #GROUP_ROW_ID} must be set when inserting a row.
-             * <P>Type: STRING</P>
+             * <P>Type: TEXT</P>
              */
             public static final String GROUP_SOURCE_ID = "group_sourceid";
         }
+
+        /**
+         * Website related to the contact.
+         */
+        public static final class Website implements BaseCommonColumns {
+            private Website() {}
+
+            /** MIME type used when storing this in data table. */
+            public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website";
+
+            /**
+             * The website URL string.
+             * <P>Type: TEXT</P>
+             */
+            public static final String URL = "data1";
+        }
     }
 
     public interface GroupsColumns {
         /**
-         * The package name that owns this group.
-         */
-        public static final String PACKAGE = "package";
-
-        /**
-         * A unique identifier for the package that owns this group.
-         */
-        public static final String PACKAGE_ID = "package_id";
-
-        /**
          * The display title of this group.
          * <p>
          * Type: TEXT
@@ -970,12 +1104,32 @@
         public static final String TITLE = "title";
 
         /**
+         * The package name to use when creating {@link Resources} objects for
+         * this group. This value is only designed for use when building user
+         * interfaces, and should not be used to infer the owner.
+         */
+        public static final String RES_PACKAGE = "res_package";
+
+        /**
          * The display title of this group to load as a resource from
-         * {@link #PACKAGE}, which may be localized.
+         * {@link #RES_PACKAGE}, which may be localized.
+         * <P>Type: TEXT</P>
+         */
+        public static final String TITLE_RES = "title_res";
+
+        /**
+         * Notes about the group.
          * <p>
          * Type: TEXT
          */
-        public static final String TITLE_RESOURCE = "title_res";
+        public static final String NOTES = "notes";
+
+        /**
+         * The ID of this group if it is a System Group, i.e. a group that has a special meaning
+         * to the sync adapter, null otherwise.
+         * <P>Type: TEXT</P>
+         */
+        public static final String SYSTEM_ID = "system_id";
 
         /**
          * The total number of {@link Aggregates} that have
@@ -997,32 +1151,6 @@
         public static final String SUMMARY_WITH_PHONES = "summ_phones";
 
         /**
-         * A reference to the name of the account to which this data belongs
-         */
-        public static final String ACCOUNT_NAME = "account_name";
-
-        /**
-         * A reference to the type of the account to which this data belongs
-         */
-        public static final String ACCOUNT_TYPE = "account_type";
-
-        /**
-         * A string that uniquely identifies this contact to its source, which is referred to
-         * by the {@link #ACCOUNT_NAME} and {@link #ACCOUNT_TYPE}
-         */
-        public static final String SOURCE_ID = "sourceid";
-
-        /**
-         * An integer that is updated whenever this contact or its data changes.
-         */
-        public static final String VERSION = "version";
-
-        /**
-         * Set to 1 whenever the version changes
-         */
-        public static final String DIRTY = "dirty";
-
-        /**
          * Flag indicating if the contacts belonging to this group should be
          * visible in any user interface.
          * <p>
@@ -1034,11 +1162,12 @@
     /**
      * Constants for the groups table.
      */
-    public static final class Groups implements BaseColumns, GroupsColumns {
+    public static final class Groups implements BaseColumns, GroupsColumns, SyncColumns {
         /**
          * This utility class cannot be instantiated
          */
-        private Groups()  {}
+        private Groups() {
+        }
 
         /**
          * The content:// style URI for this table
@@ -1047,7 +1176,7 @@
 
         /**
          * The content:// style URI for this table joined with details data from
-         * {@link Data} and {@link Presence}.
+         * {@link Data}.
          */
         public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI,
                 "groups_summary");
@@ -1127,53 +1256,6 @@
         public static final String CONTACT_ID = "contact_id";
     }
 
-    private interface RestrictionExceptionsColumns {
-        /**
-         * Package name of a specific data provider, which will be matched
-         * against {@link Data#PACKAGE}.
-         * <p>
-         * Type: STRING
-         */
-        public static final String PACKAGE_PROVIDER = "package_provider";
-
-        /**
-         * Package name of a specific data client, which will be matched against
-         * the incoming {@link android.os.Binder#getCallingUid()} to decide if
-         * the caller can access values with {@link Data#IS_RESTRICTED} flags.
-         * <p>
-         * Type: STRING
-         */
-        public static final String PACKAGE_CLIENT = "package_client";
-
-        /**
-         * Flag indicating if {@link #PACKAGE_PROVIDER} allows
-         * {@link #PACKAGE_CLIENT} to access restricted {@link Data} rows.
-         * <p>
-         * Type: INTEGER
-         */
-        public static final String ALLOW_ACCESS = "allow_access";
-    }
-
-    /**
-     * Constants for {@link Data} restriction exceptions. Sync adapters who
-     * insert restricted data can use this table to specify exceptions about
-     * which additional packages can access that restricted data.You can only
-     * modify rules for a {@link RestrictionExceptionsColumns#PACKAGE_PROVIDER}
-     * that your {@link android.os.Binder#getCallingUid()} owns.
-     */
-    public static final class RestrictionExceptions implements RestrictionExceptionsColumns {
-        /**
-         * This utility class cannot be instantiated
-         */
-        private RestrictionExceptions() {}
-
-        /**
-         * The content:// style URI for this table
-         */
-        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI,
-                "restriction_exceptions");
-    }
-
     /**
      * Contains helper classes used to create or manage {@link android.content.Intent Intents}
      * that involve contacts.
@@ -1500,8 +1582,8 @@
 
             /**
              * The extra field for the IM protocol
-             * <P>Type: the result of {@link Contacts.ContactMethods#encodePredefinedImProtocol}
-             * or {@link Contacts.ContactMethods#encodeCustomImProtocol}.</P>
+             * <P>Type: the result of {@link CommonDataKinds.Im#encodePredefinedImProtocol(int)}
+             * or {@link CommonDataKinds.Im#encodeCustomImProtocol(String)}.</P>
              */
             public static final String IM_PROTOCOL = "im_protocol";
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index df3001d..42ba149 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2530,11 +2530,17 @@
         public static final String CHECKIN_EVENTS = "checkin_events";
 
         /**
-         * Event tags for list of services to upload during checkin.
+         * Comma-separated list of service names to dump and upload during checkin.
          */
         public static final String CHECKIN_DUMPSYS_LIST = "checkin_dumpsys_list";
 
         /**
+         * Comma-separated list of packages to specify for each service that is
+         * dumped (currently only meaningful for user activity).
+         */
+        public static final String CHECKIN_PACKAGE_LIST = "checkin_package_list";
+
+        /**
          * The interval (in seconds) between periodic checkin attempts.
          */
         public static final String CHECKIN_INTERVAL = "checkin_interval";
diff --git a/core/java/android/provider/SocialContract.java b/core/java/android/provider/SocialContract.java
index 28bf8db..a3b1d6e 100644
--- a/core/java/android/provider/SocialContract.java
+++ b/core/java/android/provider/SocialContract.java
@@ -16,6 +16,7 @@
 
 package android.provider;
 
+import android.content.res.Resources;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.provider.ContactsContract.Aggregates;
@@ -36,11 +37,13 @@
 
     private interface ActivitiesColumns {
         /**
-         * The package name that owns this social activity.
+         * The package name to use when creating {@link Resources} objects for
+         * this data row. This value is only designed for use when building user
+         * interfaces, and should not be used to infer the owner.
          * <p>
          * Type: TEXT
          */
-        public static final String PACKAGE = "package";
+        public static final String RES_PACKAGE = "res_package";
 
         /**
          * The mime-type of this social activity.
diff --git a/core/java/android/server/search/SearchDialogWrapper.java b/core/java/android/server/search/SearchDialogWrapper.java
index d3ef5de..b8a9875 100644
--- a/core/java/android/server/search/SearchDialogWrapper.java
+++ b/core/java/android/server/search/SearchDialogWrapper.java
@@ -190,6 +190,9 @@
         msgData.putBundle(KEY_APP_SEARCH_DATA, appSearchData);
         msgData.putInt(KEY_IDENT, ident);
         mSearchUiThread.sendMessage(msg);
+        // be a little more eager in setting this so isVisible will return the correct value if
+        // called immediately after startSearch
+        mVisible = true;
     }
 
     /**
@@ -199,6 +202,9 @@
     public void stopSearch() {
         if (DBG) debug("stopSearch()");
         mSearchUiThread.sendEmptyMessage(MSG_STOP_SEARCH);
+        // be a little more eager in setting this so isVisible will return the correct value if
+        // called immediately after stopSearch
+        mVisible = false;
     }
 
     /**
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 4e0a87c..8f8d976 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -922,7 +922,7 @@
                 mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = loc.getISO3Country();
                 mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = loc.getVariant();
                 // the language is not set here, instead it is cached so it will be associated
-                // with all upcoming utterances. But we still need to change the language support,
+                // with all upcoming utterances. But we still need to report the language support,
                 // which is achieved by calling isLanguageAvailable()
                 result = mITts.isLanguageAvailable(
                         mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1],
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index bfab49d..061f98a 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -123,47 +123,67 @@
      */
     public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation,
             int screenLayout) {
-        if (!compatibilityInfo.isConfiguredExpandable()) {
-            // Note: this assume that configuration is updated before calling
-            // updateMetrics method.
-            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);
-                // 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
-                    widthPixels = defaultWidth;
-                }
-                if (defaultHeight < heightPixels) {
-                    heightPixels = defaultHeight;
-                }
-                
-            } else {
-                // the screen size is same as expected size. make it expandable
+        boolean expandable = compatibilityInfo.isConfiguredExpandable();
+        boolean largeScreens = compatibilityInfo.isConfiguredLargeScreens();
+        
+        // Note: this assume that configuration is updated before calling
+        // updateMetrics method.
+        if (!expandable) {
+            if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) == 0) {
+                expandable = true;
+                // the current screen size is compatible with non-resizing apps.
                 compatibilityInfo.setExpandable(true);
+            } else {
+                compatibilityInfo.setExpandable(false);
+            }
+        }
+        if (!largeScreens) {
+            if ((screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK)
+                    != Configuration.SCREENLAYOUT_SIZE_LARGE) {
+                largeScreens = true;
+                // the current screen size is not large.
+                compatibilityInfo.setLargeScreens(true);
+            } else {
+                compatibilityInfo.setLargeScreens(false);
+            }
+        }
+        
+        if (!expandable || !largeScreens) {
+            // This is a larger screen device and the app is not 
+            // compatible with large screens, so diddle it.
+            
+            // 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 +
+                            0.5f);
+                    defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density +
+                            0.5f);
+                    break;
+                }
+                case Configuration.ORIENTATION_PORTRAIT:
+                case Configuration.ORIENTATION_SQUARE:
+                default: {
+                    defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density +
+                            0.5f);
+                    defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density +
+                            0.5f);
+                    break;
+                }
+                case Configuration.ORIENTATION_UNDEFINED: {
+                    // don't change
+                    return;
+                }
+            }
+            
+            if (defaultWidth < widthPixels) {
+                // content/window's x offset in original pixels
+                widthPixels = defaultWidth;
+            }
+            if (defaultHeight < heightPixels) {
+                heightPixels = defaultHeight;
             }
         }
         if (compatibilityInfo.isScalingRequired()) {
@@ -172,8 +192,8 @@
             scaledDensity *= invertedRatio;
             xdpi *= invertedRatio;
             ydpi *= invertedRatio;
-            widthPixels *= invertedRatio;
-            heightPixels *= invertedRatio;
+            widthPixels = (int) (widthPixels * invertedRatio + 0.5f);
+            heightPixels = (int) (heightPixels * invertedRatio + 0.5f);
         }
     }
 
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index c41ee32..52f1a97 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -27,16 +27,23 @@
  */
 public final class MotionEvent implements Parcelable {
     /**
+     * Bit mask of the parts of the action code that are the action itself.
+     */
+    public static final int ACTION_MASK             = 0xff;
+    
+    /**
      * Constant for {@link #getAction}: A pressed gesture has started, the
      * motion contains the initial starting location.
      */
     public static final int ACTION_DOWN             = 0;
+    
     /**
      * Constant for {@link #getAction}: A pressed gesture has finished, the
      * motion contains the final release location as well as any intermediate
      * points since the last down or move event.
      */
     public static final int ACTION_UP               = 1;
+    
     /**
      * Constant for {@link #getAction}: A change has happened during a
      * press gesture (between {@link #ACTION_DOWN} and {@link #ACTION_UP}).
@@ -44,12 +51,14 @@
      * points since the last down or move event.
      */
     public static final int ACTION_MOVE             = 2;
+    
     /**
      * Constant for {@link #getAction}: The current gesture has been aborted.
      * You will not receive any more points in it.  You should treat this as
      * an up event, but not perform any action that you normally would.
      */
     public static final int ACTION_CANCEL           = 3;
+    
     /**
      * Constant for {@link #getAction}: A movement has happened outside of the
      * normal bounds of the UI element.  This does not provide a full gesture,
@@ -57,6 +66,61 @@
      */
     public static final int ACTION_OUTSIDE          = 4;
 
+    /**
+     * A non-primary pointer has gone down.  The bits in
+     * {@link #ACTION_POINTER_MASK} indicate which pointer changed.
+     */
+    public static final int ACTION_POINTER_DOWN     = 5;
+    
+    /**
+     * The primary pointer has gone done.
+     */
+    public static final int ACTION_POINTER_1_DOWN   = ACTION_POINTER_DOWN | 0x0000;
+    
+    /**
+     * The secondary pointer has gone done.
+     */
+    public static final int ACTION_POINTER_2_DOWN   = ACTION_POINTER_DOWN | 0x0100;
+    
+    /**
+     * The tertiary pointer has gone done.
+     */
+    public static final int ACTION_POINTER_3_DOWN   = ACTION_POINTER_DOWN | 0x0200;
+    
+    /**
+     * A non-primary pointer has gone up.  The bits in
+     * {@link #ACTION_POINTER_MASK} indicate which pointer changed.
+     */
+    public static final int ACTION_POINTER_UP       = 6;
+    
+    /**
+     * The primary pointer has gone up.
+     */
+    public static final int ACTION_POINTER_1_UP     = ACTION_POINTER_UP | 0x0000;
+    
+    /**
+     * The secondary pointer has gone up.
+     */
+    public static final int ACTION_POINTER_2_UP     = ACTION_POINTER_UP | 0x0100;
+    
+    /**
+     * The tertiary pointer has gone up.
+     */
+    public static final int ACTION_POINTER_3_UP     = ACTION_POINTER_UP | 0x0200;
+    
+    /**
+     * Bits in the action code that represent a pointer ID, used with
+     * {@link #ACTION_POINTER_DOWN} and {@link #ACTION_POINTER_UP}.  Pointer IDs
+     * start at 0, with 0 being the primary (first) pointer in the motion.
+     */
+    public static final int ACTION_POINTER_MASK     = 0xff00;
+    
+    /**
+     * Bit shift for the action bits holding the pointer identifier as
+     * defined by {@link #ACTION_POINTER_MASK}.
+     */
+    public static final int ACTION_POINTER_SHIFT    = 8;
+    
     private static final boolean TRACK_RECYCLED_LOCATION = false;
 
     /**
@@ -79,35 +143,90 @@
      */
     public static final int EDGE_RIGHT = 0x00000008;
 
+    /**
+     * This is the part of the state data that holds the finger identifier
+     * for the sample.
+     */
+    static private final int STATE_FINGER_ID_MASK = 0xff;
+    
+    /**
+     * Special value for STATE_FINGER_ID_MASK indicating that the finger
+     * is not down in that sample.
+     */
+    static private final int STATE_FINGER_ID_NONE = 0xff;
+    
+    /**
+     * Offset for the sample's X coordinate.
+     * @hide
+     */
+    static public final int SAMPLE_X = 0;
+    
+    /**
+     * Offset for the sample's Y coordinate.
+     * @hide
+     */
+    static public final int SAMPLE_Y = 1;
+    
+    /**
+     * Offset for the sample's X coordinate.
+     * @hide
+     */
+    static public final int SAMPLE_PRESSURE = 2;
+    
+    /**
+     * Offset for the sample's X coordinate.
+     * @hide
+     */
+    static public final int SAMPLE_SIZE = 3;
+    
+    /**
+     * Number of data items for each sample.
+     * @hide
+     */
+    static public final int NUM_SAMPLE_DATA = 4;
+    
+    static private final int BASE_AVAIL_POINTERS = 2;
+    static private final int BASE_AVAIL_SAMPLES = 8;
+    
     static private final int MAX_RECYCLED = 10;
     static private Object gRecyclerLock = new Object();
     static private int gRecyclerUsed = 0;
     static private MotionEvent gRecyclerTop = null;
 
     private long mDownTime;
-    private long mEventTime;
     private long mEventTimeNano;
     private int mAction;
-    private float mX;
-    private float mY;
     private float mRawX;
     private float mRawY;
-    private float mPressure;
-    private float mSize;
-    private int mMetaState;
-    private int mNumHistory;
-    private float[] mHistory;
-    private long[] mHistoryTimes;
     private float mXPrecision;
     private float mYPrecision;
     private int mDeviceId;
     private int mEdgeFlags;
+    private int mMetaState;
+    
+    // Here is the actual event data.  Note that the order of the array
+    // is a little odd: the first entry is the most recent, and the ones
+    // following it are the historical data from oldest to newest.  This
+    // allows us to easily retrieve the most recent data, without having
+    // to copy the arrays every time a new sample is added.
+    
+    private int mNumPointers;
+    private int mNumSamples;
+    // Array of (mNumSamples * mNumPointers) size of control data.
+    private int[] mStateSamples;
+    // Array of (mNumSamples * mNumPointers * NUM_SAMPLE_DATA) size of event data.
+    private float[] mDataSamples;
+    // Array of mNumSamples size of time stamps.
+    private long[] mTimeSamples;
 
     private MotionEvent mNext;
     private RuntimeException mRecycledLocation;
     private boolean mRecycled;
 
     private MotionEvent() {
+        mStateSamples = new int[BASE_AVAIL_POINTERS*BASE_AVAIL_SAMPLES];
+        mDataSamples = new float[BASE_AVAIL_POINTERS*BASE_AVAIL_SAMPLES*NUM_SAMPLE_DATA];
+        mTimeSamples = new long[BASE_AVAIL_SAMPLES];
     }
 
     static private MotionEvent obtain() {
@@ -160,22 +279,31 @@
      * @hide
      */
     static public MotionEvent obtainNano(long downTime, long eventTime, long eventTimeNano,
-            int action, float x, float y, float pressure, float size, int metaState,
+            int action, int pointers, float[] inData, int metaState,
             float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
         MotionEvent ev = obtain();
         ev.mDeviceId = deviceId;
         ev.mEdgeFlags = edgeFlags;
         ev.mDownTime = downTime;
-        ev.mEventTime = eventTime;
         ev.mEventTimeNano = eventTimeNano;
         ev.mAction = action;
-        ev.mX = ev.mRawX = x;
-        ev.mY = ev.mRawY = y;
-        ev.mPressure = pressure;
-        ev.mSize = size;
         ev.mMetaState = metaState;
         ev.mXPrecision = xPrecision;
         ev.mYPrecision = yPrecision;
+        
+        ev.mNumPointers = pointers;
+        ev.mNumSamples = 1;
+        
+        float[] data = ev.mDataSamples;
+        System.arraycopy(inData, 0, data, 0, pointers * NUM_SAMPLE_DATA);
+        
+        int[] state = ev.mStateSamples;
+        while (pointers > 0) {
+            pointers--;
+            state[pointers] = pointers;
+        }
+        
+        ev.mTimeSamples[0] = eventTime;
 
         return ev;
     }
@@ -218,17 +346,83 @@
         ev.mDeviceId = deviceId;
         ev.mEdgeFlags = edgeFlags;
         ev.mDownTime = downTime;
-        ev.mEventTime = eventTime;
         ev.mEventTimeNano = eventTime * 1000000;
         ev.mAction = action;
-        ev.mX = ev.mRawX = x;
-        ev.mY = ev.mRawY = y;
-        ev.mPressure = pressure;
-        ev.mSize = size;
         ev.mMetaState = metaState;
         ev.mXPrecision = xPrecision;
         ev.mYPrecision = yPrecision;
 
+        ev.mNumPointers = 1;
+        ev.mNumSamples = 1;
+        int[] state = ev.mStateSamples;
+        state[0] = 0;
+        float[] data = ev.mDataSamples;
+        data[SAMPLE_X] = ev.mRawX = x;
+        data[SAMPLE_Y] = ev.mRawY = y;
+        data[SAMPLE_PRESSURE] = pressure;
+        data[SAMPLE_SIZE] = size;
+        ev.mTimeSamples[0] = eventTime;
+
+        return ev;
+    }
+
+    /**
+     * Create a new MotionEvent, filling in all of the basic values that
+     * define the motion.
+     *
+     * @param downTime The time (in ms) when the user originally pressed down to start
+     * a stream of position events.  This must be obtained from {@link SystemClock#uptimeMillis()}.
+     * @param eventTime  The the time (in ms) when this specific event was generated.  This
+     * must be obtained from {@link SystemClock#uptimeMillis()}.
+     * @param action The kind of action being performed -- one of either
+     * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
+     * {@link #ACTION_CANCEL}.
+     * @param pointers The number of pointers that are active in this event.
+     * @param x The X coordinate of this event.
+     * @param y The Y coordinate of this event.
+     * @param pressure The current pressure of this event.  The pressure generally
+     * ranges from 0 (no pressure at all) to 1 (normal pressure), however
+     * values higher than 1 may be generated depending on the calibration of
+     * the input device.
+     * @param size A scaled value of the approximate size of the area being pressed when
+     * touched with the finger. The actual value in pixels corresponding to the finger
+     * touch is normalized with a device specific range of values
+     * and scaled to a value between 0 and 1.
+     * @param metaState The state of any meta / modifier keys that were in effect when
+     * the event was generated.
+     * @param xPrecision The precision of the X coordinate being reported.
+     * @param yPrecision The precision of the Y coordinate being reported.
+     * @param deviceId The id for the device that this event came from.  An id of
+     * zero indicates that the event didn't come from a physical device; other
+     * numbers are arbitrary and you shouldn't depend on the values.
+     * @param edgeFlags A bitfield indicating which edges, if any, where touched by this
+     * MotionEvent.
+     */
+    static public MotionEvent obtain(long downTime, long eventTime, int action,
+            int pointers, float x, float y, float pressure, float size, int metaState,
+            float xPrecision, float yPrecision, int deviceId, int edgeFlags) {
+        MotionEvent ev = obtain();
+        ev.mDeviceId = deviceId;
+        ev.mEdgeFlags = edgeFlags;
+        ev.mDownTime = downTime;
+        ev.mEventTimeNano = eventTime * 1000000;
+        ev.mAction = action;
+        ev.mNumPointers = pointers;
+        ev.mMetaState = metaState;
+        ev.mXPrecision = xPrecision;
+        ev.mYPrecision = yPrecision;
+
+        ev.mNumPointers = 1;
+        ev.mNumSamples = 1;
+        int[] state = ev.mStateSamples;
+        state[0] = 0;
+        float[] data = ev.mDataSamples;
+        data[SAMPLE_X] = ev.mRawX = x;
+        data[SAMPLE_Y] = ev.mRawY = y;
+        data[SAMPLE_PRESSURE] = pressure;
+        data[SAMPLE_SIZE] = size;
+        ev.mTimeSamples[0] = eventTime;
+
         return ev;
     }
 
@@ -255,17 +449,24 @@
         ev.mDeviceId = 0;
         ev.mEdgeFlags = 0;
         ev.mDownTime = downTime;
-        ev.mEventTime = eventTime;
         ev.mEventTimeNano = eventTime * 1000000;
         ev.mAction = action;
-        ev.mX = ev.mRawX = x;
-        ev.mY = ev.mRawY = y;
-        ev.mPressure = 1.0f;
-        ev.mSize = 1.0f;
+        ev.mNumPointers = 1;
         ev.mMetaState = metaState;
         ev.mXPrecision = 1.0f;
         ev.mYPrecision = 1.0f;
 
+        ev.mNumPointers = 1;
+        ev.mNumSamples = 1;
+        int[] state = ev.mStateSamples;
+        state[0] = 0;
+        float[] data = ev.mDataSamples;
+        data[SAMPLE_X] = ev.mRawX = x;
+        data[SAMPLE_Y] = ev.mRawY = y;
+        data[SAMPLE_PRESSURE] = 1.0f;
+        data[SAMPLE_SIZE] = 1.0f;
+        ev.mTimeSamples[0] = eventTime;
+
         return ev;
     }
 
@@ -275,43 +476,17 @@
      * @hide
      */
     public void scale(float scale) {
-        mX *= scale;
-        mY *= scale;
         mRawX *= scale;
         mRawY *= scale;
-        mSize *= scale;
         mXPrecision *= scale;
         mYPrecision *= scale;
-        if (mHistory != null) {
-            float[] history = mHistory;
-            int length = history.length;
-            for (int i = 0; i < length; i += 4) {
-                history[i] *= scale;        // X
-                history[i + 1] *= scale;    // Y
-                // no need to scale pressure ([i+2])
-                history[i + 3] *= scale;    // Size, TODO: square this?
-            }
-        }
-    }
-
-    /**
-     * Translate the coordination of the event by given x and y.
-     *
-     * @hide
-     */
-    public void translate(float dx, float dy) {
-        mX += dx;
-        mY += dy;
-        mRawX += dx;
-        mRawY += dx;
-        if (mHistory != null) {
-            float[] history = mHistory;
-            int length = history.length;
-            for (int i = 0; i < length; i += 4) {
-                history[i] += dx;        // X
-                history[i + 1] += dy;    // Y
-                // no need to translate pressure (i+2) and size (i+3) 
-            }
+        float[] history = mDataSamples;
+        final int length = mNumPointers * mNumSamples * NUM_SAMPLE_DATA;
+        for (int i = 0; i < length; i += NUM_SAMPLE_DATA) {
+            history[i + SAMPLE_X] *= scale;
+            history[i + SAMPLE_Y] *= scale;
+            // no need to scale pressure
+            history[i + SAMPLE_SIZE] *= scale;    // TODO: square this?
         }
     }
 
@@ -323,25 +498,36 @@
         ev.mDeviceId = o.mDeviceId;
         ev.mEdgeFlags = o.mEdgeFlags;
         ev.mDownTime = o.mDownTime;
-        ev.mEventTime = o.mEventTime;
         ev.mEventTimeNano = o.mEventTimeNano;
         ev.mAction = o.mAction;
-        ev.mX = o.mX;
+        ev.mNumPointers = o.mNumPointers;
         ev.mRawX = o.mRawX;
-        ev.mY = o.mY;
         ev.mRawY = o.mRawY;
-        ev.mPressure = o.mPressure;
-        ev.mSize = o.mSize;
         ev.mMetaState = o.mMetaState;
         ev.mXPrecision = o.mXPrecision;
         ev.mYPrecision = o.mYPrecision;
-        final int N = o.mNumHistory;
-        ev.mNumHistory = N;
-        if (N > 0) {
-            // could be more efficient about this...
-            ev.mHistory = (float[])o.mHistory.clone();
-            ev.mHistoryTimes = (long[])o.mHistoryTimes.clone();
+        
+        final int NT = ev.mNumSamples = o.mNumSamples;
+        if (ev.mTimeSamples.length < NT) {
+            System.arraycopy(o.mTimeSamples, 0, ev.mTimeSamples, 0, NT);
+        } else {
+            ev.mTimeSamples = (long[])o.mTimeSamples.clone();
         }
+        
+        final int NS = (ev.mNumPointers=o.mNumPointers) * NT;
+        if (ev.mStateSamples.length < NS) {
+            System.arraycopy(o.mStateSamples, 0, ev.mStateSamples, 0, NS);
+        } else {
+            ev.mStateSamples = (int[])o.mStateSamples.clone();
+        }
+        
+        final int ND = NS * NUM_SAMPLE_DATA;
+        if (ev.mDataSamples.length < ND) {
+            System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0, ND);
+        } else {
+            ev.mDataSamples = (float[])o.mDataSamples.clone();
+        }
+        
         return ev;
     }
 
@@ -364,7 +550,7 @@
         synchronized (gRecyclerLock) {
             if (gRecyclerUsed < MAX_RECYCLED) {
                 gRecyclerUsed++;
-                mNumHistory = 0;
+                mNumSamples = 0;
                 mNext = gRecyclerTop;
                 gRecyclerTop = this;
             }
@@ -392,7 +578,7 @@
      * Returns the time (in ms) when this specific event was generated.
      */
     public final long getEventTime() {
-        return mEventTime;
+        return mTimeSamples[0];
     }
 
     /**
@@ -406,40 +592,88 @@
     }
 
     /**
-     * Returns the X coordinate of this event.  Whole numbers are pixels; the 
-     * value may have a fraction for input devices that are sub-pixel precise. 
+     * The number of pointers of data contained in this event.  Always
+     * >= 1.
+     */
+    public final int getPointerCount() {
+        return mNumPointers;
+    }
+    
+    /**
+     * {@link #getX(int)} for the first pointer (pointer 0).
      */
     public final float getX() {
-        return mX;
+        return mDataSamples[SAMPLE_X];
     }
 
     /**
-     * Returns the Y coordinate of this event.  Whole numbers are pixels; the
-     * value may have a fraction for input devices that are sub-pixel precise.
+     * {@link #getY(int)} for the first pointer (pointer 0).
      */
     public final float getY() {
-        return mY;
+        return mDataSamples[SAMPLE_Y];
     }
 
     /**
-     * Returns the current pressure of this event.  The pressure generally
+     * {@link #getPressure(int)} for the first pointer (pointer 0).
+     */
+    public final float getPressure() {
+        return mDataSamples[SAMPLE_PRESSURE];
+    }
+
+    /**
+     * {@link #getSize(int)} for the first pointer (pointer 0).
+     */
+    public final float getSize() {
+        return mDataSamples[SAMPLE_SIZE];
+    }
+
+    /**
+     * Returns the X coordinate of this event for the given pointer.
+     * Whole numbers are pixels; the 
+     * value may have a fraction for input devices that are sub-pixel precise. 
+     * @param pointer The desired pointer to retrieve.  Value may be from 0
+     * (the first pointer) to {@link #getPointerCount()}-1.
+     */
+    public final float getX(int pointer) {
+        return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_X];
+    }
+
+    /**
+     * Returns the Y coordinate of this event for the given pointer.
+     * Whole numbers are pixels; the
+     * value may have a fraction for input devices that are sub-pixel precise.
+     * @param pointer The desired pointer to retrieve.  Value may be from 0
+     * (the first pointer) to {@link #getPointerCount()}-1.
+     */
+    public final float getY(int pointer) {
+        return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_Y];
+    }
+
+    /**
+     * Returns the current pressure of this event for the given pointer.
+     * The pressure generally
      * ranges from 0 (no pressure at all) to 1 (normal pressure), however
      * values higher than 1 may be generated depending on the calibration of
      * the input device.
+     * @param pointer The desired pointer to retrieve.  Value may be from 0
+     * (the first pointer) to {@link #getPointerCount()}-1.
      */
-    public final float getPressure() {
-        return mPressure;
+    public final float getPressure(int pointer) {
+        return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
     }
 
     /**
-     * Returns a scaled value of the approximate size, of the area being pressed when
-     * touched with the finger. The actual value in pixels corresponding to the finger
-     * touch  is normalized with the device specific range of values
+     * Returns a scaled value of the approximate size for the given pointer,
+     * representing the area of the screen being pressed.
+     * The actual value in pixels corresponding to the
+     * touch is normalized with the device specific range of values
      * and scaled to a value between 0 and 1. The value of size can be used to
      * determine fat touch events.
+     * @param pointer The desired pointer to retrieve.  Value may be from 0
+     * (the first pointer) to {@link #getPointerCount()}-1.
      */
-    public final float getSize() {
-        return mSize;
+    public final float getSize(int pointer) {
+        return mDataSamples[(pointer*NUM_SAMPLE_DATA) + SAMPLE_SIZE];
     }
 
     /**
@@ -505,7 +739,7 @@
      * @return Returns the number of historical points in the event.
      */
     public final int getHistorySize() {
-        return mNumHistory;
+        return mNumSamples - 1;
     }
 
     /**
@@ -519,63 +753,103 @@
      * @see #getEventTime
      */
     public final long getHistoricalEventTime(int pos) {
-        return mHistoryTimes[pos];
+        return mTimeSamples[pos + 1];
+    }
+
+    /**
+     * {@link #getHistoricalX(int)} for the first pointer (pointer 0).
+     */
+    public final float getHistoricalX(int pos) {
+        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_X];
+    }
+
+    /**
+     * {@link #getHistoricalY(int)} for the first pointer (pointer 0).
+     */
+    public final float getHistoricalY(int pos) {
+        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_Y];
+    }
+
+    /**
+     * {@link #getHistoricalPressure(int)} for the first pointer (pointer 0).
+     */
+    public final float getHistoricalPressure(int pos) {
+        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_PRESSURE];
+    }
+
+    /**
+     * {@link #getHistoricalSize(int)} for the first pointer (pointer 0).
+     */
+    public final float getHistoricalSize(int pos) {
+        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers) + SAMPLE_SIZE];
     }
 
     /**
      * Returns a historical X coordinate that occurred between this event
-     * and the previous event.  Only applies to ACTION_MOVE events.
+     * and the previous event for the given pointer.  Only applies to ACTION_MOVE events.
      *
+     * @param pointer The desired pointer to retrieve.  Value may be from 0
+     * (the first pointer) to {@link #getPointerCount()}-1.
      * @param pos Which historical value to return; must be less than
      * {@link #getHistorySize}
      *
      * @see #getHistorySize
      * @see #getX
      */
-    public final float getHistoricalX(int pos) {
-        return mHistory[pos*4];
+    public final float getHistoricalX(int pointer, int pos) {
+        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
+                            + (pointer * NUM_SAMPLE_DATA) + SAMPLE_X];
     }
 
     /**
      * Returns a historical Y coordinate that occurred between this event
-     * and the previous event.  Only applies to ACTION_MOVE events.
+     * and the previous event for the given pointer.  Only applies to ACTION_MOVE events.
      *
+     * @param pointer The desired pointer to retrieve.  Value may be from 0
+     * (the first pointer) to {@link #getPointerCount()}-1.
      * @param pos Which historical value to return; must be less than
      * {@link #getHistorySize}
      *
      * @see #getHistorySize
      * @see #getY
      */
-    public final float getHistoricalY(int pos) {
-        return mHistory[pos*4 + 1];
+    public final float getHistoricalY(int pointer, int pos) {
+        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
+                            + (pointer * NUM_SAMPLE_DATA) + SAMPLE_Y];
     }
 
     /**
      * Returns a historical pressure coordinate that occurred between this event
-     * and the previous event.  Only applies to ACTION_MOVE events.
+     * and the previous event for the given pointer.  Only applies to ACTION_MOVE events.
      *
      * @param pos Which historical value to return; must be less than
      * {@link #getHistorySize}
      *
+     * @param pointer The desired pointer to retrieve.  Value may be from 0
+     * (the first pointer) to {@link #getPointerCount()}-1.
      * @see #getHistorySize
      * @see #getPressure
      */
-    public final float getHistoricalPressure(int pos) {
-        return mHistory[pos*4 + 2];
+    public final float getHistoricalPressure(int pointer, int pos) {
+        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
+                            + (pointer * NUM_SAMPLE_DATA) + SAMPLE_PRESSURE];
     }
 
     /**
      * Returns a historical size coordinate that occurred between this event
-     * and the previous event.  Only applies to ACTION_MOVE events.
+     * and the previous event for the given pointer.  Only applies to ACTION_MOVE events.
      *
      * @param pos Which historical value to return; must be less than
      * {@link #getHistorySize}
      *
+     * @param pointer The desired pointer to retrieve.  Value may be from 0
+     * (the first pointer) to {@link #getPointerCount()}-1.
      * @see #getHistorySize
      * @see #getSize
      */
-    public final float getHistoricalSize(int pos) {
-        return mHistory[pos*4 + 3];
+    public final float getHistoricalSize(int pointer, int pos) {
+        return mDataSamples[((pos + 1) * NUM_SAMPLE_DATA * mNumPointers)
+                            + (pointer * NUM_SAMPLE_DATA) + SAMPLE_SIZE];
     }
 
     /**
@@ -625,16 +899,11 @@
      * @param deltaY Amount to add to the current Y coordinate of the event.
      */
     public final void offsetLocation(float deltaX, float deltaY) {
-        mX += deltaX;
-        mY += deltaY;
-        final int N = mNumHistory*4;
-        if (N <= 0) {
-            return;
-        }
-        final float[] pos = mHistory;
-        for (int i=0; i<N; i+=4) {
-            pos[i] += deltaX;
-            pos[i+1] += deltaY;
+        final int N = mNumPointers*mNumSamples*4;
+        final float[] pos = mDataSamples;
+        for (int i=0; i<N; i+=NUM_SAMPLE_DATA) {
+            pos[i+SAMPLE_X] += deltaX;
+            pos[i+SAMPLE_Y] += deltaY;
         }
     }
 
@@ -646,8 +915,8 @@
      * @param y New absolute Y location.
      */
     public final void setLocation(float x, float y) {
-        float deltaX = x-mX;
-        float deltaY = y-mY;
+        float deltaX = x-mDataSamples[SAMPLE_X];
+        float deltaY = y-mDataSamples[SAMPLE_Y];
         if (deltaX != 0 || deltaY != 0) {
             offsetLocation(deltaX, deltaY);
         }
@@ -659,58 +928,118 @@
      * the future, the current values in the event will be added to a list of
      * historic values.
      *
+     * @param eventTime The time stamp for this data.
      * @param x The new X position.
      * @param y The new Y position.
      * @param pressure The new pressure.
      * @param size The new size.
+     * @param metaState Meta key state.
      */
     public final void addBatch(long eventTime, float x, float y,
             float pressure, float size, int metaState) {
-        float[] history = mHistory;
-        long[] historyTimes = mHistoryTimes;
-        int N;
-        int avail;
-        if (history == null) {
-            mHistory = history = new float[8*4];
-            mHistoryTimes = historyTimes = new long[8];
-            mNumHistory = N = 0;
-            avail = 8;
-        } else {
-            N = mNumHistory;
-            avail = history.length/4;
-            if (N == avail) {
-                avail += 8;
-                float[] newHistory = new float[avail*4];
-                System.arraycopy(history, 0, newHistory, 0, N*4);
-                mHistory = history = newHistory;
-                long[] newHistoryTimes = new long[avail];
-                System.arraycopy(historyTimes, 0, newHistoryTimes, 0, N);
-                mHistoryTimes = historyTimes = newHistoryTimes;
-            }
+        int[] states = mStateSamples;
+        float[] data = mDataSamples;
+        long[] times = mTimeSamples;
+        
+        final int NP = mNumPointers;
+        final int NS = mNumSamples;
+        final int NI = NP*NS;
+        final int ND = NI * NUM_SAMPLE_DATA;
+        if (states.length < (NI+NP)) {
+            // The state and data arrays are sized together, since their
+            // size is always a fixed factor from each other.
+            final int NEW_NI = NP * (NS+BASE_AVAIL_SAMPLES);
+            int[] newState = new int[NEW_NI];
+            System.arraycopy(states, 0, newState, 0, NI);
+            mStateSamples = states = newState;
+            final int NEW_ND = NEW_NI * NUM_SAMPLE_DATA;
+            float[] newData = new float[NEW_ND];
+            System.arraycopy(data, 0, newData, 0, ND);
+            mDataSamples = data = newData;
         }
+        if (times.length <= NS) {
+            final int NEW_NS = NS + BASE_AVAIL_SAMPLES;
+            long[] newHistoryTimes = new long[NEW_NS];
+            System.arraycopy(times, 0, newHistoryTimes, 0, NS);
+            mTimeSamples = times = newHistoryTimes;
+        }
+        
+        times[NS] = times[0];
+        times[0] = eventTime;
+        
+        final int pos = NS*NUM_SAMPLE_DATA;
+        data[pos+SAMPLE_X] = data[SAMPLE_X];
+        data[pos+SAMPLE_Y] = data[SAMPLE_Y];
+        data[pos+SAMPLE_PRESSURE] = data[SAMPLE_PRESSURE];
+        data[pos+SAMPLE_SIZE] = data[SAMPLE_SIZE];
+        data[SAMPLE_X] = x;
+        data[SAMPLE_Y] = y;
+        data[SAMPLE_PRESSURE] = pressure;
+        data[SAMPLE_SIZE] = size;
+        mNumSamples = NS+1;
 
-        historyTimes[N] = mEventTime;
+        mRawX = x;
+        mRawY = y;
+        mMetaState |= metaState;
+    }
 
-        final int pos = N*4;
-        history[pos] = mX;
-        history[pos+1] = mY;
-        history[pos+2] = mPressure;
-        history[pos+3] = mSize;
-        mNumHistory = N+1;
+    /**
+     * Add a new movement to the batch of movements in this event.  The
+     * input data must contain (NUM_SAMPLE_DATA * {@link #getPointerCount()})
+     * samples of data.
+     *
+     * @param eventTime The time stamp for this data.
+     * @param inData The actual data.
+     * @param metaState Meta key state.
+     * 
+     * @hide
+     */
+    public final void addBatch(long eventTime, float[] inData, int metaState) {
+        int[] states = mStateSamples;
+        float[] data = mDataSamples;
+        long[] times = mTimeSamples;
+        
+        final int NP = mNumPointers;
+        final int NS = mNumSamples;
+        final int NI = NP*NS;
+        final int ND = NI * NUM_SAMPLE_DATA;
+        if (states.length < (NI+NP)) {
+            // The state and data arrays are sized together, since their
+            // size is always a fixed factor from each other.
+            final int NEW_NI = NP * (NS+BASE_AVAIL_SAMPLES);
+            int[] newState = new int[NEW_NI];
+            System.arraycopy(states, 0, newState, 0, NI);
+            mStateSamples = states = newState;
+            final int NEW_ND = NEW_NI * NUM_SAMPLE_DATA;
+            float[] newData = new float[NEW_ND];
+            System.arraycopy(data, 0, newData, 0, ND);
+            mDataSamples = data = newData;
+        }
+        if (times.length <= NS) {
+            final int NEW_NS = NS + BASE_AVAIL_SAMPLES;
+            long[] newHistoryTimes = new long[NEW_NS];
+            System.arraycopy(times, 0, newHistoryTimes, 0, NS);
+            mTimeSamples = times = newHistoryTimes;
+        }
+        
+        times[NS] = times[0];
+        times[0] = eventTime;
+        
+        System.arraycopy(data, 0, data, ND, mNumPointers*NUM_SAMPLE_DATA);
+        System.arraycopy(inData, 0, data, 0, mNumPointers*NUM_SAMPLE_DATA);
+        
+        mNumSamples = NS+1;
 
-        mEventTime = eventTime;
-        mX = mRawX = x;
-        mY = mRawY = y;
-        mPressure = pressure;
-        mSize = size;
+        mRawX = inData[SAMPLE_X];
+        mRawY = inData[SAMPLE_Y];
         mMetaState |= metaState;
     }
 
     @Override
     public String toString() {
         return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this))
-            + " action=" + mAction + " x=" + mX
-            + " y=" + mY + " pressure=" + mPressure + " size=" + mSize + "}";
+            + " action=" + mAction + " x=" + getX()
+            + " y=" + getY() + " pressure=" + getPressure() + " size=" + getSize() + "}";
     }
 
     public static final Parcelable.Creator<MotionEvent> CREATOR
@@ -732,27 +1061,29 @@
 
     public void writeToParcel(Parcel out, int flags) {
         out.writeLong(mDownTime);
-        out.writeLong(mEventTime);
         out.writeLong(mEventTimeNano);
         out.writeInt(mAction);
-        out.writeFloat(mX);
-        out.writeFloat(mY);
-        out.writeFloat(mPressure);
-        out.writeFloat(mSize);
         out.writeInt(mMetaState);
         out.writeFloat(mRawX);
         out.writeFloat(mRawY);
-        final int N = mNumHistory;
-        out.writeInt(N);
-        if (N > 0) {
-            final int N4 = N*4;
+        final int NP = mNumPointers;
+        out.writeInt(NP);
+        final int NS = mNumSamples;
+        out.writeInt(NS);
+        final int NI = NP*NS;
+        if (NI > 0) {
             int i;
-            float[] history = mHistory;
-            for (i=0; i<N4; i++) {
+            int[] state = mStateSamples;
+            for (i=0; i<NI; i++) {
+                out.writeInt(state[i]);
+            }
+            final int NI4 = NI*NUM_SAMPLE_DATA;
+            float[] history = mDataSamples;
+            for (i=0; i<NI4; i++) {
                 out.writeFloat(history[i]);
             }
-            long[] times = mHistoryTimes;
-            for (i=0; i<N; i++) {
+            long[] times = mTimeSamples;
+            for (i=0; i<NS; i++) {
                 out.writeLong(times[i]);
             }
         }
@@ -764,31 +1095,37 @@
 
     private void readFromParcel(Parcel in) {
         mDownTime = in.readLong();
-        mEventTime = in.readLong();
         mEventTimeNano = in.readLong();
         mAction = in.readInt();
-        mX = in.readFloat();
-        mY = in.readFloat();
-        mPressure = in.readFloat();
-        mSize = in.readFloat();
         mMetaState = in.readInt();
         mRawX = in.readFloat();
         mRawY = in.readFloat();
-        final int N = in.readInt();
-        if ((mNumHistory=N) > 0) {
-            final int N4 = N*4;
-            float[] history = mHistory;
-            if (history == null || history.length < N4) {
-                mHistory = history = new float[N4 + (4*4)];
+        final int NP = in.readInt();
+        mNumPointers = NP;
+        final int NS = in.readInt();
+        mNumSamples = NS;
+        final int NI = NP*NS;
+        if (NI > 0) {
+            final int NI4 = NI*4;
+            int[] state = mStateSamples;
+            if (state.length < NI) {
+                mStateSamples = state = new int[NI];
             }
-            for (int i=0; i<N4; i++) {
+            for (int i=0; i<NI; i++) {
+                state[i] = in.readInt();
+            }
+            float[] history = mDataSamples;
+            if (history.length < NI4) {
+                mDataSamples = history = new float[NI4];
+            }
+            for (int i=0; i<NI4; i++) {
                 history[i] = in.readFloat();
             }
-            long[] times = mHistoryTimes;
-            if (times == null || times.length < N) {
-                mHistoryTimes = times = new long[N + 4];
+            long[] times = mTimeSamples;
+            if (times == null || times.length < NS) {
+                mTimeSamples = times = new long[NS];
             }
-            for (int i=0; i<N; i++) {
+            for (int i=0; i<NS; i++) {
                 times[i] = in.readLong();
             }
         }
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index a87c622..e6bbf9f5 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -19,6 +19,7 @@
 import android.graphics.*;
 import android.os.Parcelable;
 import android.os.Parcel;
+import android.util.DisplayMetrics;
 import android.util.Log;
 
 /**
@@ -133,6 +134,10 @@
     @SuppressWarnings("unused")
     private Canvas mCanvas;
 
+    // The display metrics used to provide the pseudo canvas size for applications
+    // running in compatibility mode. This is set to null for regular mode.
+    private DisplayMetrics mDisplayMetrics;
+
     /**
      * Exception thrown when a surface couldn't be created or resized
      */
@@ -169,7 +174,23 @@
      * {@hide}
      */
     public Surface() {
-        mCanvas = new Canvas();
+        mCanvas = new Canvas() {
+            @Override
+            public int getWidth() {
+                return mDisplayMetrics == null ? super.getWidth() : mDisplayMetrics.widthPixels;
+            }
+            @Override
+            public int getHeight() {
+                return mDisplayMetrics == null ? super.getHeight() : mDisplayMetrics.heightPixels;
+            }
+        };
+    }
+
+    /**
+     * Sets the display metrics used to provide canva's width/height in comaptibility mode.
+     */
+    void setCompatibleDisplayMetrics(DisplayMetrics metrics) {
+        mDisplayMetrics = metrics;
     }
     
     /**
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 25bbb6a..a854535 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.content.res.CompatibilityInfo.Translator;
 import android.graphics.Canvas;
 import android.graphics.PixelFormat;
@@ -140,7 +141,14 @@
     int mType = -1;
     final Rect mSurfaceFrame = new Rect();
     private Translator mTranslator;
-
+    
+    // A flag to indicate that the Canvas has to be scaled
+    private boolean mScaleCanvas = false;
+    // A flag to indicate that the Canvas is in use and being scaled.
+    // This may remain to be false even if mScaleCanvas is true if the applicatio
+    // does not use the canvas (such as GLSurfaceView, VideoView).
+    private boolean mCanvasScaled = false;
+    
     public SurfaceView(Context context) {
         super(context);
         setWillNotDraw(true);
@@ -254,18 +262,21 @@
 
     @Override
     public boolean dispatchTouchEvent(MotionEvent event) {
-        // SurfaceView uses pre-scaled size unless fixed size is requested. This hook
-        // scales the event back to the pre-scaled coordinates for such surface.
-        if (mScaled) {
+        if (mTranslator == null || mCanvasScaled) {
+            // Use the event as is if no scaling is required, or the surface's canvas
+            // is scaled too.
+            return super.dispatchTouchEvent(event);
+        } else {
+            // The surface is in native size, so we need to scale the event
+            // back to native location.
             MotionEvent scaledBack = MotionEvent.obtain(event);
-            mTranslator.translateEventInScreenToAppWindow(event);
+            // scale back to original
+            scaledBack.scale(mTranslator.applicationScale);
             try {
                 return super.dispatchTouchEvent(scaledBack);
             } finally {
                 scaledBack.recycle();
             }
-        } else {
-            return super.dispatchTouchEvent(event);
         }
     }
 
@@ -291,8 +302,6 @@
         mWindowType = type;
     }
 
-    boolean mScaled = false;
-    
     private void updateWindow(boolean force) {
         if (!mHaveFrame) {
             return;
@@ -301,20 +310,26 @@
         mTranslator = viewRoot.mTranslator;
 
         float appScale = mTranslator == null ? 1.0f : mTranslator.applicationScale;
+
+        Resources res = getContext().getResources();
+        if (mTranslator != null || !res.getCompatibilityInfo().supportsScreen()) {
+            mSurface.setCompatibleDisplayMetrics(res.getDisplayMetrics());
+        }
         
         int myWidth = mRequestedWidth;
         if (myWidth <= 0) myWidth = getWidth();
         int myHeight = mRequestedHeight;
         if (myHeight <= 0) myHeight = getHeight();
 
-        // Use original size if the app specified the size of the view,
-        // and let the flinger to scale up.
+        // Use requested size if the app specified the size of the view
+        // and let the flinger to scale up. Otherwise, use the native size
+        // (* appScale) and assume the application can handle it.
         if (mRequestedWidth <= 0 && mTranslator != null) {
-            myWidth *= appScale;
-            myHeight *= appScale;
-            mScaled = true;
+            myWidth = (int) (myWidth * appScale + 0.5f);
+            myHeight = (int) (myHeight * appScale + 0.5f);
+            mScaleCanvas = true;
         } else {
-            mScaled = false;
+            mScaleCanvas = false;
         }
 
         getLocationInWindow(mLocation);
@@ -636,7 +651,9 @@
             if (localLOGV) Log.i(TAG, "Returned canvas: " + c);
             if (c != null) {
                 mLastLockTime = SystemClock.uptimeMillis();
-                if (mScaled) {
+                if (mScaleCanvas) {
+                    // When the canvas is scaled, don't scale back the event's location.
+                    mCanvasScaled = true;
                     mSaveCount = c.save();
                     mTranslator.translateCanvas(c);
                 }
@@ -662,7 +679,7 @@
         }
 
         public void unlockCanvasAndPost(Canvas canvas) {
-            if (mScaled) {
+            if (mCanvasScaled) {
                 canvas.restoreToCount(mSaveCount);
             }
             mSurface.unlockCanvasAndPost(canvas);
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 2acf790..242690b 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -42,6 +42,7 @@
 import android.widget.Scroller;
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
+import android.content.res.Resources;
 import android.content.Context;
 import android.app.ActivityManagerNative;
 import android.Manifest;
@@ -393,10 +394,14 @@
                 mView = view;
                 mWindowAttributes.copyFrom(attrs);
                 attrs = mWindowAttributes;
-
-                CompatibilityInfo compatibilityInfo =
-                        mView.getContext().getResources().getCompatibilityInfo();
+                Resources resources = mView.getContext().getResources();
+                CompatibilityInfo compatibilityInfo = resources.getCompatibilityInfo();
                 mTranslator = compatibilityInfo.getTranslator(attrs);
+
+                if (mTranslator != null || !compatibilityInfo.supportsScreen()) {
+                    mSurface.setCompatibleDisplayMetrics(resources.getDisplayMetrics());
+                }
+
                 boolean restore = false;
                 if (attrs != null && mTranslator != null) {
                     restore = true;
@@ -914,7 +919,8 @@
             mHeight = frame.height();
 
             if (initialized) {
-                mGlCanvas.setViewport((int) (mWidth * appScale), (int) (mHeight * appScale));
+                mGlCanvas.setViewport((int) (mWidth * appScale + 0.5f),
+                        (int) (mHeight * appScale + 0.5f));
             }
 
             boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
@@ -1244,7 +1250,7 @@
 
         if (fullRedrawNeeded) {
             mAttachInfo.mIgnoreDirtyState = true;
-            dirty.union(0, 0, (int) (mWidth * appScale), (int) (mHeight * appScale));
+            dirty.union(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
         }
 
         if (DEBUG_ORIENTATION || DEBUG_DRAW) {
@@ -1774,7 +1780,8 @@
                             if (mGlCanvas != null) {
                                 float appScale = mAttachInfo.mApplicationScale;
                                 mGlCanvas.setViewport(
-                                        (int) (mWidth * appScale), (int) (mHeight * appScale));
+                                        (int) (mWidth * appScale + 0.5f),
+                                        (int) (mHeight * appScale + 0.5f));
                             }
                         }
                     }
@@ -2419,8 +2426,8 @@
         }
         int relayoutResult = sWindowSession.relayout(
                 mWindow, params,
-                (int) (mView.mMeasuredWidth * appScale),
-                (int) (mView.mMeasuredHeight * appScale),
+                (int) (mView.mMeasuredWidth * appScale + 0.5f),
+                (int) (mView.mMeasuredHeight * appScale + 0.5f),
                 viewVisibility, insetsPending, mWinFrame,
                 mPendingContentInsets, mPendingVisibleInsets, mSurface);
         if (restore) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 6a26a31..c0be9e8 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -991,13 +991,13 @@
          * @hide
          */
         public void scale(float scale) {
-            x *= scale;
-            y *= scale;
+            x = (int) (x * scale + 0.5f);
+            y = (int) (y * scale + 0.5f);
             if (width > 0) {
-                width *= scale;
+                width = (int) (width * scale + 0.5f);
             }
             if (height > 0) {
-                height *= scale;
+                height = (int) (height * scale + 0.5f);
             }
         }
 
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index c0b6dab..4fe4036 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -1370,7 +1370,8 @@
      */
     private boolean ignoreCallbacks() {
         return (mCancelled || mAuthHeader != null ||
-                (mStatusCode > 300 && mStatusCode < 400));
+                // Allow 305 (Use Proxy) to call through.
+                (mStatusCode > 300 && mStatusCode < 400 && mStatusCode != 305));
     }
 
     /**
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index 648ec27..b2aa524 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -22,7 +22,7 @@
 /**
  * Two-way map that maps MIME-types to file extensions and vice versa.
  */
-public /* package */ class MimeTypeMap {
+public class MimeTypeMap {
 
     /**
      * Singleton MIME-type map instance:
@@ -39,7 +39,6 @@
      */
     private HashMap<String, String> mExtensionToMimeTypeMap;
 
-
     /**
      * Creates a new MIME-type map.
      */
@@ -50,7 +49,10 @@
 
     /**
      * Returns the file extension or an empty string iff there is no
-     * extension.
+     * extension. This method is a convenience method for obtaining the
+     * extension of a url and has undefined results for other Strings.
+     * @param url
+     * @return The file extension of the given url.
      */
     public static String getFileExtensionFromUrl(String url) {
         if (url != null && url.length() > 0) {
@@ -80,8 +82,7 @@
      * Load an entry into the map. This does not check if the item already
      * exists, it trusts the caller!
      */
-    private void loadEntry(String mimeType, String extension, 
-            boolean textType) {
+    private void loadEntry(String mimeType, String extension) {
         //
         // if we have an existing x --> y mapping, we do not want to
         // override it with another mapping x --> ?
@@ -94,18 +95,12 @@
             mMimeTypeToExtensionMap.put(mimeType, extension);
         }
 
-        //
-        // here, we don't want to map extensions to text MIME types;
-        // otherwise, we will start replacing generic text/plain and
-        // text/html with text MIME types that our platform does not
-        // understand.
-        //
-        if (!textType) {
-            mExtensionToMimeTypeMap.put(extension, mimeType);
-        }
+        mExtensionToMimeTypeMap.put(extension, mimeType);
     }
 
     /**
+     * Return true if the given MIME type has an entry in the map.
+     * @param mimeType A MIME type (i.e. text/plain)
      * @return True iff there is a mimeType entry in the map.
      */
     public boolean hasMimeType(String mimeType) {
@@ -117,7 +112,9 @@
     }
 
     /**
-     * @return The extension for the MIME type or null iff there is none.
+     * Return the MIME type for the given extension.
+     * @param extension A file extension without the leading '.'
+     * @return The MIME type for the given extension or null iff there is none.
      */
     public String getMimeTypeFromExtension(String extension) {
         if (extension != null && extension.length() > 0) {
@@ -128,18 +125,23 @@
     }
 
     /**
+     * Return true if the given extension has a registered MIME type.
+     * @param extension A file extension without the leading '.'
      * @return True iff there is an extension entry in the map.
      */
     public boolean hasExtension(String extension) {
         if (extension != null && extension.length() > 0) {
             return mExtensionToMimeTypeMap.containsKey(extension);
         }
-
         return false;
     }
 
     /**
-     * @return The MIME type for the extension or null iff there is none.
+     * Return the registered extension for the given MIME type. Note that some
+     * MIME types map to multiple extensions. This call will return the most
+     * common extension for the given MIME type.
+     * @param mimeType A MIME type (i.e. text/plain)
+     * @return The extension for the given MIME type or null iff there is none.
      */
     public String getExtensionFromMimeType(String mimeType) {
         if (mimeType != null && mimeType.length() > 0) {
@@ -150,6 +152,7 @@
     }
 
     /**
+     * Get the singleton instance of MimeTypeMap.
      * @return The singleton instance of the MIME-type map.
      */
     public static MimeTypeMap getSingleton() {
@@ -164,341 +167,311 @@
             // mail.google.com/a/google.com
             //
             // and "active" MIME types (due to potential security issues).
-            //
-            // Also, notice that not all data from this table is actually
-            // added (see loadEntry method for more details).
 
-            sMimeTypeMap.loadEntry("application/andrew-inset", "ez", false);
-            sMimeTypeMap.loadEntry("application/dsptype", "tsp", false);
-            sMimeTypeMap.loadEntry("application/futuresplash", "spl", false);
-            sMimeTypeMap.loadEntry("application/hta", "hta", false);
-            sMimeTypeMap.loadEntry("application/mac-binhex40", "hqx", false);
-            sMimeTypeMap.loadEntry("application/mac-compactpro", "cpt", false);
-            sMimeTypeMap.loadEntry("application/mathematica", "nb", false);
-            sMimeTypeMap.loadEntry("application/msaccess", "mdb", false);
-            sMimeTypeMap.loadEntry("application/oda", "oda", false);
-            sMimeTypeMap.loadEntry("application/ogg", "ogg", false);
-            sMimeTypeMap.loadEntry("application/pdf", "pdf", false);
-            sMimeTypeMap.loadEntry("application/pgp-keys", "key", false);
-            sMimeTypeMap.loadEntry("application/pgp-signature", "pgp", false);
-            sMimeTypeMap.loadEntry("application/pics-rules", "prf", false);
-            sMimeTypeMap.loadEntry("application/rar", "rar", false);
-            sMimeTypeMap.loadEntry("application/rdf+xml", "rdf", false);
-            sMimeTypeMap.loadEntry("application/rss+xml", "rss", false);
-            sMimeTypeMap.loadEntry("application/zip", "zip", false);
+            sMimeTypeMap.loadEntry("application/andrew-inset", "ez");
+            sMimeTypeMap.loadEntry("application/dsptype", "tsp");
+            sMimeTypeMap.loadEntry("application/futuresplash", "spl");
+            sMimeTypeMap.loadEntry("application/hta", "hta");
+            sMimeTypeMap.loadEntry("application/mac-binhex40", "hqx");
+            sMimeTypeMap.loadEntry("application/mac-compactpro", "cpt");
+            sMimeTypeMap.loadEntry("application/mathematica", "nb");
+            sMimeTypeMap.loadEntry("application/msaccess", "mdb");
+            sMimeTypeMap.loadEntry("application/oda", "oda");
+            sMimeTypeMap.loadEntry("application/ogg", "ogg");
+            sMimeTypeMap.loadEntry("application/pdf", "pdf");
+            sMimeTypeMap.loadEntry("application/pgp-keys", "key");
+            sMimeTypeMap.loadEntry("application/pgp-signature", "pgp");
+            sMimeTypeMap.loadEntry("application/pics-rules", "prf");
+            sMimeTypeMap.loadEntry("application/rar", "rar");
+            sMimeTypeMap.loadEntry("application/rdf+xml", "rdf");
+            sMimeTypeMap.loadEntry("application/rss+xml", "rss");
+            sMimeTypeMap.loadEntry("application/zip", "zip");
             sMimeTypeMap.loadEntry("application/vnd.android.package-archive", 
-                    "apk", false);
-            sMimeTypeMap.loadEntry("application/vnd.cinderella", "cdy", false);
-            sMimeTypeMap.loadEntry("application/vnd.ms-pki.stl", "stl", false);
+                    "apk");
+            sMimeTypeMap.loadEntry("application/vnd.cinderella", "cdy");
+            sMimeTypeMap.loadEntry("application/vnd.ms-pki.stl", "stl");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.oasis.opendocument.database", "odb", 
-                    false);
+                    "application/vnd.oasis.opendocument.database", "odb");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.oasis.opendocument.formula", "odf", 
-                    false);
+                    "application/vnd.oasis.opendocument.formula", "odf");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.oasis.opendocument.graphics", "odg", 
-                    false);
+                    "application/vnd.oasis.opendocument.graphics", "odg");
             sMimeTypeMap.loadEntry(
                     "application/vnd.oasis.opendocument.graphics-template",
-                    "otg", false);
+                    "otg");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.oasis.opendocument.image", "odi", false);
+                    "application/vnd.oasis.opendocument.image", "odi");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.oasis.opendocument.spreadsheet", "ods", 
-                    false);
+                    "application/vnd.oasis.opendocument.spreadsheet", "ods");
             sMimeTypeMap.loadEntry(
                     "application/vnd.oasis.opendocument.spreadsheet-template",
-                    "ots", false);
+                    "ots");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.oasis.opendocument.text", "odt", false);
+                    "application/vnd.oasis.opendocument.text", "odt");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.oasis.opendocument.text-master", "odm", 
-                    false);
+                    "application/vnd.oasis.opendocument.text-master", "odm");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.oasis.opendocument.text-template", "ott", 
-                    false);
+                    "application/vnd.oasis.opendocument.text-template", "ott");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.oasis.opendocument.text-web", "oth", 
-                    false);
-            sMimeTypeMap.loadEntry("application/vnd.rim.cod", "cod", false);
-            sMimeTypeMap.loadEntry("application/vnd.smaf", "mmf", false);
-            sMimeTypeMap.loadEntry("application/vnd.stardivision.calc", "sdc", 
-                    false);
-            sMimeTypeMap.loadEntry("application/vnd.stardivision.draw", "sda", 
-                    false);
+                    "application/vnd.oasis.opendocument.text-web", "oth");
+            sMimeTypeMap.loadEntry("application/vnd.rim.cod", "cod");
+            sMimeTypeMap.loadEntry("application/vnd.smaf", "mmf");
+            sMimeTypeMap.loadEntry("application/vnd.stardivision.calc", "sdc");
+            sMimeTypeMap.loadEntry("application/vnd.stardivision.draw", "sda");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.stardivision.impress", "sdd", false);
+                    "application/vnd.stardivision.impress", "sdd");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.stardivision.impress", "sdp", false);
-            sMimeTypeMap.loadEntry("application/vnd.stardivision.math", "smf", 
-                    false);
-            sMimeTypeMap.loadEntry("application/vnd.stardivision.writer", "sdw", 
-                    false);
-            sMimeTypeMap.loadEntry("application/vnd.stardivision.writer", "vor", 
-                    false);
+                    "application/vnd.stardivision.impress", "sdp");
+            sMimeTypeMap.loadEntry("application/vnd.stardivision.math", "smf");
+            sMimeTypeMap.loadEntry("application/vnd.stardivision.writer",
+                    "sdw");
+            sMimeTypeMap.loadEntry("application/vnd.stardivision.writer",
+                    "vor");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.stardivision.writer-global", "sgl", false);
-            sMimeTypeMap.loadEntry("application/vnd.sun.xml.calc", "sxc", 
-                    false);
+                    "application/vnd.stardivision.writer-global", "sgl");
+            sMimeTypeMap.loadEntry("application/vnd.sun.xml.calc", "sxc");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.sun.xml.calc.template", "stc", false);
-            sMimeTypeMap.loadEntry("application/vnd.sun.xml.draw", "sxd", 
-                    false);
+                    "application/vnd.sun.xml.calc.template", "stc");
+            sMimeTypeMap.loadEntry("application/vnd.sun.xml.draw", "sxd");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.sun.xml.draw.template", "std", false);
-            sMimeTypeMap.loadEntry("application/vnd.sun.xml.impress", "sxi", 
-                    false);
+                    "application/vnd.sun.xml.draw.template", "std");
+            sMimeTypeMap.loadEntry("application/vnd.sun.xml.impress", "sxi");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.sun.xml.impress.template", "sti", false);
-            sMimeTypeMap.loadEntry("application/vnd.sun.xml.math", "sxm", 
-                    false);
-            sMimeTypeMap.loadEntry("application/vnd.sun.xml.writer", "sxw", 
-                    false);
+                    "application/vnd.sun.xml.impress.template", "sti");
+            sMimeTypeMap.loadEntry("application/vnd.sun.xml.math", "sxm");
+            sMimeTypeMap.loadEntry("application/vnd.sun.xml.writer", "sxw");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.sun.xml.writer.global", "sxg", false);
+                    "application/vnd.sun.xml.writer.global", "sxg");
             sMimeTypeMap.loadEntry(
-                    "application/vnd.sun.xml.writer.template", "stw", false);
-            sMimeTypeMap.loadEntry("application/vnd.visio", "vsd", false);
-            sMimeTypeMap.loadEntry("application/x-abiword", "abw", false);
-            sMimeTypeMap.loadEntry("application/x-apple-diskimage", "dmg", 
-                    false);
-            sMimeTypeMap.loadEntry("application/x-bcpio", "bcpio", false);
-            sMimeTypeMap.loadEntry("application/x-bittorrent", "torrent", 
-                    false);
-            sMimeTypeMap.loadEntry("application/x-cdf", "cdf", false);
-            sMimeTypeMap.loadEntry("application/x-cdlink", "vcd", false);
-            sMimeTypeMap.loadEntry("application/x-chess-pgn", "pgn", false);
-            sMimeTypeMap.loadEntry("application/x-cpio", "cpio", false);
-            sMimeTypeMap.loadEntry("application/x-debian-package", "deb", 
-                    false);
-            sMimeTypeMap.loadEntry("application/x-debian-package", "udeb", 
-                    false);
-            sMimeTypeMap.loadEntry("application/x-director", "dcr", false);
-            sMimeTypeMap.loadEntry("application/x-director", "dir", false);
-            sMimeTypeMap.loadEntry("application/x-director", "dxr", false);
-            sMimeTypeMap.loadEntry("application/x-dms", "dms", false);
-            sMimeTypeMap.loadEntry("application/x-doom", "wad", false);
-            sMimeTypeMap.loadEntry("application/x-dvi", "dvi", false);
-            sMimeTypeMap.loadEntry("application/x-flac", "flac", false);
-            sMimeTypeMap.loadEntry("application/x-font", "pfa", false);
-            sMimeTypeMap.loadEntry("application/x-font", "pfb", false);
-            sMimeTypeMap.loadEntry("application/x-font", "gsf", false);
-            sMimeTypeMap.loadEntry("application/x-font", "pcf", false);
-            sMimeTypeMap.loadEntry("application/x-font", "pcf.Z", false);
-            sMimeTypeMap.loadEntry("application/x-freemind", "mm", false);
-            sMimeTypeMap.loadEntry("application/x-futuresplash", "spl", false);
-            sMimeTypeMap.loadEntry("application/x-gnumeric", "gnumeric", false);
-            sMimeTypeMap.loadEntry("application/x-go-sgf", "sgf", false);
-            sMimeTypeMap.loadEntry("application/x-graphing-calculator", "gcf", 
-                    false);
-            sMimeTypeMap.loadEntry("application/x-gtar", "gtar", false);
-            sMimeTypeMap.loadEntry("application/x-gtar", "tgz", false);
-            sMimeTypeMap.loadEntry("application/x-gtar", "taz", false);
-            sMimeTypeMap.loadEntry("application/x-hdf", "hdf", false);
-            sMimeTypeMap.loadEntry("application/x-ica", "ica", false);
-            sMimeTypeMap.loadEntry("application/x-internet-signup", "ins", 
-                    false);
-            sMimeTypeMap.loadEntry("application/x-internet-signup", "isp", 
-                    false);
-            sMimeTypeMap.loadEntry("application/x-iphone", "iii", false);
-            sMimeTypeMap.loadEntry("application/x-iso9660-image", "iso", false);
-            sMimeTypeMap.loadEntry("application/x-jmol", "jmz", false);
-            sMimeTypeMap.loadEntry("application/x-kchart", "chrt", false);
-            sMimeTypeMap.loadEntry("application/x-killustrator", "kil", false);
-            sMimeTypeMap.loadEntry("application/x-koan", "skp", false);
-            sMimeTypeMap.loadEntry("application/x-koan", "skd", false);
-            sMimeTypeMap.loadEntry("application/x-koan", "skt", false);
-            sMimeTypeMap.loadEntry("application/x-koan", "skm", false);
-            sMimeTypeMap.loadEntry("application/x-kpresenter", "kpr", false);
-            sMimeTypeMap.loadEntry("application/x-kpresenter", "kpt", false);
-            sMimeTypeMap.loadEntry("application/x-kspread", "ksp", false);
-            sMimeTypeMap.loadEntry("application/x-kword", "kwd", false);
-            sMimeTypeMap.loadEntry("application/x-kword", "kwt", false);
-            sMimeTypeMap.loadEntry("application/x-latex", "latex", false);
-            sMimeTypeMap.loadEntry("application/x-lha", "lha", false);
-            sMimeTypeMap.loadEntry("application/x-lzh", "lzh", false);
-            sMimeTypeMap.loadEntry("application/x-lzx", "lzx", false);
-            sMimeTypeMap.loadEntry("application/x-maker", "frm", false);
-            sMimeTypeMap.loadEntry("application/x-maker", "maker", false);
-            sMimeTypeMap.loadEntry("application/x-maker", "frame", false);
-            sMimeTypeMap.loadEntry("application/x-maker", "fb", false);
-            sMimeTypeMap.loadEntry("application/x-maker", "book", false);
-            sMimeTypeMap.loadEntry("application/x-maker", "fbdoc", false);
-            sMimeTypeMap.loadEntry("application/x-mif", "mif", false);
-            sMimeTypeMap.loadEntry("application/x-ms-wmd", "wmd", false);
-            sMimeTypeMap.loadEntry("application/x-ms-wmz", "wmz", false);
-            sMimeTypeMap.loadEntry("application/x-msi", "msi", false);
-            sMimeTypeMap.loadEntry("application/x-ns-proxy-autoconfig", "pac", 
-                    false);
-            sMimeTypeMap.loadEntry("application/x-nwc", "nwc", false);
-            sMimeTypeMap.loadEntry("application/x-object", "o", false);
-            sMimeTypeMap.loadEntry("application/x-oz-application", "oza", 
-                    false);
-            sMimeTypeMap.loadEntry("application/x-pkcs12", "p12", false);
-            sMimeTypeMap.loadEntry("application/x-pkcs7-certreqresp", "p7r", 
-                    false);
-            sMimeTypeMap.loadEntry("application/x-pkcs7-crl", "crl", false);
-            sMimeTypeMap.loadEntry("application/x-quicktimeplayer", "qtl", 
-                    false);
-            sMimeTypeMap.loadEntry("application/x-shar", "shar", false);
-            sMimeTypeMap.loadEntry("application/x-stuffit", "sit", false);
-            sMimeTypeMap.loadEntry("application/x-sv4cpio", "sv4cpio", false);
-            sMimeTypeMap.loadEntry("application/x-sv4crc", "sv4crc", false);
-            sMimeTypeMap.loadEntry("application/x-tar", "tar", false);
-            sMimeTypeMap.loadEntry("application/x-texinfo", "texinfo", false);
-            sMimeTypeMap.loadEntry("application/x-texinfo", "texi", false);
-            sMimeTypeMap.loadEntry("application/x-troff", "t", false);
-            sMimeTypeMap.loadEntry("application/x-troff", "roff", false);
-            sMimeTypeMap.loadEntry("application/x-troff-man", "man", false);
-            sMimeTypeMap.loadEntry("application/x-ustar", "ustar", false);
-            sMimeTypeMap.loadEntry("application/x-wais-source", "src", false);
-            sMimeTypeMap.loadEntry("application/x-wingz", "wz", false);
-            sMimeTypeMap.loadEntry(
-                    "application/x-webarchive", "webarchive", false); // added
-            sMimeTypeMap.loadEntry("application/x-x509-ca-cert", "crt", false);
-            sMimeTypeMap.loadEntry("application/x-xcf", "xcf", false);
-            sMimeTypeMap.loadEntry("application/x-xfig", "fig", false);
-            sMimeTypeMap.loadEntry("application/xhtml+xml", "xhtml", false);
-            sMimeTypeMap.loadEntry("audio/basic", "snd", false);
-            sMimeTypeMap.loadEntry("audio/midi", "mid", false);
-            sMimeTypeMap.loadEntry("audio/midi", "midi", false);
-            sMimeTypeMap.loadEntry("audio/midi", "kar", false);
-            sMimeTypeMap.loadEntry("audio/mpeg", "mpga", false);
-            sMimeTypeMap.loadEntry("audio/mpeg", "mpega", false);
-            sMimeTypeMap.loadEntry("audio/mpeg", "mp2", false);
-            sMimeTypeMap.loadEntry("audio/mpeg", "mp3", false);
-            sMimeTypeMap.loadEntry("audio/mpeg", "m4a", false);
-            sMimeTypeMap.loadEntry("audio/mpegurl", "m3u", false);
-            sMimeTypeMap.loadEntry("audio/prs.sid", "sid", false);
-            sMimeTypeMap.loadEntry("audio/x-aiff", "aif", false);
-            sMimeTypeMap.loadEntry("audio/x-aiff", "aiff", false);
-            sMimeTypeMap.loadEntry("audio/x-aiff", "aifc", false);
-            sMimeTypeMap.loadEntry("audio/x-gsm", "gsm", false);
-            sMimeTypeMap.loadEntry("audio/x-mpegurl", "m3u", false);
-            sMimeTypeMap.loadEntry("audio/x-ms-wma", "wma", false);
-            sMimeTypeMap.loadEntry("audio/x-ms-wax", "wax", false);
-            sMimeTypeMap.loadEntry("audio/x-pn-realaudio", "ra", false);
-            sMimeTypeMap.loadEntry("audio/x-pn-realaudio", "rm", false);
-            sMimeTypeMap.loadEntry("audio/x-pn-realaudio", "ram", false);
-            sMimeTypeMap.loadEntry("audio/x-realaudio", "ra", false);
-            sMimeTypeMap.loadEntry("audio/x-scpls", "pls", false);
-            sMimeTypeMap.loadEntry("audio/x-sd2", "sd2", false);
-            sMimeTypeMap.loadEntry("audio/x-wav", "wav", false);
-            sMimeTypeMap.loadEntry("image/bmp", "bmp", false); // added
-            sMimeTypeMap.loadEntry("image/gif", "gif", false);
-            sMimeTypeMap.loadEntry("image/ico", "cur", false); // added
-            sMimeTypeMap.loadEntry("image/ico", "ico", false); // added
-            sMimeTypeMap.loadEntry("image/ief", "ief", false);
-            sMimeTypeMap.loadEntry("image/jpeg", "jpeg", false);
-            sMimeTypeMap.loadEntry("image/jpeg", "jpg", false);
-            sMimeTypeMap.loadEntry("image/jpeg", "jpe", false);
-            sMimeTypeMap.loadEntry("image/pcx", "pcx", false);
-            sMimeTypeMap.loadEntry("image/png", "png", false);
-            sMimeTypeMap.loadEntry("image/svg+xml", "svg", false);
-            sMimeTypeMap.loadEntry("image/svg+xml", "svgz", false);
-            sMimeTypeMap.loadEntry("image/tiff", "tiff", false);
-            sMimeTypeMap.loadEntry("image/tiff", "tif", false);
-            sMimeTypeMap.loadEntry("image/vnd.djvu", "djvu", false);
-            sMimeTypeMap.loadEntry("image/vnd.djvu", "djv", false);
-            sMimeTypeMap.loadEntry("image/vnd.wap.wbmp", "wbmp", false);
-            sMimeTypeMap.loadEntry("image/x-cmu-raster", "ras", false);
-            sMimeTypeMap.loadEntry("image/x-coreldraw", "cdr", false);
-            sMimeTypeMap.loadEntry("image/x-coreldrawpattern", "pat", false);
-            sMimeTypeMap.loadEntry("image/x-coreldrawtemplate", "cdt", false);
-            sMimeTypeMap.loadEntry("image/x-corelphotopaint", "cpt", false);
-            sMimeTypeMap.loadEntry("image/x-icon", "ico", false);
-            sMimeTypeMap.loadEntry("image/x-jg", "art", false);
-            sMimeTypeMap.loadEntry("image/x-jng", "jng", false);
-            sMimeTypeMap.loadEntry("image/x-ms-bmp", "bmp", false);
-            sMimeTypeMap.loadEntry("image/x-photoshop", "psd", false);
-            sMimeTypeMap.loadEntry("image/x-portable-anymap", "pnm", false);
-            sMimeTypeMap.loadEntry("image/x-portable-bitmap", "pbm", false);
-            sMimeTypeMap.loadEntry("image/x-portable-graymap", "pgm", false);
-            sMimeTypeMap.loadEntry("image/x-portable-pixmap", "ppm", false);
-            sMimeTypeMap.loadEntry("image/x-rgb", "rgb", false);
-            sMimeTypeMap.loadEntry("image/x-xbitmap", "xbm", false);
-            sMimeTypeMap.loadEntry("image/x-xpixmap", "xpm", false);
-            sMimeTypeMap.loadEntry("image/x-xwindowdump", "xwd", false);
-            sMimeTypeMap.loadEntry("model/iges", "igs", false);
-            sMimeTypeMap.loadEntry("model/iges", "iges", false);
-            sMimeTypeMap.loadEntry("model/mesh", "msh", false);
-            sMimeTypeMap.loadEntry("model/mesh", "mesh", false);
-            sMimeTypeMap.loadEntry("model/mesh", "silo", false);
-            sMimeTypeMap.loadEntry("text/calendar", "ics", true);
-            sMimeTypeMap.loadEntry("text/calendar", "icz", true);
-            sMimeTypeMap.loadEntry("text/comma-separated-values", "csv", true);
-            sMimeTypeMap.loadEntry("text/css", "css", true);
-            sMimeTypeMap.loadEntry("text/h323", "323", true);
-            sMimeTypeMap.loadEntry("text/iuls", "uls", true);
-            sMimeTypeMap.loadEntry("text/mathml", "mml", true);
+                    "application/vnd.sun.xml.writer.template", "stw");
+            sMimeTypeMap.loadEntry("application/vnd.visio", "vsd");
+            sMimeTypeMap.loadEntry("application/x-abiword", "abw");
+            sMimeTypeMap.loadEntry("application/x-apple-diskimage", "dmg");
+            sMimeTypeMap.loadEntry("application/x-bcpio", "bcpio");
+            sMimeTypeMap.loadEntry("application/x-bittorrent", "torrent");
+            sMimeTypeMap.loadEntry("application/x-cdf", "cdf");
+            sMimeTypeMap.loadEntry("application/x-cdlink", "vcd");
+            sMimeTypeMap.loadEntry("application/x-chess-pgn", "pgn");
+            sMimeTypeMap.loadEntry("application/x-cpio", "cpio");
+            sMimeTypeMap.loadEntry("application/x-debian-package", "deb");
+            sMimeTypeMap.loadEntry("application/x-debian-package", "udeb");
+            sMimeTypeMap.loadEntry("application/x-director", "dcr");
+            sMimeTypeMap.loadEntry("application/x-director", "dir");
+            sMimeTypeMap.loadEntry("application/x-director", "dxr");
+            sMimeTypeMap.loadEntry("application/x-dms", "dms");
+            sMimeTypeMap.loadEntry("application/x-doom", "wad");
+            sMimeTypeMap.loadEntry("application/x-dvi", "dvi");
+            sMimeTypeMap.loadEntry("application/x-flac", "flac");
+            sMimeTypeMap.loadEntry("application/x-font", "pfa");
+            sMimeTypeMap.loadEntry("application/x-font", "pfb");
+            sMimeTypeMap.loadEntry("application/x-font", "gsf");
+            sMimeTypeMap.loadEntry("application/x-font", "pcf");
+            sMimeTypeMap.loadEntry("application/x-font", "pcf.Z");
+            sMimeTypeMap.loadEntry("application/x-freemind", "mm");
+            sMimeTypeMap.loadEntry("application/x-futuresplash", "spl");
+            sMimeTypeMap.loadEntry("application/x-gnumeric", "gnumeric");
+            sMimeTypeMap.loadEntry("application/x-go-sgf", "sgf");
+            sMimeTypeMap.loadEntry("application/x-graphing-calculator", "gcf");
+            sMimeTypeMap.loadEntry("application/x-gtar", "gtar");
+            sMimeTypeMap.loadEntry("application/x-gtar", "tgz");
+            sMimeTypeMap.loadEntry("application/x-gtar", "taz");
+            sMimeTypeMap.loadEntry("application/x-hdf", "hdf");
+            sMimeTypeMap.loadEntry("application/x-ica", "ica");
+            sMimeTypeMap.loadEntry("application/x-internet-signup", "ins");
+            sMimeTypeMap.loadEntry("application/x-internet-signup", "isp");
+            sMimeTypeMap.loadEntry("application/x-iphone", "iii");
+            sMimeTypeMap.loadEntry("application/x-iso9660-image", "iso");
+            sMimeTypeMap.loadEntry("application/x-jmol", "jmz");
+            sMimeTypeMap.loadEntry("application/x-kchart", "chrt");
+            sMimeTypeMap.loadEntry("application/x-killustrator", "kil");
+            sMimeTypeMap.loadEntry("application/x-koan", "skp");
+            sMimeTypeMap.loadEntry("application/x-koan", "skd");
+            sMimeTypeMap.loadEntry("application/x-koan", "skt");
+            sMimeTypeMap.loadEntry("application/x-koan", "skm");
+            sMimeTypeMap.loadEntry("application/x-kpresenter", "kpr");
+            sMimeTypeMap.loadEntry("application/x-kpresenter", "kpt");
+            sMimeTypeMap.loadEntry("application/x-kspread", "ksp");
+            sMimeTypeMap.loadEntry("application/x-kword", "kwd");
+            sMimeTypeMap.loadEntry("application/x-kword", "kwt");
+            sMimeTypeMap.loadEntry("application/x-latex", "latex");
+            sMimeTypeMap.loadEntry("application/x-lha", "lha");
+            sMimeTypeMap.loadEntry("application/x-lzh", "lzh");
+            sMimeTypeMap.loadEntry("application/x-lzx", "lzx");
+            sMimeTypeMap.loadEntry("application/x-maker", "frm");
+            sMimeTypeMap.loadEntry("application/x-maker", "maker");
+            sMimeTypeMap.loadEntry("application/x-maker", "frame");
+            sMimeTypeMap.loadEntry("application/x-maker", "fb");
+            sMimeTypeMap.loadEntry("application/x-maker", "book");
+            sMimeTypeMap.loadEntry("application/x-maker", "fbdoc");
+            sMimeTypeMap.loadEntry("application/x-mif", "mif");
+            sMimeTypeMap.loadEntry("application/x-ms-wmd", "wmd");
+            sMimeTypeMap.loadEntry("application/x-ms-wmz", "wmz");
+            sMimeTypeMap.loadEntry("application/x-msi", "msi");
+            sMimeTypeMap.loadEntry("application/x-ns-proxy-autoconfig", "pac");
+            sMimeTypeMap.loadEntry("application/x-nwc", "nwc");
+            sMimeTypeMap.loadEntry("application/x-object", "o");
+            sMimeTypeMap.loadEntry("application/x-oz-application", "oza");
+            sMimeTypeMap.loadEntry("application/x-pkcs12", "p12");
+            sMimeTypeMap.loadEntry("application/x-pkcs7-certreqresp", "p7r");
+            sMimeTypeMap.loadEntry("application/x-pkcs7-crl", "crl");
+            sMimeTypeMap.loadEntry("application/x-quicktimeplayer", "qtl");
+            sMimeTypeMap.loadEntry("application/x-shar", "shar");
+            sMimeTypeMap.loadEntry("application/x-stuffit", "sit");
+            sMimeTypeMap.loadEntry("application/x-sv4cpio", "sv4cpio");
+            sMimeTypeMap.loadEntry("application/x-sv4crc", "sv4crc");
+            sMimeTypeMap.loadEntry("application/x-tar", "tar");
+            sMimeTypeMap.loadEntry("application/x-texinfo", "texinfo");
+            sMimeTypeMap.loadEntry("application/x-texinfo", "texi");
+            sMimeTypeMap.loadEntry("application/x-troff", "t");
+            sMimeTypeMap.loadEntry("application/x-troff", "roff");
+            sMimeTypeMap.loadEntry("application/x-troff-man", "man");
+            sMimeTypeMap.loadEntry("application/x-ustar", "ustar");
+            sMimeTypeMap.loadEntry("application/x-wais-source", "src");
+            sMimeTypeMap.loadEntry("application/x-wingz", "wz");
+            sMimeTypeMap.loadEntry("application/x-webarchive", "webarchive");
+            sMimeTypeMap.loadEntry("application/x-x509-ca-cert", "crt");
+            sMimeTypeMap.loadEntry("application/x-xcf", "xcf");
+            sMimeTypeMap.loadEntry("application/x-xfig", "fig");
+            sMimeTypeMap.loadEntry("application/xhtml+xml", "xhtml");
+            sMimeTypeMap.loadEntry("audio/basic", "snd");
+            sMimeTypeMap.loadEntry("audio/midi", "mid");
+            sMimeTypeMap.loadEntry("audio/midi", "midi");
+            sMimeTypeMap.loadEntry("audio/midi", "kar");
+            sMimeTypeMap.loadEntry("audio/mpeg", "mpga");
+            sMimeTypeMap.loadEntry("audio/mpeg", "mpega");
+            sMimeTypeMap.loadEntry("audio/mpeg", "mp2");
+            sMimeTypeMap.loadEntry("audio/mpeg", "mp3");
+            sMimeTypeMap.loadEntry("audio/mpeg", "m4a");
+            sMimeTypeMap.loadEntry("audio/mpegurl", "m3u");
+            sMimeTypeMap.loadEntry("audio/prs.sid", "sid");
+            sMimeTypeMap.loadEntry("audio/x-aiff", "aif");
+            sMimeTypeMap.loadEntry("audio/x-aiff", "aiff");
+            sMimeTypeMap.loadEntry("audio/x-aiff", "aifc");
+            sMimeTypeMap.loadEntry("audio/x-gsm", "gsm");
+            sMimeTypeMap.loadEntry("audio/x-mpegurl", "m3u");
+            sMimeTypeMap.loadEntry("audio/x-ms-wma", "wma");
+            sMimeTypeMap.loadEntry("audio/x-ms-wax", "wax");
+            sMimeTypeMap.loadEntry("audio/x-pn-realaudio", "ra");
+            sMimeTypeMap.loadEntry("audio/x-pn-realaudio", "rm");
+            sMimeTypeMap.loadEntry("audio/x-pn-realaudio", "ram");
+            sMimeTypeMap.loadEntry("audio/x-realaudio", "ra");
+            sMimeTypeMap.loadEntry("audio/x-scpls", "pls");
+            sMimeTypeMap.loadEntry("audio/x-sd2", "sd2");
+            sMimeTypeMap.loadEntry("audio/x-wav", "wav");
+            sMimeTypeMap.loadEntry("image/bmp", "bmp");
+            sMimeTypeMap.loadEntry("image/gif", "gif");
+            sMimeTypeMap.loadEntry("image/ico", "cur");
+            sMimeTypeMap.loadEntry("image/ico", "ico");
+            sMimeTypeMap.loadEntry("image/ief", "ief");
+            sMimeTypeMap.loadEntry("image/jpeg", "jpeg");
+            sMimeTypeMap.loadEntry("image/jpeg", "jpg");
+            sMimeTypeMap.loadEntry("image/jpeg", "jpe");
+            sMimeTypeMap.loadEntry("image/pcx", "pcx");
+            sMimeTypeMap.loadEntry("image/png", "png");
+            sMimeTypeMap.loadEntry("image/svg+xml", "svg");
+            sMimeTypeMap.loadEntry("image/svg+xml", "svgz");
+            sMimeTypeMap.loadEntry("image/tiff", "tiff");
+            sMimeTypeMap.loadEntry("image/tiff", "tif");
+            sMimeTypeMap.loadEntry("image/vnd.djvu", "djvu");
+            sMimeTypeMap.loadEntry("image/vnd.djvu", "djv");
+            sMimeTypeMap.loadEntry("image/vnd.wap.wbmp", "wbmp");
+            sMimeTypeMap.loadEntry("image/x-cmu-raster", "ras");
+            sMimeTypeMap.loadEntry("image/x-coreldraw", "cdr");
+            sMimeTypeMap.loadEntry("image/x-coreldrawpattern", "pat");
+            sMimeTypeMap.loadEntry("image/x-coreldrawtemplate", "cdt");
+            sMimeTypeMap.loadEntry("image/x-corelphotopaint", "cpt");
+            sMimeTypeMap.loadEntry("image/x-icon", "ico");
+            sMimeTypeMap.loadEntry("image/x-jg", "art");
+            sMimeTypeMap.loadEntry("image/x-jng", "jng");
+            sMimeTypeMap.loadEntry("image/x-ms-bmp", "bmp");
+            sMimeTypeMap.loadEntry("image/x-photoshop", "psd");
+            sMimeTypeMap.loadEntry("image/x-portable-anymap", "pnm");
+            sMimeTypeMap.loadEntry("image/x-portable-bitmap", "pbm");
+            sMimeTypeMap.loadEntry("image/x-portable-graymap", "pgm");
+            sMimeTypeMap.loadEntry("image/x-portable-pixmap", "ppm");
+            sMimeTypeMap.loadEntry("image/x-rgb", "rgb");
+            sMimeTypeMap.loadEntry("image/x-xbitmap", "xbm");
+            sMimeTypeMap.loadEntry("image/x-xpixmap", "xpm");
+            sMimeTypeMap.loadEntry("image/x-xwindowdump", "xwd");
+            sMimeTypeMap.loadEntry("model/iges", "igs");
+            sMimeTypeMap.loadEntry("model/iges", "iges");
+            sMimeTypeMap.loadEntry("model/mesh", "msh");
+            sMimeTypeMap.loadEntry("model/mesh", "mesh");
+            sMimeTypeMap.loadEntry("model/mesh", "silo");
+            sMimeTypeMap.loadEntry("text/calendar", "ics");
+            sMimeTypeMap.loadEntry("text/calendar", "icz");
+            sMimeTypeMap.loadEntry("text/comma-separated-values", "csv");
+            sMimeTypeMap.loadEntry("text/css", "css");
+            sMimeTypeMap.loadEntry("text/h323", "323");
+            sMimeTypeMap.loadEntry("text/iuls", "uls");
+            sMimeTypeMap.loadEntry("text/mathml", "mml");
             // add it first so it will be the default for ExtensionFromMimeType
-            sMimeTypeMap.loadEntry("text/plain", "txt", true);
-            sMimeTypeMap.loadEntry("text/plain", "asc", true);
-            sMimeTypeMap.loadEntry("text/plain", "text", true);
-            sMimeTypeMap.loadEntry("text/plain", "diff", true);
-            sMimeTypeMap.loadEntry("text/plain", "pot", true);
-            sMimeTypeMap.loadEntry("text/richtext", "rtx", true);
-            sMimeTypeMap.loadEntry("text/rtf", "rtf", true);
-            sMimeTypeMap.loadEntry("text/texmacs", "ts", true);
-            sMimeTypeMap.loadEntry("text/text", "phps", true);
-            sMimeTypeMap.loadEntry("text/tab-separated-values", "tsv", true);
-            sMimeTypeMap.loadEntry("text/x-bibtex", "bib", true);
-            sMimeTypeMap.loadEntry("text/x-boo", "boo", true);
-            sMimeTypeMap.loadEntry("text/x-c++hdr", "h++", true);
-            sMimeTypeMap.loadEntry("text/x-c++hdr", "hpp", true);
-            sMimeTypeMap.loadEntry("text/x-c++hdr", "hxx", true);
-            sMimeTypeMap.loadEntry("text/x-c++hdr", "hh", true);
-            sMimeTypeMap.loadEntry("text/x-c++src", "c++", true);
-            sMimeTypeMap.loadEntry("text/x-c++src", "cpp", true);
-            sMimeTypeMap.loadEntry("text/x-c++src", "cxx", true);
-            sMimeTypeMap.loadEntry("text/x-chdr", "h", true);
-            sMimeTypeMap.loadEntry("text/x-component", "htc", true);
-            sMimeTypeMap.loadEntry("text/x-csh", "csh", true);
-            sMimeTypeMap.loadEntry("text/x-csrc", "c", true);
-            sMimeTypeMap.loadEntry("text/x-dsrc", "d", true);
-            sMimeTypeMap.loadEntry("text/x-haskell", "hs", true);
-            sMimeTypeMap.loadEntry("text/x-java", "java", true);
-            sMimeTypeMap.loadEntry("text/x-literate-haskell", "lhs", true);
-            sMimeTypeMap.loadEntry("text/x-moc", "moc", true);
-            sMimeTypeMap.loadEntry("text/x-pascal", "p", true);
-            sMimeTypeMap.loadEntry("text/x-pascal", "pas", true);
-            sMimeTypeMap.loadEntry("text/x-pcs-gcd", "gcd", true);
-            sMimeTypeMap.loadEntry("text/x-setext", "etx", true);
-            sMimeTypeMap.loadEntry("text/x-tcl", "tcl", true);
-            sMimeTypeMap.loadEntry("text/x-tex", "tex", true);
-            sMimeTypeMap.loadEntry("text/x-tex", "ltx", true);
-            sMimeTypeMap.loadEntry("text/x-tex", "sty", true);
-            sMimeTypeMap.loadEntry("text/x-tex", "cls", true);
-            sMimeTypeMap.loadEntry("text/x-vcalendar", "vcs", true);
-            sMimeTypeMap.loadEntry("text/x-vcard", "vcf", true);
-            sMimeTypeMap.loadEntry("video/3gpp", "3gp", false);
-            sMimeTypeMap.loadEntry("video/3gpp", "3g2", false);
-            sMimeTypeMap.loadEntry("video/dl", "dl", false);
-            sMimeTypeMap.loadEntry("video/dv", "dif", false);
-            sMimeTypeMap.loadEntry("video/dv", "dv", false);
-            sMimeTypeMap.loadEntry("video/fli", "fli", false);
-            sMimeTypeMap.loadEntry("video/mpeg", "mpeg", false);
-            sMimeTypeMap.loadEntry("video/mpeg", "mpg", false);
-            sMimeTypeMap.loadEntry("video/mpeg", "mpe", false);
-            sMimeTypeMap.loadEntry("video/mp4", "mp4", false);
-            sMimeTypeMap.loadEntry("video/mpeg", "VOB", false);
-            sMimeTypeMap.loadEntry("video/quicktime", "qt", false);
-            sMimeTypeMap.loadEntry("video/quicktime", "mov", false);
-            sMimeTypeMap.loadEntry("video/vnd.mpegurl", "mxu", false);
-            sMimeTypeMap.loadEntry("video/x-la-asf", "lsf", false);
-            sMimeTypeMap.loadEntry("video/x-la-asf", "lsx", false);
-            sMimeTypeMap.loadEntry("video/x-mng", "mng", false);
-            sMimeTypeMap.loadEntry("video/x-ms-asf", "asf", false);
-            sMimeTypeMap.loadEntry("video/x-ms-asf", "asx", false);
-            sMimeTypeMap.loadEntry("video/x-ms-wm", "wm", false);
-            sMimeTypeMap.loadEntry("video/x-ms-wmv", "wmv", false);
-            sMimeTypeMap.loadEntry("video/x-ms-wmx", "wmx", false);
-            sMimeTypeMap.loadEntry("video/x-ms-wvx", "wvx", false);
-            sMimeTypeMap.loadEntry("video/x-msvideo", "avi", false);
-            sMimeTypeMap.loadEntry("video/x-sgi-movie", "movie", false);
-            sMimeTypeMap.loadEntry("x-conference/x-cooltalk", "ice", false);
-            sMimeTypeMap.loadEntry("x-epoc/x-sisx-app", "sisx", false);
+            sMimeTypeMap.loadEntry("text/plain", "txt");
+            sMimeTypeMap.loadEntry("text/plain", "asc");
+            sMimeTypeMap.loadEntry("text/plain", "text");
+            sMimeTypeMap.loadEntry("text/plain", "diff");
+            sMimeTypeMap.loadEntry("text/plain", "pot");
+            sMimeTypeMap.loadEntry("text/richtext", "rtx");
+            sMimeTypeMap.loadEntry("text/rtf", "rtf");
+            sMimeTypeMap.loadEntry("text/texmacs", "ts");
+            sMimeTypeMap.loadEntry("text/text", "phps");
+            sMimeTypeMap.loadEntry("text/tab-separated-values", "tsv");
+            sMimeTypeMap.loadEntry("text/x-bibtex", "bib");
+            sMimeTypeMap.loadEntry("text/x-boo", "boo");
+            sMimeTypeMap.loadEntry("text/x-c++hdr", "h++");
+            sMimeTypeMap.loadEntry("text/x-c++hdr", "hpp");
+            sMimeTypeMap.loadEntry("text/x-c++hdr", "hxx");
+            sMimeTypeMap.loadEntry("text/x-c++hdr", "hh");
+            sMimeTypeMap.loadEntry("text/x-c++src", "c++");
+            sMimeTypeMap.loadEntry("text/x-c++src", "cpp");
+            sMimeTypeMap.loadEntry("text/x-c++src", "cxx");
+            sMimeTypeMap.loadEntry("text/x-chdr", "h");
+            sMimeTypeMap.loadEntry("text/x-component", "htc");
+            sMimeTypeMap.loadEntry("text/x-csh", "csh");
+            sMimeTypeMap.loadEntry("text/x-csrc", "c");
+            sMimeTypeMap.loadEntry("text/x-dsrc", "d");
+            sMimeTypeMap.loadEntry("text/x-haskell", "hs");
+            sMimeTypeMap.loadEntry("text/x-java", "java");
+            sMimeTypeMap.loadEntry("text/x-literate-haskell", "lhs");
+            sMimeTypeMap.loadEntry("text/x-moc", "moc");
+            sMimeTypeMap.loadEntry("text/x-pascal", "p");
+            sMimeTypeMap.loadEntry("text/x-pascal", "pas");
+            sMimeTypeMap.loadEntry("text/x-pcs-gcd", "gcd");
+            sMimeTypeMap.loadEntry("text/x-setext", "etx");
+            sMimeTypeMap.loadEntry("text/x-tcl", "tcl");
+            sMimeTypeMap.loadEntry("text/x-tex", "tex");
+            sMimeTypeMap.loadEntry("text/x-tex", "ltx");
+            sMimeTypeMap.loadEntry("text/x-tex", "sty");
+            sMimeTypeMap.loadEntry("text/x-tex", "cls");
+            sMimeTypeMap.loadEntry("text/x-vcalendar", "vcs");
+            sMimeTypeMap.loadEntry("text/x-vcard", "vcf");
+            sMimeTypeMap.loadEntry("video/3gpp", "3gp");
+            sMimeTypeMap.loadEntry("video/3gpp", "3g2");
+            sMimeTypeMap.loadEntry("video/dl", "dl");
+            sMimeTypeMap.loadEntry("video/dv", "dif");
+            sMimeTypeMap.loadEntry("video/dv", "dv");
+            sMimeTypeMap.loadEntry("video/fli", "fli");
+            sMimeTypeMap.loadEntry("video/mpeg", "mpeg");
+            sMimeTypeMap.loadEntry("video/mpeg", "mpg");
+            sMimeTypeMap.loadEntry("video/mpeg", "mpe");
+            sMimeTypeMap.loadEntry("video/mp4", "mp4");
+            sMimeTypeMap.loadEntry("video/mpeg", "VOB");
+            sMimeTypeMap.loadEntry("video/quicktime", "qt");
+            sMimeTypeMap.loadEntry("video/quicktime", "mov");
+            sMimeTypeMap.loadEntry("video/vnd.mpegurl", "mxu");
+            sMimeTypeMap.loadEntry("video/x-la-asf", "lsf");
+            sMimeTypeMap.loadEntry("video/x-la-asf", "lsx");
+            sMimeTypeMap.loadEntry("video/x-mng", "mng");
+            sMimeTypeMap.loadEntry("video/x-ms-asf", "asf");
+            sMimeTypeMap.loadEntry("video/x-ms-asf", "asx");
+            sMimeTypeMap.loadEntry("video/x-ms-wm", "wm");
+            sMimeTypeMap.loadEntry("video/x-ms-wmv", "wmv");
+            sMimeTypeMap.loadEntry("video/x-ms-wmx", "wmx");
+            sMimeTypeMap.loadEntry("video/x-ms-wvx", "wvx");
+            sMimeTypeMap.loadEntry("video/x-msvideo", "avi");
+            sMimeTypeMap.loadEntry("video/x-sgi-movie", "movie");
+            sMimeTypeMap.loadEntry("x-conference/x-cooltalk", "ice");
+            sMimeTypeMap.loadEntry("x-epoc/x-sisx-app", "sisx");
         }
 
         return sMimeTypeMap;
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index 0488691..1a60dba 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -24,7 +24,9 @@
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.HashMap;
-import java.util.Vector;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
 
 /**
  * Functionality for manipulating the webstorage databases.
@@ -49,8 +51,9 @@
     // Global instance of a WebStorage
     private static WebStorage sWebStorage;
 
-    // We keep a copy of the origins, quotas and usages
-    // that we protect via a lock and update in syncValues()
+    // We keep the origins, quotas and usages as member values
+    // that we protect via a lock and update in syncValues().
+    // This is needed to transfer this data across threads.
     private static Lock mLock = new ReentrantLock();
     private static Condition mCacheUpdated = mLock.newCondition();
 
@@ -60,7 +63,7 @@
     static final int DELETE_ORIGIN = 2;
     static final int DELETE_ALL = 3;
 
-    private Vector <String> mOrigins;
+    private Set <String> mOrigins;
     private HashMap <String, Long> mQuotas = new HashMap<String, Long>();
     private HashMap <String, Long> mUsages = new HashMap<String, Long>();
 
@@ -102,18 +105,15 @@
                             Origin website = (Origin) msg.obj;
                             nativeSetQuotaForOrigin(website.getOrigin(),
                                                     website.getQuota());
-                            syncValues();
                             } break;
 
                         case DELETE_ORIGIN: {
                             Origin website = (Origin) msg.obj;
                             nativeDeleteOrigin(website.getOrigin());
-                            syncValues();
                             } break;
 
                         case DELETE_ALL:
-                            nativeDeleteAllDatabases();
-                            syncValues();
+                            nativeDeleteAllData();
                             break;
 
                         case UPDATE:
@@ -129,8 +129,8 @@
      * @hide
      * Returns a list of origins having a database
      */
-    public Vector getOrigins() {
-        Vector ret = null;
+    public Set getOrigins() {
+        Set ret = null;
         mLock.lock();
         try {
             update();
@@ -202,7 +202,6 @@
         if (origin != null) {
             if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
                 nativeSetQuotaForOrigin(origin, quota);
-                syncValues();
             } else {
                 postMessage(Message.obtain(null, SET_QUOTA_ORIGIN,
                     new Origin(origin, quota)));
@@ -218,7 +217,6 @@
         if (origin != null) {
             if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
                 nativeDeleteOrigin(origin);
-                syncValues();
             } else {
                 postMessage(Message.obtain(null, DELETE_ORIGIN,
                     new Origin(origin)));
@@ -230,10 +228,9 @@
      * @hide
      * Delete all databases
      */
-    public void deleteAllDatabases() {
+    public void deleteAllData() {
         if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
-            nativeDeleteAllDatabases();
-            syncValues();
+            nativeDeleteAllData();
         } else {
             postMessage(Message.obtain(null, DELETE_ALL));
         }
@@ -274,16 +271,17 @@
 
     /**
      * Run on the webcore thread
-     * sync the local cached values with the real ones
+     * set the local values with the current ones
      */
     private void syncValues() {
         mLock.lock();
-        Vector tmp = nativeGetOrigins();
-        mOrigins = new Vector<String>();
+        Set tmp = nativeGetOrigins();
+        mOrigins = new HashSet<String>();
         mQuotas.clear();
         mUsages.clear();
-        for (int i = 0; i < tmp.size(); i++) {
-            String origin = (String) tmp.get(i);
+        Iterator<String> iter = tmp.iterator();
+        while (iter.hasNext()) {
+            String origin = iter.next();
             mOrigins.add(origin);
             mQuotas.put(origin, new Long(nativeGetQuotaForOrigin(origin)));
             mUsages.put(origin, new Long(nativeGetUsageForOrigin(origin)));
@@ -293,10 +291,10 @@
     }
 
     // Native functions
-    private static native Vector nativeGetOrigins();
+    private static native Set nativeGetOrigins();
     private static native long nativeGetUsageForOrigin(String origin);
     private static native long nativeGetQuotaForOrigin(String origin);
     private static native void nativeSetQuotaForOrigin(String origin, long quota);
     private static native void nativeDeleteOrigin(String origin);
-    private static native void nativeDeleteAllDatabases();
+    private static native void nativeDeleteAllData();
 }
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index da1443c..d6c8f81 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -31,6 +31,7 @@
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.method.MovementMethod;
+import android.text.method.Touch;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.KeyCharacterMap;
@@ -71,6 +72,12 @@
     // need to send down the DOM events.
     private String          mPreChange;
     private Drawable        mBackground;
+    // Variables for keeping track of the touch down, to send to the WebView
+    // when a drag starts
+    private float           mDragStartX;
+    private float           mDragStartY;
+    private long            mDragStartTime;
+    private boolean         mDragSent;
     // Array to store the final character added in onTextChanged, so that its
     // KeyEvents may be determined.
     private char[]          mCharacter = new char[1];
@@ -366,6 +373,65 @@
     }
 
     @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        int initialScrollX = -1;
+        int initialScrollY = -1;
+        int selectionStart = -1;
+        int selectionEnd = -1;
+        int action = event.getAction();
+        if (action == MotionEvent.ACTION_MOVE) {
+            Spannable buffer = getText();
+            initialScrollX = Touch.getInitialScrollX(this, buffer);
+            initialScrollY = Touch.getInitialScrollY(this, buffer);
+            selectionStart = Selection.getSelectionStart(buffer);
+            selectionEnd = Selection.getSelectionEnd(buffer);
+        }
+        super.onTouchEvent(event);
+        switch (action) {
+        case MotionEvent.ACTION_DOWN:
+            // This event may be the start of a drag, so store it to pass to the
+            // WebView if it is.
+            mDragStartX = event.getX();
+            mDragStartY = event.getY();
+            mDragStartTime = event.getEventTime();
+            mDragSent = false;
+            break;
+        case MotionEvent.ACTION_MOVE:
+            if (mScrollX != initialScrollX
+                    || mScrollY != initialScrollY) {
+                // TextView scrolled, so return true.
+                // FIXME: Need to make the webkit text scroll to reflect this
+                return true;
+            }
+            if (Selection.getSelectionStart(getText()) != selectionStart
+                    || Selection.getSelectionEnd(getText()) != selectionEnd) {
+                // Selection changed, so return true
+                return true;
+            }
+            if (mWebView != null) {
+                // Only want to set the initial state once.
+                if (!mDragSent) {
+                    mWebView.initiateTextFieldDrag(mDragStartX, mDragStartY,
+                            mDragStartTime);
+                    mDragSent = true;
+                }
+                return mWebView.textFieldDrag(event);
+            }
+            return false;
+        case MotionEvent.ACTION_UP:
+        case MotionEvent.ACTION_CANCEL:
+            // Necessary for the WebView to reset its state
+            if (mWebView != null && mDragSent) {
+                mWebView.onTouchEvent(event);
+            }
+            break;
+        default:
+            break;
+        }
+        return true;
+    }
+
+    @Override
     public boolean onTrackballEvent(MotionEvent event) {
         if (isPopupShowing()) {
             return super.onTrackballEvent(event);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c1ba690..9ce95d6 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4494,6 +4494,38 @@
         nativeSelectBestAt(rect);
     }
 
+    /**
+     * Set our starting point and time for a drag from the WebTextView.
+     */
+    /*package*/ void initiateTextFieldDrag(float x, float y, long eventTime) {
+        if (!inEditingMode()) {
+            return;
+        }
+        mLastTouchX = x + (float) (mWebTextView.getLeft() - mScrollX);
+        mLastTouchY = y + (float) (mWebTextView.getTop() - mScrollY);
+        mLastTouchTime = eventTime;
+        if (!mScroller.isFinished()) {
+            mScroller.abortAnimation();
+            mPrivateHandler.removeMessages(RESUME_WEBCORE_UPDATE);
+        }
+        mSnapScrollMode = SNAP_NONE;
+        mVelocityTracker = VelocityTracker.obtain();
+        mTouchMode = TOUCH_DRAG_START_MODE;
+    }
+
+    /**
+     * Given a motion event from the WebTextView, set its location to our
+     * coordinates, and handle the event.
+     */
+    /*package*/ boolean textFieldDrag(MotionEvent event) {
+        if (!inEditingMode()) {
+            return false;
+        }
+        event.offsetLocation((float) (mWebTextView.getLeft() - mScrollX),
+                (float) (mWebTextView.getTop() - mScrollY));
+        return onTouchEvent(event);
+    }
+
     /*package*/ void shortPressOnTextField() {
         if (inEditingMode()) {
             View v = mWebTextView;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 777beed..eea97dc 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1535,6 +1535,9 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
 
+        // Dismiss the popup in case onSaveInstanceState() was not invoked
+        dismissPopup();
+
         final ViewTreeObserver treeObserver = getViewTreeObserver();
         if (treeObserver != null) {
             treeObserver.removeOnTouchModeChangeListener(this);
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 09a547f..e613ec4 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -116,6 +116,8 @@
     private boolean mDropDownAlwaysVisible = false;
 
     private boolean mDropDownDismissedOnCompletion = true;
+    
+    private boolean mForceIgnoreOutsideTouch = false;
 
     private int mLastKeyCode = KeyEvent.KEYCODE_UNKNOWN;
     private boolean mOpenBefore;
@@ -205,11 +207,10 @@
      * Private hook into the on click event, dispatched from {@link PassThroughClickListener}
      */
     private void onClickImpl() {
-        // if drop down should always visible, bring it back in front of the soft
-        // keyboard when the user touches the text field
-        if (mDropDownAlwaysVisible
-                && mPopup.isShowing()
-                && mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED) {
+        // If the dropdown is showing, bring it back in front of the soft
+        // keyboard when the user touches the text field.
+        if (mPopup.isShowing() &&
+                mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED) {
             ensureImeVisible();
         }
     }
@@ -1129,6 +1130,8 @@
                 heightSpec = mDropDownHeight;
             }
 
+            mPopup.setOutsideTouchable(mForceIgnoreOutsideTouch ? false : !mDropDownAlwaysVisible);
+
             mPopup.update(getDropDownAnchorView(), mDropDownHorizontalOffset,
                     mDropDownVerticalOffset, widthSpec, heightSpec);
         } else {
@@ -1154,7 +1157,10 @@
 
             mPopup.setWindowLayoutMode(widthSpec, heightSpec);
             mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
-            mPopup.setOutsideTouchable(true);
+            
+            // use outside touchable to dismiss drop down when touching outside of it, so
+            // only set this if the dropdown is not always visible
+            mPopup.setOutsideTouchable(mForceIgnoreOutsideTouch ? false : !mDropDownAlwaysVisible);
             mPopup.setTouchInterceptor(new PopupTouchIntercepter());
             mPopup.showAsDropDown(getDropDownAnchorView(),
                     mDropDownHorizontalOffset, mDropDownVerticalOffset);
@@ -1163,6 +1169,17 @@
             post(mHideSelector);
         }
     }
+    
+    /**
+     * Forces outside touches to be ignored. Normally if {@link #isDropDownAlwaysVisible()} is
+     * false, we allow outside touch to dismiss the dropdown. If this is set to true, then we
+     * ignore outside touch even when the drop down is not set to always visible.
+     * 
+     * @hide used only by SearchDialog
+     */
+    public void setForceIgnoreOutsideTouch(boolean forceIgnoreOutsideTouch) {
+        mForceIgnoreOutsideTouch = forceIgnoreOutsideTouch;
+    }
 
     /**
      * <p>Builds the popup window's content and returns the height the popup
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7eeb1ca..0421612 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2443,7 +2443,13 @@
         }
 
         if (ss.error != null) {
-            setError(ss.error);
+            final CharSequence error = ss.error;
+            // Display the error later, after the first layout pass
+            post(new Runnable() {
+                public void run() {
+                    setError(error);
+                }
+            });
         }
     }
 
@@ -3263,7 +3269,9 @@
             final TextView err = (TextView) inflater.inflate(com.android.internal.R.layout.textview_hint,
                     null);
 
-            mPopup = new ErrorPopup(err, 200, 50);
+            final float scale = getResources().getDisplayMetrics().density;
+            mPopup = new ErrorPopup(err, (int) (200 * scale + 0.5f),
+                    (int) (50 * scale + 0.5f));
             mPopup.setFocusable(false);
             // The user is entering text, so the input method is needed.  We
             // don't want the popup to be displayed on top of it.
@@ -3317,11 +3325,12 @@
          * The "25" is the distance between the point and the right edge
          * of the background
          */
+        final float scale = getResources().getDisplayMetrics().density;
 
         final Drawables dr = mDrawables;
         return getWidth() - mPopup.getWidth()
                 - getPaddingRight()
-                - (dr != null ? dr.mDrawableSizeRight : 0) / 2 + 25;
+                - (dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
     }
 
     /**
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index a03802d..a449e5f 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.os;
 
+import android.bluetooth.BluetoothHeadset;
 import android.os.BatteryStats;
 import android.os.NetStat;
 import android.os.Parcel;
@@ -128,7 +129,10 @@
     
     boolean mBluetoothOn;
     StopwatchTimer mBluetoothOnTimer;
-    
+
+    /** Bluetooth headset object */
+    BluetoothHeadset mBtHeadset;
+
     /**
      * These provide time bases that discount the time the device is plugged
      * in to power.
@@ -160,6 +164,9 @@
     private long mRadioDataUptime;
     private long mRadioDataStart;
 
+    private int mBluetoothPingCount;
+    private int mBluetoothPingStart = -1;
+
     /*
      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
      */
@@ -920,14 +927,18 @@
         dataTransfer[STATS_UNPLUGGED] = currentBytes;
     }
 
-    private long getCurrentRadioDataUptimeMs() {
+    /**
+     * Radio uptime in microseconds when transferring data. This value is very approximate.
+     * @return
+     */
+    private long getCurrentRadioDataUptime() {
         try {
             File awakeTimeFile = new File("/sys/devices/virtual/net/rmnet0/awake_time_ms");
             if (!awakeTimeFile.exists()) return 0;
             BufferedReader br = new BufferedReader(new FileReader(awakeTimeFile));
             String line = br.readLine();
             br.close();
-            return Long.parseLong(line);
+            return Long.parseLong(line) * 1000;
         } catch (NumberFormatException nfe) {
             // Nothing
         } catch (IOException ioe) {
@@ -936,14 +947,44 @@
         return 0;
     }
 
+    /**
+     * @deprecated use getRadioDataUptime
+     */
     public long getRadioDataUptimeMs() {
+        return getRadioDataUptime() / 1000;
+    }
+
+    /**
+     * Returns the duration that the cell radio was up for data transfers. 
+     */
+    public long getRadioDataUptime() {
         if (mRadioDataStart == -1) {
             return mRadioDataUptime;
         } else {
-            return getCurrentRadioDataUptimeMs() - mRadioDataStart;
+            return getCurrentRadioDataUptime() - mRadioDataStart;
         }
     }
 
+    private int getCurrentBluetoothPingCount() {
+        if (mBtHeadset != null) {
+            return mBtHeadset.getBatteryUsageHint();
+        }
+        return -1;
+    }
+
+    public int getBluetoothPingCount() {
+        if (mBluetoothPingStart == -1) {
+            return mBluetoothPingCount;
+        } else if (mBtHeadset != null) {
+            return getCurrentBluetoothPingCount() - mBluetoothPingStart;
+        }
+        return -1;
+    }
+
+    public void setBtHeadset(BluetoothHeadset headset) {
+        mBtHeadset = headset;
+    }
+
     public void doUnplug(long batteryUptime, long batteryRealtime) {
         for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
             Uid u = mUidStats.valueAt(iu);
@@ -961,8 +1002,11 @@
         doDataUnplug(mTotalDataRx, NetStat.getTotalRxBytes());
         doDataUnplug(mTotalDataTx, NetStat.getTotalTxBytes());
         // Track radio awake time
-        mRadioDataStart = getCurrentRadioDataUptimeMs();
+        mRadioDataStart = getCurrentRadioDataUptime();
         mRadioDataUptime = 0;
+        // Track bt headset ping count
+        mBluetoothPingStart = getCurrentBluetoothPingCount();
+        mBluetoothPingCount = 0;
     }
 
     public void doPlug(long batteryUptime, long batteryRealtime) {
@@ -985,8 +1029,12 @@
         doDataPlug(mTotalDataRx, NetStat.getTotalRxBytes());
         doDataPlug(mTotalDataTx, NetStat.getTotalTxBytes());
         // Track radio awake time
-        mRadioDataUptime = getRadioDataUptimeMs();
+        mRadioDataUptime = getRadioDataUptime();
         mRadioDataStart = -1;
+
+        // Track bt headset ping count
+        mBluetoothPingCount = getBluetoothPingCount();
+        mBluetoothPingStart = -1;
     }
 
     public void noteStartGps(int uid) {
@@ -3335,6 +3383,9 @@
         mRadioDataUptime = in.readLong();
         mRadioDataStart = -1;
 
+        mBluetoothPingCount = in.readInt();
+        mBluetoothPingStart = -1;
+
         mKernelWakelockStats.clear();
         int NKW = in.readInt();
         for (int ikw = 0; ikw < NKW; ikw++) {
@@ -3415,7 +3466,9 @@
         out.writeLong(getTotalTcpBytesSent(STATS_UNPLUGGED));
 
         // Write radio uptime for data
-        out.writeLong(getRadioDataUptimeMs());
+        out.writeLong(getRadioDataUptime());
+
+        out.writeInt(getBluetoothPingCount());
 
         out.writeInt(mKernelWakelockStats.size());
         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 4a8d8b1..94f703a 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -87,6 +87,11 @@
     public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active";
 
     /**
+     * Power consumption when Bluetooth driver gets an AT command.
+     */
+    public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at";
+
+    /**
      * Power consumption when screen is on, not including the backlight power.
      */
     public static final String POWER_SCREEN_ON = "screen.on";
diff --git a/core/java/com/google/android/net/GoogleHttpClient.java b/core/java/com/google/android/net/GoogleHttpClient.java
index 922f5be..8a1298f 100644
--- a/core/java/com/google/android/net/GoogleHttpClient.java
+++ b/core/java/com/google/android/net/GoogleHttpClient.java
@@ -58,8 +58,8 @@
  * and otherwise tweak HTTP requests.
  */
 public class GoogleHttpClient implements HttpClient {
-
     private static final String TAG = "GoogleHttpClient";
+    private static final boolean LOCAL_LOGV = Config.LOGV || false;
 
     /** Exception thrown when a request is blocked by the URL rules. */
     public static class BlockedRequestException extends IOException {
@@ -289,9 +289,7 @@
         wrapper.setURI(uri);
         request = wrapper;
 
-        if (Config.LOGV) {
-            Log.v(TAG, "Rule " + rule.mName + ": " + original + " -> " + rewritten);
-        }
+        if (LOCAL_LOGV) Log.v(TAG, "Rule " + rule.mName + ": " + original + " -> " + rewritten);
         return executeWithoutRewriting(request, context);
     }
 
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 6776dce..8a312d9 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -171,7 +171,8 @@
                 mCameraJObjectWeak, msgType, 0, 0, NULL);
         break;
     default:
-        LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
+        // TODO: Change to LOGV
+        LOGD("dataCallback(%d, %p)", msgType, dataPtr.get());
         copyAndPost(env, dataPtr, msgType);
         break;
     }
@@ -222,6 +223,8 @@
 // finalizer is invoked later.
 static void android_hardware_Camera_release(JNIEnv *env, jobject thiz)
 {
+    // TODO: Change to LOGV
+    LOGD("release camera");
     JNICameraContext* context = NULL;
     sp<Camera> camera;
     {
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 2d90ba4..59f4067 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -553,7 +553,7 @@
     config.touchscreen = (uint8_t)touchscreen;
     config.density = (uint16_t)density;
     config.keyboard = (uint8_t)keyboard;
-    config.inputFlags = (uint8_t)keyboardHidden<<ResTable_config::SHIFT_KEYSHIDDEN;
+    config.inputFlags = (uint8_t)keyboardHidden;
     config.navigation = (uint8_t)navigation;
     config.screenWidth = (uint16_t)screenWidth;
     config.screenHeight = (uint16_t)screenHeight;
diff --git a/core/res/res/layout/search_dropdown_app_selector.xml b/core/res/res/layout/search_dropdown_app_selector.xml
deleted file mode 100644
index f86645f..0000000
--- a/core/res/res/layout/search_dropdown_app_selector.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/res/layout/search_dropdown_app_selector.xml
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight"
-    android:orientation="horizontal"
-    android:gravity="center_vertical"
-    android:baselineAligned="false"
-    >
-
-    <ImageView android:id="@+id/search_app_icon1"
-        android:layout_width="32dip"
-        android:layout_height="32dip"
-        android:layout_gravity="center_vertical"
-        android:scaleType="fitCenter"
-        android:src="@android:drawable/ic_search_category_default" />
-        
-    <TextView android:id="@+id/search_app_text1"
-        style="?android:attr/dropDownItemStyle"
-        android:singleLine="true"
-        android:layout_height="wrap_content"
-        android:layout_width="0dip"
-        android:layout_weight="1"
-        android:layout_gravity="center_vertical" />
-    
-</LinearLayout>
diff --git a/core/res/res/layout/search_dropdown_item_2line.xml b/core/res/res/layout/search_dropdown_item_2line.xml
deleted file mode 100644
index 5546b6636..0000000
--- a/core/res/res/layout/search_dropdown_item_2line.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/layout/simple_spinner_item.xml
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:layout_width="fill_parent"
-    android:layout_height="?android:attr/searchResultListItemHeight"
-    android:orientation="horizontal"
-    android:gravity="center_vertical"
-    android:baselineAligned="false"
-    >
-    
-    <TwoLineListItem
-        android:paddingTop="1dip"
-        android:paddingBottom="1dip"
-        android:gravity="center_vertical"
-        android:layout_width="0dip"
-        android:layout_weight="1"
-        android:layout_height="wrap_content"
-        android:mode="twoLine" >
-    
-        <TextView
-            android:id="@android:id/text1"
-            style="?android:attr/dropDownItemStyle"
-            android:textAppearance="?android:attr/textAppearanceSearchResultTitle"
-            android:singleLine="true"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content" />
-    
-        <TextView
-            android:id="@android:id/text2"
-            style="?android:attr/dropDownItemStyle"
-            android:textAppearance="?android:attr/textAppearanceSearchResultSubtitle"
-            android:textColor="?android:attr/textColorSecondaryInverse"
-            android:singleLine="true"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:layout_below="@android:id/text1"
-            android:layout_alignLeft="@android:id/text1" />
-    
-    </TwoLineListItem>
-
-</LinearLayout>
diff --git a/core/res/res/layout/search_dropdown_item_icons_1line.xml b/core/res/res/layout/search_dropdown_item_icons_1line.xml
deleted file mode 100644
index 4f65d74..0000000
--- a/core/res/res/layout/search_dropdown_item_icons_1line.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/layout/simple_spinner_item.xml
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
--->
-
-    <!-- NOTE: The appearance of the inner text element must match the appearance -->
-    <!-- of the text element in apps/common/res/layout/simple_dropdown_item_1line.xml -->
-    
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:paddingLeft="4dip"
-    android:paddingRight="2dip"
-    android:layout_width="fill_parent"
-    android:layout_height="?android:attr/searchResultListItemHeight"
-    android:orientation="horizontal"
-    android:gravity="center_vertical"
-    android:baselineAligned="false"
-    >
-    
-    <ImageView android:id="@android:id/icon1"
-        android:layout_width="48dip"
-        android:layout_height="48dip"
-        android:layout_gravity="center_vertical"
-        android:scaleType="centerInside" />
-
-    <TextView android:id="@android:id/text1"
-        style="?android:attr/dropDownItemStyle"
-        android:textAppearance="?android:attr/textAppearanceSearchResultTitle"
-        android:singleLine="true"
-        android:layout_height="wrap_content"
-        android:layout_width="0dip"
-        android:layout_weight="1"  />
-
-    <ImageView android:id="@android:id/icon2"
-        android:layout_width="48dip"
-        android:layout_height="48dip"
-        android:layout_gravity="center_vertical"
-        android:scaleType="centerInside" />
-
-</LinearLayout>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 9dc483c..48b565f 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -827,28 +827,6 @@
         <attr name="name" />
     </declare-styleable>
     
-    <!-- The <code>supports-density</code> specifies a screen density that this
-         package supports. Application can specify multiple densities it supports.
-         <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).
-             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;
@@ -885,6 +863,18 @@
              screen, so that it retains the dimensions it was originally
              designed for. -->
         <attr name="largeScreens" format="boolean" />
+        <!-- Indicates whether the application can resize itself to newer
+             screen sizes.  This is mostly used to distinguish between old
+             applications that may not be compatible with newly introduced
+             screen sizes and newer applications that should be; it will be
+             set for you automatically based on whether you are targeting
+             a newer platform that supports more screens. -->
+        <attr name="resizeable" format="boolean" />
+        <!-- Indicates whether the application can accommodate any screen
+             density.  Older applications are assumed to not be able to,
+             new ones able to.  You can explicitly supply your abilities
+             here. -->
+        <attr name="anyDensity" format="boolean" />
     </declare-styleable>
 
     <!-- Private tag to declare system protected broadcast actions.
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6906e438..f8dd4c1 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1093,7 +1093,7 @@
 
   <public type="attr" name="tension" id="0x0101026a" />
   <public type="attr" name="extraTension" />
-  <public type="attr" name="density" />
+  <public type="attr" name="anyDensity" />
   <public type="attr" name="searchSuggestThreshold" />
   <public type="attr" name="includeInGlobalSearch" />
   <public type="attr" name="onClick" />
@@ -1126,6 +1126,7 @@
   <public type="attr" name="searchSettingsDescription" />
   <public type="attr" name="textColorPrimaryInverseDisableOnly" />
   <public type="attr" name="autoUrlDetect" />
+  <public type="attr" name="resizeable" />
 
   <public-padding type="attr" name="donut_resource_pad" end="0x0101029f" />
 
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 8eda12e..6df8b0a 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -687,8 +687,8 @@
 
     <style name="MediaButton">
         <item name="android:background">@android:drawable/media_button_background</item>
-        <item name="android:layout_width">71px</item>
-        <item name="android:layout_height">52px</item>
+        <item name="android:layout_width">71dip</item>
+        <item name="android:layout_height">52dip</item>
     </style>
 
     <style name="MediaButton.Previous">
diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd
index 35c0a1a..c00f312 100644
--- a/docs/html/guide/developing/device.jd
+++ b/docs/html/guide/developing/device.jd
@@ -145,7 +145,7 @@
               <code>SUBSYSTEM=="usb_device", SYSFS{idVendor}=="0bb4", MODE="0666"</code></p>
           </li>
           <li>Now execute:<br/>
-              <code>chmod a+rx /etc/udev/rules.d/50-android.rules</code>
+              <code>chmod a+r /etc/udev/rules.d/50-android.rules</code>
           </li>
         </ol>
 
diff --git a/docs/html/guide/topics/resources/resources-i18n.jd b/docs/html/guide/topics/resources/resources-i18n.jd
index 2bcc5e3..85b89d1 100755
--- a/docs/html/guide/topics/resources/resources-i18n.jd
+++ b/docs/html/guide/topics/resources/resources-i18n.jd
@@ -441,7 +441,7 @@
 <pre>
 MyApp/
     res/
-        drawable-en-rUS-port-160dpi-finger-keysexposed-qwerty-dpad-480x320/
+        drawable-en-rUS-large-long-port-mdpi-finger-keysexposed-qwerty-dpad-480x320/
 </pre>
 
 <p>More typically, you will only specify a few specific configuration options. You may drop any of the values from the
@@ -453,7 +453,7 @@
     res/
         drawable-en-rUS-finger/
         drawable-port/
-        drawable-port-160dpi/
+        drawable-port-mdpi/
         drawable-qwerty/
 </pre>
 <p>Table 2 lists the valid folder-name qualifiers, in order of precedence. Qualifiers that are listed higher in the table take precedence over those listed lower, as described in <a href="#best-match">How Android finds the best matching directory</a>. </p>
@@ -465,37 +465,111 @@
     </tr>
     <tr>
       <td>MCC and MNC</td>
-      <td>The mobile country code and mobile network code from the SIM in the device. For example  <code>mcc310-mnc004</code> (U.S., Verizon brand); <code>mcc208-mnc00</code> (France, Orange brand); <code>mcc234-mnc00</code> (U.K., BT brand). <br>
-        <br>
-        If the device uses a radio connection  (GSM phone), the MCC will come from the SIM, and the MNC will come from the  network to which the device is attached. You might sometimes use the MCC alone, for example to include country-specific legal resources in your application. If your application specifies resources for a MCC/MNC  combination, those resources can only be used if both the MCC and the MNC match. </td>
-  </tr>
+      <td><p>The mobile country code optionally followed by mobile network code
+      from the SIM in the device. For example
+      <code>mcc310</code> (U.S. on any carrier);
+      <code>mcc310-mnc004</code> (U.S., Verizon brand);
+      <code>mcc208-mnc00</code> (France, Orange brand);
+      <code>mcc234-mnc00</code> (U.K., BT brand).
+        </p><p>
+        If the device uses a radio connection  (GSM phone), the MCC will come
+        from the SIM, and the MNC will come from the  network to which the
+        device is attached. You might sometimes use the MCC alone, for example
+        to include country-specific legal resources in your application. If
+        your application specifies resources for a MCC/MNC  combination, those
+        resources can only be used if both the MCC and the MNC match. </p></td>
+    </tr>
     <tr>
         <td>Language and region</td>
-        <td>The two letter <a href="http://www.loc.gov/standards/iso639-2/php/code_list.php">ISO
-                639-1</a> language code and two letter
+        <td><p>The two letter <a href="http://www.loc.gov/standards/iso639-2/php/code_list.php">ISO
+                639-1</a> language code optionally followed by a two letter
                 <a href="http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html">ISO
                 3166-1-alpha-2</a> region code (preceded by lowercase &quot;r&quot;). For example 
-                <code>en-rUS</code>, <code>fr-rFR</code>, <code>es-rES</code>. <br>
-                <br>
-          The codes are case-sensitive: The language code is lowercase, and the country code is uppercase. You cannot specify a region alone, but you can specify a language alone, for example <code>en</code>, <code>fr</code>, <code>es</code>. </td>
-  </tr>
+                <code>fr</code>, <code>en-rUS</code>, <code>fr-rFR</code>, <code>es-rES</code>.
+          </p><p>
+          The codes are <em>not</em> case-sensitive; the r prefix is used to
+          distinguish the region portion.
+          You cannot specify a region alone, but you can specify a language alone,
+          for example <code>en</code>, <code>fr</code>, <code>es</code>.</p> </td>
+    </tr>
+    <tr>
+        <td>Screen dimensions</td>
+        <td><p><code>small</code>, <code>normal</code>, <code>large</code>
+        </p><p>
+        Specify that the resource is for a particular class of screen.
+        The meanings of these are:</p>
+        <ul>
+        <li> <b>Normal screens</b> are based on the traditional Android HVGA
+        medium density screen.  A screen is considered to be normal if it is
+        at least this size (independent of density) and not large.  Examples
+        of such screens a WQVGA low density, HVGA medium density, WVGA
+        high density.
+        <li> <b>Small screens</b> are based on the space available on a
+        QVGA low density screen.  Considering a portrait HVGA display, this has
+        the same available width but less height -- it is 3:4 vs. HVGA's
+        2:3 aspect ratio.  Examples are QVGA low density and VGA high
+        density.
+        <li> <b>Large screens</b> are based on the space available on a
+        VGA medium density screen.  Such a screen has significantly more
+        available space in both width and height than an HVGA display.
+        Examples are VGA and WVGA medium density screens.
+        </td>
+    </tr>
+    <tr>
+        <td>Wider/taller screens</td>
+        <td><p><code>long</code>, <code>notlong</code>
+        </p><p>
+        Specify that the resource is for a taller/wider than traditional
+        screen.  This is based purely on the aspect ration of the screen:
+        QVGA, HVGA, and VGA are notlong; WQVGA, WVGA, FWVGA are long.  Note
+        that long may mean either wide or tall, depending on the current
+        orientation.</p>
+        </td>
+    </tr>
     <tr>
         <td>Screen orientation</td>
-        <td><code>port</code>, <code>land</code>, <code>square</code> </td>
+        <td><p><code>port</code>, <code>land</code>, <code>square</code>
+        </p><p>
+        Specifies that the resource is for a screen that is tall (port)
+        or wide (land); square is not currently used.</p>
+        </td>
     </tr>
     <tr>
         <td>Screen pixel density</td>
-        <td><code>92dpi</code>, <code>108dpi</code>, etc. When Android selects which resource files to use, it handles screen density  differently than the other qualifiers. In step 1 of <a href="#best-match">How Android finds the best matching directory</a> (below),  screen density is always  considered to be a match. In step 4, if the qualifier being considered is screen density, Android will select the best final match at that point, without any need to move on to step 5. </td>
-  </tr>
+        <td><p><code>ldpi</code>, <code>mdpi</code>, <code>hdpi</code>, <code>nodpi</code>
+        </p><p>
+         Specifies the screen density the resource is defined for.  The medium
+         density of traditional HVGA screens (mdpi) is defined to be approximately
+         160dpi; low density (ldpi) is 120, and high density (hdpi) is 240.  There
+         is thus a 4:3 scaling factor between each density, so a 9x9 bitmap
+         in ldpi would be 12x12 is mdpi and 16x16 in hdpi.  The special
+         <code>nodpi</code> density can be used with bitmap resources to prevent
+         them from being scaled at load time to match the device density.
+        </p><p>
+         When Android selects which resource files to use,
+         it handles screen density  differently than the other qualifiers.
+         In step 1 of <a href="#best-match">How Android finds the best
+         matching directory</a> (below), screen density is always considered to
+         be a match. In step 4, if the qualifier being considered is screen
+         density, Android will select the best final match at that point,
+         without any need to move on to step 5.
+         </p><p>
+         You can also specify explicit densities like <code>92dpi</code>
+         or <code>108dpi</code>, but these are not fully supported by the
+         system so should not be used.
+         </p>
+         </td>
+    </tr>
     <tr>
         <td>Touchscreen type</td>
         <td><code>notouch</code>, <code>stylus</code>, <code>finger</code></td>
     </tr>
     <tr>
         <td>Whether the keyboard is available to the user</td>
-        <td><code>keysexposed</code>, <code>keyshidden</code>, <code>keyssoft</code> <br>
-          If your application has specific resources that should only be used with a soft keyboard, use the <code>keyssoft</code> value. If no <code>keyssoft</code> resources are available (only <code>keysexposed</code> and <code>keyshidden</code>) and the device  shows a soft keyboard,  the system will use <code>keysexposed</code> resources. </td>
-  </tr>
+        <td><p><code>keysexposed</code>, <code>keyshidden</code>, <code>keyssoft</code>
+        </p><p>
+          If your application has specific resources that should only be used with a soft keyboard, use the <code>keyssoft</code> value. If no <code>keyssoft</code> resources are available (only <code>keysexposed</code> and <code>keyshidden</code>) and the device  shows a soft keyboard,  the system will use <code>keysexposed</code> resources.</p> </td>
+    </tr>
     <tr>
         <td>Primary text input method</td>
         <td><code>nokeys</code>, <code>qwerty</code>, <code>12key</code> </td>
@@ -508,15 +582,17 @@
     <tr>
         <td>Screen dimensions</td>
         <td><code>320x240</code>, <code>640x480</code>, etc. The larger dimension
-            must be specified first. </td>
+            must be specified first.  This configuration is deprecated and
+            should not be used; use instead screen dimension, wider/taller
+            screens, and screen orientation described above.</td>
     </tr>
     <tr>
       <td>SDK version</td>
       <td>The SDK version supported by the device, for example <code>v3</code>. The Android 1.0 SDK is <code>v1, </code> the 1.1 SDK is <code>v2</code>, and the 1.5 SDK is <code>v3</code>.</td>
-  </tr>
+    </tr>
     <tr>
       <td>(Minor version)</td>
-      <td>(You cannot currently    specify minor version. It is always set to 0.)</td>
+      <td>(You cannot currently specify minor version. It is always set to 0.)</td>
   </tr>
 </table>
 
@@ -536,8 +612,11 @@
         <li>Incorrect: <code>values-nokeys-mcc460/</code></li>
       </ul>
     </li>
-    <li>Values are case-sensitive. For example, a portrait-specific <code>drawable</code> directory must be named
-    <code>drawable-port</code>, not <code>drawable-PORT</code> or <code>drawable-Port</code>.</li>
+    <li>Values are case-insensitive.  The resource compiler converts folder names
+    to lower case before processing to avoid problems in case-insensitive
+    file systems.  On case-sensitive file systems, you should keep all names
+    lower-case or at least use a consistent case to protect your future
+    sanity when trying to find a resource file.</li>
     <li>Only one value for each qualifier type is supported. For example, if you want to use exactly the same drawable files for Spain and France, you will need two  resource directories, such as <code>drawable-rES/</code> and <code>drawable-rFR/</code>, containing identical files. You cannot 
         have a directory named <code>drawable-rES-rFR/</code>. </li>
     <li>Qualified directories cannot be nested. For example, you cannot have <code>res/drawable/drawable-en</code>. </li>
@@ -546,7 +625,7 @@
 <h3>How resources are referenced in code</h3>
 <p>All resources will be referenced in code or resource reference syntax by
     their simple, undecorated names. So if a resource were named this:<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>MyApp/res/drawable-port-92dpi/myimage.png</code><br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>MyApp/res/drawable-port-mdpi/myimage.png</code><br />
   It would be referenced as this:<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>R.drawable.myimage</code> (code)<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>&#064;drawable/myimage</code> (XML)</p>
@@ -554,11 +633,12 @@
 <h3 id="best-match">How Android finds the best matching directory </h3>
 
 <p>Android will pick which of the various underlying resource files should be
-used at runtime, depending on the current configuration of the device. The example used here assumes the following device configuration:</p>
+used at runtime, depending on the current configuration of the device.
+The example used here assumes the following device configuration:</p>
 <blockquote>
   <p>Locale = <code>en-GB</code><br>
   Screen orientation = <code>port</code><br>
-  Screen pixel density = <code>108dpi</code><br>
+  Screen pixel density = <code>mdpi</code><br>
     Touchscreen type = <code>notouch</code><br>
     Primary text input method = <code>12key</code><br>
   </p>
@@ -573,9 +653,9 @@
 <strike>MyApp/res/drawable-fr-rCA/</strike>
 MyApp/res/drawable-en-port/
 MyApp/res/drawable-en-notouch-12key/
-MyApp/res/drawable-port-92dpi/
+MyApp/res/drawable-port-ldpi/
 MyApp/res/drawable-port-notouch-12key</pre>
-      <strong>Exception: </strong>Screen pixel density is the one qualifier that is not used to eliminate files. Even though the screen density of the device is 108 dpi, <code>drawable-port-92dpi/</code> is not  eliminated from the list, because every screen density is considered to be a 
+      <strong>Exception: </strong>Screen pixel density is the one qualifier that is not used to eliminate files. Even though the screen density of the device is medium dpi, <code>drawable-port-ldpi/</code> is not  eliminated from the list, because every screen density is considered to be a 
         match at this point.</li>
     <li>From <a href="#table2">Table 2</a>, pick the   highest-precedence qualifier that remains in the list. (Start with MCC, then move down through the list.) </li>
   <li>Do any of the available resource directories include this qualifier?  </li>
@@ -588,7 +668,7 @@
 MyApp/res/drawable-en/
 MyApp/res/drawable-en-port/
 MyApp/res/drawable-en-notouch-12key/
-<strike>MyApp/res/drawable-port-92dpi/</strike>
+<strike>MyApp/res/drawable-port-ldpi/</strike>
 <strike>MyApp/res/drawable-port-notouch-12key</strike></pre>
   <strong>Exception:</strong> If the qualifier in question  is screen pixel density, Android will select the option that most closely matches the device, and the selection process will be complete. In general, Android will prefer scaling down a larger original image to scaling  up a smaller original image.<br><br></li>
 
@@ -597,7 +677,11 @@
     <pre><strike>MyApp/res/drawable-en/</strike>
 MyApp/res/drawable-en-port/
 <strike>MyApp/res/drawable-en-notouch-12key/</strike></pre>
-  Only one choice remains, so that's it. When drawables are called for in this example application, the Android system will load resources from the <code>MyApp/res/drawable-en-port/</code> directory.
+  Only one choice remains, so that's it. When drawables are called for in this
+  example application, the Android system will load resources from the
+  <code>MyApp/res/drawable-en-port/</code> directory.  In addition, if the
+  resource being loaded is a bitmap, it will be scaled up so that its supplied
+  low density matches the device's medium density.
 </ol>
 <p class="note"><strong>Tip:</strong> The <em>precedence</em> of the qualifiers is more important than the number of qualifiers that exactly match the device. For example, in step 4 above, the last choice on the list includes three qualifiers that exactly match the device (orientation, touchscreen type, and input method), while <code>drawable-en</code> has only one parameter that matches (language). However, language has a higher precedence, so <code>drawable-port-notouch-12key</code> is out.</p>
 <p>This flowchart summarizes how Android selects resource directories to load.</p>
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 50ab566..42a14ce 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -552,10 +552,10 @@
      */
     public void scale(float scale) {
         if (scale != 1.0f) {
-            left *= scale;
-            top *= scale;
-            right *= scale;
-            bottom*= scale;
+            left = (int) (left * scale + 0.5f);
+            top = (int) (top * scale + 0.5f);
+            right = (int) (right * scale + 0.5f);
+            bottom = (int) (bottom * scale + 0.5f);
         }
     }
 }
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 376b1df..dc80cf5 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -272,6 +272,8 @@
         boolean     mCheckedConstantState;
         boolean     mCanConstantState;
 
+        boolean     mPaddingChecked = false;
+
         DrawableContainerState(DrawableContainerState orig, DrawableContainer owner) {
             mOwner = owner;
 
@@ -334,6 +336,7 @@
             mHaveStateful = false;
 
             mConstantPadding = null;
+            mPaddingChecked = false;
             mComputedConstantSize = false;
 
             return pos;
@@ -359,23 +362,25 @@
             if (mVariablePadding) {
                 return null;
             }
-            if (mConstantPadding != null) {
+            if (mConstantPadding != null || mPaddingChecked) {
                 return mConstantPadding;
             }
 
-            final Rect r = new Rect(0, 0, 0, 0);
+            Rect r = null;
             final Rect t = new Rect();
             final int N = getChildCount();
             final Drawable[] drawables = mDrawables;
             for (int i = 0; i < N; i++) {
                 if (drawables[i].getPadding(t)) {
+                    if (r == null) r = new Rect(0, 0, 0, 0);
                     if (t.left > r.left) r.left = t.left;
                     if (t.top > r.top) r.top = t.top;
                     if (t.right > r.right) r.right = t.right;
                     if (t.bottom > r.bottom) r.bottom = t.bottom;
                 }
             }
-            return (mConstantPadding=r);
+            mPaddingChecked = true;
+            return (mConstantPadding = r);
         }
 
         public final void setConstantSize(boolean constant) {
diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h
index 6628f75..03ac70a 100644
--- a/include/binder/MemoryDealer.h
+++ b/include/binder/MemoryDealer.h
@@ -218,8 +218,6 @@
             const sp<HeapInterface>& heap,
             const sp<AllocatorInterface>& allocator);
 
-    virtual ~MemoryDealer();
-
     virtual sp<IMemory> allocate(size_t size, uint32_t flags = 0);
     virtual void        deallocate(size_t offset);
     virtual void        dump(const char* what, uint32_t flags = 0) const;
@@ -228,6 +226,9 @@
     sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
     sp<AllocatorInterface> getAllocator() const { return allocator(); }
 
+protected:
+    virtual ~MemoryDealer();
+
 private:    
     const sp<HeapInterface>&        heap() const;
     const sp<AllocatorInterface>&   allocator() const;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 97d55aa..f723cfd 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -26,11 +26,10 @@
 
 #include <media/mediaplayer.h>
 #include <media/AudioSystem.h>
+#include <media/Metadata.h>
 
 namespace android {
 
-typedef int32_t MetadataType;
-
 class Parcel;
 template<typename T> class SortedVector;
 
@@ -129,8 +128,10 @@
     //            the known metadata should be returned.
     // @param[inout] records Parcel where the player appends its metadata.
     // @return OK if the call was successful.
-    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
-                                    Parcel *records) = 0;
+    virtual status_t    getMetadata(const media::Metadata::Filter& ids,
+                                    Parcel *records) {
+        return INVALID_OPERATION;
+    };
 
 protected:
     virtual void        sendEvent(int msg, int ext1=0, int ext2=0) { if (mNotify) mNotify(mCookie, msg, ext1, ext2); }
diff --git a/include/media/Metadata.h b/include/media/Metadata.h
new file mode 100644
index 0000000..241868a
--- /dev/null
+++ b/include/media/Metadata.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef ANDROID_MEDIA_METADATA_H__
+#define ANDROID_MEDIA_METADATA_H__
+
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+
+namespace android {
+class Parcel;
+
+namespace media {
+
+// Metadata is a class to build/serialize a set of metadata in a Parcel.
+//
+// This class should be kept in sync with android/media/Metadata.java.
+// It provides all the metadata ids available and methods to build the
+// header, add records and adjust the set size header field.
+//
+// Typical Usage:
+// ==============
+//  Parcel p;
+//  media::Metadata data(&p);
+//
+//  data.appendHeader();
+//  data.appendBool(Metadata::kPauseAvailable, true);
+//   ... more append ...
+//  data.updateLength();
+//
+
+class Metadata {
+  public:
+    typedef int32_t Type;
+    typedef SortedVector<Type> Filter;
+
+    static const Type kAny = 0;
+
+    // Keep in sync with android/media/Metadata.java
+    static const Type kTitle = 1;           // String
+    static const Type kComment = 2;         // String
+    static const Type kCopyright = 3;       // String
+    static const Type kAlbum = 4;           // String
+    static const Type kArtist = 5;          // String
+    static const Type kAuthor = 6;          // String
+    static const Type kComposer = 7;        // String
+    static const Type kGenre = 8;           // String
+    static const Type kDate = 9;            // Date
+    static const Type kDuration = 10;       // Integer(millisec)
+    static const Type kCdTrackNum = 11;     // Integer 1-based
+    static const Type kCdTrackMax = 12;     // Integer
+    static const Type kRating = 13;         // String
+    static const Type kAlbumArt = 14;       // byte[]
+    static const Type kVideoFrame = 15;     // Bitmap
+    static const Type kCaption = 16;        // TimedText
+
+    static const Type kBitRate = 17;       // Integer, Aggregate rate of
+    // all the streams in bps.
+
+    static const Type kAudioBitRate = 18; // Integer, bps
+    static const Type kVideoBitRate = 19; // Integer, bps
+    static const Type kAudioSampleRate = 20; // Integer, Hz
+    static const Type kVideoframeRate = 21;  // Integer, Hz
+
+    // See RFC2046 and RFC4281.
+    static const Type kMimeType = 22;      // String
+    static const Type kAudioCodec = 23;    // String
+    static const Type kVideoCodec = 24;    // String
+
+    static const Type kVideoHeight = 25;   // Integer
+    static const Type kVideoWidth = 26;    // Integer
+    static const Type kNumTracks = 27;     // Integer
+    static const Type kDrmCrippled = 28;   // Boolean
+
+    // Playback capabilities.
+    static const Type kPauseAvailable = 29;        // Boolean
+    static const Type kSeekBackwardAvailable = 30; // Boolean
+    static const Type kSeekForwardAvailable = 31;  // Boolean
+
+    // @param p[inout] The parcel to append the metadata records
+    // to. The global metadata header should have been set already.
+    explicit Metadata(Parcel *p);
+    ~Metadata();
+
+    // Rewind the underlying parcel, undoing all the changes.
+    void resetParcel();
+
+    // Append the size and 'META' marker.
+    bool appendHeader();
+
+    // Once all the records have been added, call this to update the
+    // lenght field in the header.
+    void updateLength();
+
+    // append* are methods to append metadata.
+    // @param key Is the metadata Id.
+    // @param val Is the value of the metadata.
+    // @return true if successful, false otherwise.
+    // TODO: add more as needed to handle other types.
+    bool appendBool(Type key, bool val);
+    bool appendInt32(Type key, int32_t val);
+
+  private:
+    Metadata(const Metadata&);
+    Metadata& operator=(const Metadata&);
+
+
+    // Checks the key is valid and not already present.
+    bool checkKey(Type key);
+
+    Parcel *mData;
+    size_t mBegin;
+};
+
+}  // namespace android::media
+}  // namespace android
+
+#endif  // ANDROID_MEDIA_METADATA_H__
diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h
index 40ccc14b..8a66152 100644
--- a/include/media/PVPlayer.h
+++ b/include/media/PVPlayer.h
@@ -19,6 +19,7 @@
 
 #include <utils/Errors.h>
 #include <media/MediaPlayerInterface.h>
+#include <media/Metadata.h>
 
 #define MAX_OPENCORE_INSTANCES 25
 
@@ -53,8 +54,9 @@
     virtual status_t    setLooping(int loop);
     virtual player_type playerType() { return PV_PLAYER; }
     virtual status_t    invoke(const Parcel& request, Parcel *reply);
-    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
-                                    Parcel *records);
+    virtual status_t    getMetadata(
+        const SortedVector<media::Metadata::Type>& ids,
+        Parcel *records);
 
     // make available to PlayerDriver
     void        sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); }
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 3819335..edd0cae6 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -826,6 +826,9 @@
     
     enum {
         DENSITY_DEFAULT = 0,
+        DENSITY_LOW = 120,
+        DENSITY_MEDIUM = 160,
+        DENSITY_HIGH = 240,
         DENSITY_NONE = 0xffff
     };
     
@@ -855,7 +858,6 @@
     
     enum {
         MASK_KEYSHIDDEN = 0x0003,
-        SHIFT_KEYSHIDDEN = 0,
         KEYSHIDDEN_ANY = 0x0000,
         KEYSHIDDEN_NO = 0x0001,
         KEYSHIDDEN_YES = 0x0002,
@@ -907,10 +909,18 @@
     };
     
     enum {
-        SCREENLAYOUT_ANY  = 0x0000,
-        SCREENLAYOUT_SMALL = 0x0001,
-        SCREENLAYOUT_NORMAL = 0x0002,
-        SCREENLAYOUT_LARGE = 0x0003,
+        // screenLayout bits for screen size class.
+        MASK_SCREENSIZE = 0x0f,
+        SCREENSIZE_ANY  = 0x00,
+        SCREENSIZE_SMALL = 0x01,
+        SCREENSIZE_NORMAL = 0x02,
+        SCREENSIZE_LARGE = 0x03,
+        
+        // screenLayout bits for wide/long screen variation.
+        MASK_SCREENLONG = 0x30,
+        SCREENLONG_ANY = 0x00,
+        SCREENLONG_NO = 0x10,
+        SCREENLONG_YES = 0x20,
     };
     
     union {
@@ -1040,6 +1050,17 @@
             }
         }
 
+        if (screenConfig || o.screenConfig) {
+            if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0) {
+                if (!(screenLayout & MASK_SCREENSIZE)) return false;
+                if (!(o.screenLayout & MASK_SCREENSIZE)) return true;
+            }
+            if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0) {
+                if (!(screenLayout & MASK_SCREENLONG)) return false;
+                if (!(o.screenLayout & MASK_SCREENLONG)) return true;
+            }
+        }
+
         if (screenType || o.screenType) {
             if (orientation != o.orientation) {
                 if (!orientation) return false;
@@ -1056,7 +1077,7 @@
         }
 
         if (input || o.input) {
-            if (inputFlags != o.inputFlags) {
+            if (((inputFlags^o.inputFlags) & MASK_KEYSHIDDEN) != 0) {
                 if (!(inputFlags & MASK_KEYSHIDDEN)) return false;
                 if (!(o.inputFlags & MASK_KEYSHIDDEN)) return true;
             }
@@ -1084,13 +1105,6 @@
             }
         }
 
-        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;
@@ -1139,6 +1153,17 @@
                 }
             }
 
+            if (screenConfig || o.screenConfig) {
+                if (((screenLayout^o.screenLayout) & MASK_SCREENSIZE) != 0
+                        && (requested->screenLayout & MASK_SCREENSIZE)) {
+                    return (screenLayout & MASK_SCREENSIZE);
+                }
+                if (((screenLayout^o.screenLayout) & MASK_SCREENLONG) != 0
+                        && (requested->screenLayout & MASK_SCREENLONG)) {
+                    return (screenLayout & MASK_SCREENLONG);
+                }
+            }
+
             if (screenType || o.screenType) {
                 if ((orientation != o.orientation) && requested->orientation) {
                     return (orientation);
@@ -1220,12 +1245,6 @@
                 }
             }
 
-            if (screenConfig || o.screenConfig) {
-                if ((screenLayout != o.screenLayout) && requested->screenLayout) {
-                    return (screenLayout);
-                }
-            }
-
             if (version || o.version) {
                 if ((sdkVersion != o.sdkVersion) && requested->sdkVersion) {
                     return (sdkVersion);
@@ -1273,6 +1292,21 @@
                 return false;
             }
         }
+        if (screenConfig != 0) {
+            const int screenSize = screenLayout&MASK_SCREENSIZE;
+            const int setScreenSize = settings.screenLayout&MASK_SCREENSIZE;
+            if (setScreenSize != 0 && screenSize != 0
+                    && screenSize != setScreenSize) {
+                return false;
+            }
+            
+            const int screenLong = screenLayout&MASK_SCREENLONG;
+            const int setScreenLong = settings.screenLayout&MASK_SCREENLONG;
+            if (setScreenLong != 0 && screenLong != 0
+                    && screenLong != setScreenLong) {
+                return false;
+            }
+        }
         if (screenType != 0) {
             if (settings.orientation != 0 && orientation != 0
                 && orientation != settings.orientation) {
@@ -1317,12 +1351,6 @@
                 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) {
@@ -1352,12 +1380,14 @@
     String8 toString() const {
         char buf[200];
         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",
+                "kbd=%d nav=%d input=%d scrnW=%d scrnH=%d sz=%d long=%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, screenLayout, sdkVersion, minorVersion);
+                screenWidth, screenHeight,
+                screenLayout&MASK_SCREENSIZE, screenLayout&MASK_SCREENLONG,
+                sdkVersion, minorVersion);
         return String8(buf);
     }
 };
diff --git a/keystore/java/android/security/CertTool.java b/keystore/java/android/security/CertTool.java
index c96cd4f..79418bd 100644
--- a/keystore/java/android/security/CertTool.java
+++ b/keystore/java/android/security/CertTool.java
@@ -53,6 +53,7 @@
     public static final String TITLE_USER_CERT = "User Certificate";
     public static final String TITLE_PKCS12_KEYSTORE = "PKCS12 Keystore";
     public static final String TITLE_PRIVATE_KEY = "Private Key";
+    public static final int INCORRECT_PKCS12_PASSPHRASE = -100;
 
     private static final String TAG = "CertTool";
     private static final String UNKNOWN = "Unknown";
@@ -143,30 +144,47 @@
         intent.putExtra(KEY_NAMESPACE + "1", namespace);
     }
 
-    public int addPkcs12Keystore(byte[] p12Data, String password,
-            String keyname) {
-        int handle, i = 0;
+    private int extractAndStoreKeysFromPkcs12(int handle, String keyname) {
+        int ret, i = 0;
         String pemData;
-        Log.i("CertTool", "addPkcs12Keystore()");
 
-        if ((handle = getPkcs12Handle(p12Data, password)) == 0) return -1;
         if ((pemData = getPkcs12Certificate(handle)) != null) {
-            sKeystore.put(USER_CERTIFICATE, keyname, pemData);
+            if ((ret = sKeystore.put(USER_CERTIFICATE, keyname, pemData)) != 0) {
+                return ret;
+            }
         }
         if ((pemData = getPkcs12PrivateKey(handle)) != null) {
-            sKeystore.put(USER_KEY, keyname, pemData);
+            if ((ret = sKeystore.put(USER_KEY, keyname, pemData)) != 0) {
+                return ret;
+            }
         }
         while ((pemData = this.popPkcs12CertificateStack(handle)) != null) {
             if (i++ > 0) {
-                sKeystore.put(CA_CERTIFICATE, keyname + i, pemData);
+                if ((ret = sKeystore.put(CA_CERTIFICATE, keyname + i, pemData)) != 0) {
+                    return ret;
+                }
             } else {
-                sKeystore.put(CA_CERTIFICATE, keyname, pemData);
+                if ((ret = sKeystore.put(CA_CERTIFICATE, keyname, pemData)) != 0) {
+                    return ret;
+                }
             }
         }
-        freePkcs12Handle(handle);
         return 0;
     }
 
+    public int addPkcs12Keystore(byte[] p12Data, String password,
+            String keyname) {
+        int handle, ret;
+        Log.i("CertTool", "addPkcs12Keystore()");
+
+        if ((handle = getPkcs12Handle(p12Data, password)) == 0) {
+            return INCORRECT_PKCS12_PASSPHRASE;
+        }
+        ret = extractAndStoreKeysFromPkcs12(handle, keyname);
+        freePkcs12Handle(handle);
+        return ret;
+    }
+
     public synchronized void addCertificate(byte[] data, Context context) {
         int handle;
         Intent intent = null;
diff --git a/keystore/java/android/security/Keystore.java b/keystore/java/android/security/Keystore.java
index 1f14da7..a6cfbca 100644
--- a/keystore/java/android/security/Keystore.java
+++ b/keystore/java/android/security/Keystore.java
@@ -48,49 +48,6 @@
     public abstract int remove(String namespace, String keyname);
     public abstract int reset();
 
-    // TODO: for migrating to the mini-keystore, clean up from here
-    /**
-     */
-    public abstract String getCaCertificate(String key);
-
-    /**
-     */
-    public abstract String getUserCertificate(String key);
-
-    /**
-     */
-    public abstract String getUserPrivateKey(String key);
-
-    /**
-     * Returns the array of the certificate keynames in keystore if successful.
-     * Or return an empty array if error.
-     *
-     * @return array of the certificate keynames
-     */
-    public abstract String[] getAllUserCertificateKeys();
-
-    /**
-     */
-    public abstract String[] getAllCaCertificateKeys();
-
-    /**
-     */
-    public abstract String[] getSupportedKeyStrenghs();
-
-    /**
-     * Generates a key pair and returns the certificate request.
-     * @param keyStrengthIndex index to the array of supported key strengths
-     * @param challenge the challenge message in the keygen tag
-     * @param organizations the organization string, e.g.,
-     *      "/C=US/ST={state}/L={city}/O={company}/OU={app}/CN={hostname}"
-     * @return the certificate request
-     */
-    public abstract String generateKeyPair(
-            int keyStrengthIndex, String challenge, String organizations);
-
-    public abstract void addCertificate(byte[] cert);
-    // to here
-
     private static class FileKeystore extends Keystore {
         private static final String SERVICE_NAME = "keystore";
         private static final String CA_CERTIFICATE = "CaCertificate";
@@ -100,69 +57,6 @@
         private static final ServiceCommand mServiceCommand =
                 new ServiceCommand(SERVICE_NAME);
 
-        // TODO: for migrating to the mini-keystore, start from here
-        @Override
-        public String getUserPrivateKey(String key) {
-            return "";
-        }
-
-        @Override
-        public String getUserCertificate(String key) {
-            return "";
-        }
-
-        @Override
-        public String getCaCertificate(String key) {
-            return "";
-        }
-
-        @Override
-        public String[] getAllUserCertificateKeys() {
-            return new String[0];
-        }
-
-        @Override
-        public String[] getAllCaCertificateKeys() {
-          return new String[0];
-        }
-
-        @Override
-        public String[] getSupportedKeyStrenghs() {
-            // TODO: real implementation
-            return new String[] {"High Grade", "Medium Grade"};
-        }
-
-        @Override
-        public String generateKeyPair(int keyStrengthIndex, String challenge,
-                String organizations) {
-            // TODO: real implementation
-            return "-----BEGIN CERTIFICATE REQUEST-----"
-                    + "\nMIICzjCCAbYCAQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh"
-                    + "\nMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRYw"
-                    + "\nFAYDVQQLEw1SZW1vdGUgQWNjZXNzMRAwDgYDVQQLEwdHbGFwdG9wMQ0wCwYDVQQD"
-                    + "\nEwR0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAznwy7a16O35u"
-                    + "\nODLQOw6yHAxozrrX1J+c0reiIh8GYohwKrBedFnQ/FnTls6bxY4fNHD+SZvFFgvU"
-                    + "\nECBFOfRmRm7AFo51qT0t2a8qgvDLM6L1qGkmy94W28Q3OlcpF2QianHYdjyGT+Ac"
-                    + "\nYDek1Zi/E/mdPzuVM/K8tkB7n8ktC0PTm1ZtdMRauE5R0WrEhWuF6In/2gy1Q/Zh"
-                    + "\noy7/zQqpbPl2ouulvkx1Y3OXHM6XPNFLoHS1gH0HyAuBUokO0QmetRn6ngJSvz7e"
-                    + "\nVD7QYRppGp+g4BxqaV9XSxhaaKrMs4PAld9enV51X9qjvjCRBve2QxtuJgMfGJdU"
-                    + "\njGr/JweZoQIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBADtxOtEseoLOVYh6sh4b"
-                    + "\nWCdngK87uHn2bdGipFwKdNTxQDdxNQLAKdoGYIfbVsC1cDgFiufeNwVukxxymdnm"
-                    + "\nk0GGK+0O0tZKENv8ysgfbgEsHpJH9FoR5Y5XEq1etejkcgCp59dyhrSk0DLyVm0D"
-                    + "\nIfTC/nsK95H7AAGOkbbDFo2otyLNNrthYncQ9diAG0UzzLacA+86JXZmD3HyC48u"
-                    + "\nI9hsivVnTTfl9afcfVAhfxbQ6HgkhZZjbjFjfABSd4v8wKlAAqK58VxCajNVOVcV"
-                    + "\ncCzOWf6NpE7xEHCf32i8bWDP6hi0WgQcdpQwnZNKhhTLGNb23Uty6HYlJhbxexC7"
-                    + "\nUoM="
-                    + "\n-----END CERTIFICATE REQUEST-----";
-        }
-
-        @Override
-        public void addCertificate(byte[] cert) {
-            // TODO: real implementation
-        }
-
-        // to here
-
         @Override
         public int lock() {
             Reply result = mServiceCommand.execute(ServiceCommand.LOCK, null);
diff --git a/libs/rs/java/Film/res/raw/filmstrip.c b/libs/rs/java/Film/res/raw/filmstrip.c
index 863b930..6885251 100644
--- a/libs/rs/java/Film/res/raw/filmstrip.c
+++ b/libs/rs/java/Film/res/raw/filmstrip.c
@@ -1,7 +1,7 @@
 // Fountain test script
 
 #pragma version(1)
-#pragma stateVertex(PV)
+#pragma stateVertex(PVBackground)
 #pragma stateFragment(PFBackground)
 #pragma stateFragmentStore(PFSBackground)
 
@@ -43,8 +43,6 @@
     //materialDiffuse(con, 0.0f, 0.0f, 0.0f, 1.0f);
     //materialSpecular(con, 0.5f, 0.5f, 0.5f, 0.5f);
     //materialShininess(intToFloat(20));
-    //lightPosition(con, 0.2f, -0.2f, -2.0f, 0.0f);
-    //enable(con, GL_LIGHTING);
     drawTriangleMesh(NAMED_mesh);
 
 
@@ -53,6 +51,7 @@
 
     bindProgramFragmentStore(NAMED_PFImages);
     bindProgramFragment(NAMED_PFSImages);
+    bindProgramVertex(NAMED_PVImages);
 
     //focusPos = loadF(1, 2);
     //focusID = 0;
diff --git a/libs/rs/java/Film/src/com/android/film/FilmRS.java b/libs/rs/java/Film/src/com/android/film/FilmRS.java
index 2711bf0..fca0818 100644
--- a/libs/rs/java/Film/src/com/android/film/FilmRS.java
+++ b/libs/rs/java/Film/src/com/android/film/FilmRS.java
@@ -45,7 +45,6 @@
     public void init(RenderScript rs, Resources res, int width, int height) {
         mRS = rs;
         mRes = res;
-        initNamed();
         initRS();
     }
 
@@ -77,7 +76,8 @@
     private RenderScript.ProgramFragmentStore mPFSImages;
     private RenderScript.ProgramFragment mPFBackground;
     private RenderScript.ProgramFragment mPFImages;
-    private RenderScript.ProgramVertex mPV;
+    private RenderScript.ProgramVertex mPVBackground;
+    private RenderScript.ProgramVertex mPVImages;
     private ProgramVertexAlloc mPVA;
 
     private RenderScript.Allocation mAllocEnv;
@@ -90,20 +90,7 @@
     private float[] mBufferPos;
     private float[] mBufferPV;
 
-    private void initNamed() {
-        mElementVertex = mRS.elementGetPredefined(
-            RenderScript.ElementPredefined.NORM_ST_XYZ_F32);
-        mElementIndex = mRS.elementGetPredefined(
-            RenderScript.ElementPredefined.INDEX_16);
-
-        mRS.triangleMeshBegin(mElementVertex, mElementIndex);
-        FilmStripMesh fsm = new FilmStripMesh();
-        fsm.init(mRS);
-        mMesh = mRS.triangleMeshCreate();
-        mMesh.setName("mesh");
-        Log.e("rs", "Done loading strips");
-
-
+    private void initSamplers() {
         mRS.samplerBegin();
         mRS.samplerSet(RenderScript.SamplerParam.FILTER_MIN,
                        RenderScript.SamplerValue.LINEAR_MIP_LINEAR);
@@ -112,19 +99,9 @@
         mRS.samplerSet(RenderScript.SamplerParam.WRAP_MODE_T,
                        RenderScript.SamplerValue.CLAMP);
         mSampler = mRS.samplerCreate();
+    }
 
-        mRS.programFragmentBegin(null, null);
-        mPFBackground = mRS.programFragmentCreate();
-        mPFBackground.setName("PFBackground");
-
-        mRS.programFragmentBegin(null, null);
-        mRS.programFragmentSetTexEnable(0, true);
-        //mRS.programFragmentSetEnvMode(0, RS_TEX_ENV_MODE_REPLACE);
-        //rsProgramFragmentSetType(0, gEnv.tex[0]->getType());
-        mPFImages = mRS.programFragmentCreate();
-        mPFImages.setName("PFImages");
-        mPFImages.bindSampler(mSampler, 0);
-
+    private void initPFS() {
         mRS.programFragmentStoreBegin(null, null);
         mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.LESS);
         mRS.programFragmentStoreDitherEnable(true);
@@ -139,26 +116,59 @@
                                           RenderScript.BlendDstFunc.ONE);
         mPFSImages = mRS.programFragmentStoreCreate();
         mPFSImages.setName("PFSImages");
+    }
 
-        mRS.programVertexBegin(null, null);
-        mRS.programVertexSetTextureMatrixEnable(true);
-        mPV = mRS.programVertexCreate();
-        mPV.setName("PV");
+    private void initPF() {
+        mRS.programFragmentBegin(null, null);
+        mPFBackground = mRS.programFragmentCreate();
+        mPFBackground.setName("PFBackground");
 
+        mRS.programFragmentBegin(null, null);
+        mRS.programFragmentSetTexEnable(0, true);
+        //mRS.programFragmentSetEnvMode(0, RS_TEX_ENV_MODE_REPLACE);
+        //rsProgramFragmentSetType(0, gEnv.tex[0]->getType());
+        mPFImages = mRS.programFragmentCreate();
+        mPFImages.setName("PFImages");
+    }
+
+    private void initPV() {
         mRS.lightBegin();
         mLight = mRS.lightCreate();
         mLight.setPosition(0, -0.5f, -1.0f);
 
-        Log.e("rs", "Done loading named");
+        mRS.programVertexBegin(null, null);
+        mRS.programVertexSetTextureMatrixEnable(true);
+        mRS.programVertexAddLight(mLight);
+        mPVBackground = mRS.programVertexCreate();
+        mPVBackground.setName("PVBackground");
+
+        mRS.programVertexBegin(null, null);
+        mPVImages = mRS.programVertexCreate();
+        mPVImages.setName("PVImages");
     }
 
 
-    private Bitmap mBackground;
-
     int mParams[] = new int[10];
 
     private void initRS() {
-        int partCount = 1024;
+        mElementVertex = mRS.elementGetPredefined(
+            RenderScript.ElementPredefined.NORM_ST_XYZ_F32);
+        mElementIndex = mRS.elementGetPredefined(
+            RenderScript.ElementPredefined.INDEX_16);
+
+        mRS.triangleMeshBegin(mElementVertex, mElementIndex);
+        FilmStripMesh fsm = new FilmStripMesh();
+        fsm.init(mRS);
+        mMesh = mRS.triangleMeshCreate();
+        mMesh.setName("mesh");
+
+        initPFS();
+        initSamplers();
+        initPF();
+        initPV();
+        mPFImages.bindSampler(mSampler, 0);
+
+        Log.e("rs", "Done loading named");
 
         mRS.scriptCBegin();
         mRS.scriptCSetClearColor(0.0f, 0.0f, 0.0f, 1.0f);
@@ -172,7 +182,8 @@
             mBufferPos.length);
 
         mPVA = new ProgramVertexAlloc(mRS);
-        mPV.bindAllocation(0, mPVA.mAlloc);
+        mPVBackground.bindAllocation(0, mPVA.mAlloc);
+        mPVImages.bindAllocation(0, mPVA.mAlloc);
         mPVA.setupProjectionNormalized(320, 480);
 
 
@@ -181,10 +192,6 @@
         mScriptStrip.bindAllocation(mPVA.mAlloc, 3);
 
 
-        //mIntAlloc = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, 10);
-        //mPartAlloc = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, partCount * 3 * 3);
-        //mPartAlloc.setName("PartBuffer");
-        //mVertAlloc = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, partCount * 5 + 1);
 /*
         {
             Resources res = getResources();
@@ -203,25 +210,6 @@
         mPFS = mRS.programFragmentStoreCreate();
         mPFS.setName("MyBlend");
         mRS.contextBindProgramFragmentStore(mPFS);
-
-        mRS.samplerBegin();
-        mRS.samplerSet(RenderScript.SamplerParam.FILTER_MAG, RenderScript.SamplerValue.LINEAR);
-        mRS.samplerSet(RenderScript.SamplerParam.FILTER_MIN, RenderScript.SamplerValue.LINEAR);
-        mSampler = mRS.samplerCreate();
-
-
-        mParams[0] = 0;
-        mParams[1] = partCount;
-        mParams[2] = 0;
-        mParams[3] = 0;
-        mParams[4] = 0;
-        mIntAlloc.data(mParams);
-
-        int t2[] = new int[partCount * 4*3];
-        for (int ct=0; ct < t2.length; ct++) {
-            t2[ct] = 0;
-        }
-        mPartAlloc.data(t2);
         */
 
         setFilmStripPosition(0, 0);
diff --git a/libs/rs/java/RenderScript/android/renderscript/RenderScript.java b/libs/rs/java/RenderScript/android/renderscript/RenderScript.java
index 733009e..e355635 100644
--- a/libs/rs/java/RenderScript/android/renderscript/RenderScript.java
+++ b/libs/rs/java/RenderScript/android/renderscript/RenderScript.java
@@ -156,6 +156,7 @@
     native private void nProgramVertexBegin(int inID, int outID);
     native private void nProgramVertexSetType(int slot, int mID);
     native private void nProgramVertexSetTextureMatrixEnable(boolean enable);
+    native private void nProgramVertexAddLight(int id);
     native private int  nProgramVertexCreate();
 
     native private void nLightBegin();
@@ -720,7 +721,6 @@
         public void bindAllocation(int slot, Allocation va) {
             nProgramVertexBindAllocation(mID, slot, va.mID);
         }
-
     }
 
     public void programVertexBegin(Element in, Element out) {
@@ -743,6 +743,10 @@
         nProgramVertexSetTextureMatrixEnable(enable);
     }
 
+    public void programVertexAddLight(Light l) {
+        nProgramVertexAddLight(l.mID);
+    }
+
     public ProgramVertex programVertexCreate() {
         int id = nProgramVertexCreate();
         return new ProgramVertex(id);
diff --git a/libs/rs/jni/RenderScript_jni.cpp b/libs/rs/jni/RenderScript_jni.cpp
index 248a6bd..1747673 100644
--- a/libs/rs/jni/RenderScript_jni.cpp
+++ b/libs/rs/jni/RenderScript_jni.cpp
@@ -810,6 +810,14 @@
     rsProgramVertexSetTextureMatrixEnable(enable);
 }
 
+static void
+nProgramVertexAddLight(JNIEnv *_env, jobject _this, jint light)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramVertexAddLight, con(%p), light(%p)", con, (RsLight)light);
+    rsProgramVertexAddLight((RsLight)light);
+}
+
 static jint
 nProgramVertexCreate(JNIEnv *_env, jobject _this)
 {
@@ -1048,6 +1056,7 @@
 {"nProgramVertexBegin",            "(II)V",                                (void*)nProgramVertexBegin },
 {"nProgramVertexSetType",          "(II)V",                                (void*)nProgramVertexSetType },
 {"nProgramVertexSetTextureMatrixEnable",   "(Z)V",                         (void*)nProgramVertexSetTextureMatrixEnable },
+{"nProgramVertexAddLight",         "(I)V",                                 (void*)nProgramVertexAddLight },
 {"nProgramVertexCreate",           "()I",                                  (void*)nProgramVertexCreate },
 
 {"nLightBegin",                    "()V",                                  (void*)nLightBegin },
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 62533af..2f99808 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -403,6 +403,10 @@
 	param bool enable
 	}
 
+ProgramVertexAddLight {
+	param RsLight light
+	}
+
 LightBegin {
 	}
 
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 442a920..497dbcf 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -32,10 +32,10 @@
 #include "rsAllocation.h"
 #include "rsAdapter.h"
 #include "rsSampler.h"
+#include "rsLight.h"
 #include "rsProgramFragment.h"
 #include "rsProgramFragmentStore.h"
 #include "rsProgramVertex.h"
-#include "rsLight.h"
 
 #include "rsgApiStructs.h"
 #include "rsLocklessFifo.h"
diff --git a/libs/rs/rsLight.cpp b/libs/rs/rsLight.cpp
index 67d0095..24b58b6 100644
--- a/libs/rs/rsLight.cpp
+++ b/libs/rs/rsLight.cpp
@@ -16,6 +16,8 @@
 
 #include "rsContext.h"
 
+#include <GLES/gl.h>
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -25,13 +27,15 @@
     mIsLocal = isLocal;
     mIsMono = isMono;
 
-    mX = 0;
-    mY = 0;
-    mZ = 0;
+    mPosition[0] = 0;
+    mPosition[1] = 0;
+    mPosition[2] = 1;
+    mPosition[3] = 0;
 
-    mR = 1.f;
-    mG = 1.f;
-    mB = 1.f;
+    mColor[0] = 1.f;
+    mColor[1] = 1.f;
+    mColor[2] = 1.f;
+    mColor[3] = 1.f;
 }
 
 Light::~Light()
@@ -40,16 +44,23 @@
 
 void Light::setPosition(float x, float y, float z)
 {
-    mX = x;
-    mY = y;
-    mZ = z;
+    mPosition[0] = x;
+    mPosition[1] = y;
+    mPosition[2] = z;
 }
 
 void Light::setColor(float r, float g, float b)
 {
-    mR = r;
-    mG = g;
-    mB = b;
+    mColor[0] = r;
+    mColor[1] = g;
+    mColor[2] = b;
+}
+
+void Light::setupGL(uint32_t num) const
+{
+    glLightfv(GL_LIGHT0 + num, GL_DIFFUSE, mColor);
+    glLightfv(GL_LIGHT0 + num, GL_SPECULAR, mColor);
+    glLightfv(GL_LIGHT0 + num, GL_POSITION, mPosition);
 }
 
 ////////////////////////////////////////////
diff --git a/libs/rs/rsLight.h b/libs/rs/rsLight.h
index 76d1ecc..b0c3386 100644
--- a/libs/rs/rsLight.h
+++ b/libs/rs/rsLight.h
@@ -36,9 +36,11 @@
     void setPosition(float x, float y, float z);
     void setColor(float r, float g, float b);
 
+    void setupGL(uint32_t num) const;
+
 protected:
-    float mR, mG, mB;
-    float mX, mY, mZ;
+    float mColor[4];
+    float mPosition[4];
     bool mIsLocal;
     bool mIsMono;
 };
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 4089507..417ba6a 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -28,6 +28,7 @@
     Program(in, out)
 {
     mTextureMatrixEnable = false;
+    mLightCount = 0;
 }
 
 ProgramVertex::~ProgramVertex()
@@ -54,8 +55,29 @@
         glLoadIdentity();
     }
 
-    //logMatrix("prog", &f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
-    //logMatrix("model", &f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]);
+
+    LOGE("lights %i ", mLightCount);
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    if (mLightCount) {
+        int v = 1;
+        glEnable(GL_LIGHTING);
+        glLightModelxv(GL_LIGHT_MODEL_TWO_SIDE, &v);
+        for (uint32_t ct = 0; ct < mLightCount; ct++) {
+            const Light *l = mLights[ct].get();
+            glEnable(GL_LIGHT0 + ct);
+            l->setupGL(ct);
+        }
+        for (uint32_t ct = mLightCount; ct < MAX_LIGHTS; ct++) {
+            glDisable(GL_LIGHT0 + ct);
+        }
+    } else {
+        glDisable(GL_LIGHTING);
+    }
+    
+    if (!f) {
+        LOGE("Must bind constants to vertex program");
+    }
 
     glMatrixMode(GL_PROJECTION);
     glLoadMatrixf(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
@@ -73,6 +95,14 @@
     mConstants[slot].set(a);
 }
 
+void ProgramVertex::addLight(const Light *l)
+{
+    if (mLightCount < MAX_LIGHTS) {
+        mLights[mLightCount].set(l);
+        mLightCount++;
+    }
+}
+
 
 ProgramVertexState::ProgramVertexState()
 {
@@ -136,6 +166,10 @@
     rsc->mStateVertex.mPV->setTextureMatrixEnable(enable);
 }
 
+void rsi_ProgramVertexAddLight(Context *rsc, RsLight light)
+{
+    rsc->mStateVertex.mPV->addLight(static_cast<const Light *>(light));
+}
 
 
 }
diff --git a/libs/rs/rsProgramVertex.h b/libs/rs/rsProgramVertex.h
index 1a92f01..ac15b70 100644
--- a/libs/rs/rsProgramVertex.h
+++ b/libs/rs/rsProgramVertex.h
@@ -28,6 +28,7 @@
 {
 public:
     const static uint32_t MAX_CONSTANTS = 2;
+    const static uint32_t MAX_LIGHTS = 8;
 
     ProgramVertex(Element *in, Element *out);
     virtual ~ProgramVertex();
@@ -38,12 +39,16 @@
     void setConstantType(uint32_t slot, const Type *);
     void bindAllocation(uint32_t slot, Allocation *);
     void setTextureMatrixEnable(bool e) {mTextureMatrixEnable = e;}
+    void addLight(const Light *);
 
 protected:
     bool mDirty;
+    uint32_t mLightCount;
 
     ObjectBaseRef<Allocation> mConstants[MAX_CONSTANTS];
     ObjectBaseRef<const Type> mConstantTypes[MAX_CONSTANTS];
+    ObjectBaseRef<const Light> mLights[MAX_LIGHTS];
+
 
     // Hacks to create a program for now
     bool mTextureMatrixEnable;
@@ -61,6 +66,8 @@
 
     ObjectBaseRef<ProgramVertex> mDefault;
     ObjectBaseRef<Allocation> mDefaultAlloc;
+    
+
 
     ProgramVertex *mPV;
 
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index e0928c3..842c836 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -103,14 +103,10 @@
 static ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) 
 {
     const ScriptCState::SymbolTable_t *sym = ScriptCState::lookupSymbol(name);
-
     if (sym) {
         return sym->mPtr;
     }
-
     LOGE("ScriptC sym lookup failed for %s", name);
-
-    // Default to calling dlsym to allow any global symbol:
     return NULL;
 }
 
@@ -121,7 +117,7 @@
 
     rsc->appendNameDefines(&tmp);
     appendDecls(&tmp);
-    //tmp.append("#line 1\n");
+    tmp.append("#line 1\n");
 
     const char* scriptSource[] = {tmp.string(), mProgram.mScriptText};
     int scriptLength[] = {tmp.length(), mProgram.mScriptTextLength} ;
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 59d8e5f..129b19f 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -249,6 +249,12 @@
 
 }
 
+static void SC_bindProgramVertex(RsProgramVertex pv)
+{
+    GET_TLS();
+    rsi_ContextBindProgramVertex(rsc, pv);
+
+}
 
 //////////////////////////////////////////////////////////////////////////////
 // Drawing
@@ -468,6 +474,8 @@
         "void", "(int)" },
     { "bindProgramFragmentStore", (void *)&SC_bindProgramFragmentStore,
         "void", "(int)" },
+    { "bindProgramVertex", (void *)&SC_bindProgramVertex,
+        "void", "(int)" },
     { "bindSampler", (void *)&SC_bindSampler,
         "void", "(int, int, int)" },
     { "bindTexture", (void *)&SC_bindTexture,
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 98d450b..4dca8bd 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -4012,11 +4012,11 @@
                     if (dval == ResTable_config::DENSITY_DEFAULT) {
                         strcpy(density, "def");
                     } else if (dval == ResTable_config::DENSITY_NONE) {
-                        strcpy(density, "non");
+                        strcpy(density, "no");
                     } else {
                         sprintf(density, "%d", (int)dval);
                     }
-                    printf("      config %d lang=%c%c cnt=%c%c orien=%d touch=%d density=%s key=%d infl=%d nav=%d w=%d h=%d lyt=%d\n",
+                    printf("      config %d lang=%c%c cnt=%c%c orien=%d touch=%d density=%s key=%d infl=%d nav=%d w=%d h=%d sz=%d lng=%d\n",
                            (int)configIndex,
                            type->config.language[0] ? type->config.language[0] : '-',
                            type->config.language[1] ? type->config.language[1] : '-',
@@ -4030,7 +4030,8 @@
                            type->config.navigation,
                            dtohs(type->config.screenWidth),
                            dtohs(type->config.screenHeight),
-                           type->config.screenLayout);
+                           type->config.screenLayout&ResTable_config::MASK_SCREENSIZE,
+                           type->config.screenLayout&ResTable_config::MASK_SCREENLONG);
                     size_t entryCount = dtohl(type->entryCount);
                     uint32_t entriesStart = dtohl(type->entriesStart);
                     if ((entriesStart&0x3) != 0) {
diff --git a/media/java/android/media/Metadata.java b/media/java/android/media/Metadata.java
index 70e89a2..bd25da2 100644
--- a/media/java/android/media/Metadata.java
+++ b/media/java/android/media/Metadata.java
@@ -104,7 +104,7 @@
     public static final int SEEK_FORWARD_AVAILABLE = 31;  // Boolean
 
     private static final int LAST_SYSTEM = 31;
-    private static final int FIRST_CUSTOM = 8092;
+    private static final int FIRST_CUSTOM = 8192;
 
     // Shorthands to set the MediaPlayer's metadata filter.
     public static final Set<Integer> MATCH_NONE = Collections.EMPTY_SET;
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index ce80f92..1fdecdd 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -18,8 +18,7 @@
 #define LOG_TAG "SoundPool"
 #include <utils/Log.h>
 
-//
-#define USE_SHARED_MEM_BUFFER
+//#define USE_SHARED_MEM_BUFFER
 
 // XXX needed for timing latency
 #include <utils/Timers.h>
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index cdaab04..07c81f7 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -2,24 +2,25 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	AudioTrack.cpp \
-	IAudioFlinger.cpp \
-	IAudioFlingerClient.cpp \
-	IAudioTrack.cpp \
-	IAudioRecord.cpp \
-	AudioRecord.cpp \
-	AudioSystem.cpp \
-	mediaplayer.cpp \
-	IMediaPlayerService.cpp \
-	IMediaPlayerClient.cpp \
-	IMediaPlayer.cpp \
-	IMediaRecorder.cpp \
-	mediarecorder.cpp \
-	IMediaMetadataRetriever.cpp \
-	mediametadataretriever.cpp \
-	ToneGenerator.cpp \
-	JetPlayer.cpp \
-        IOMX.cpp
+    AudioTrack.cpp \
+    IAudioFlinger.cpp \
+    IAudioFlingerClient.cpp \
+    IAudioTrack.cpp \
+    IAudioRecord.cpp \
+    AudioRecord.cpp \
+    AudioSystem.cpp \
+    mediaplayer.cpp \
+    IMediaPlayerService.cpp \
+    IMediaPlayerClient.cpp \
+    IMediaPlayer.cpp \
+    IMediaRecorder.cpp \
+    Metadata.cpp \
+    mediarecorder.cpp \
+    IMediaMetadataRetriever.cpp \
+    mediametadataretriever.cpp \
+    ToneGenerator.cpp \
+    JetPlayer.cpp \
+    IOMX.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox
diff --git a/media/libmedia/Metadata.cpp b/media/libmedia/Metadata.cpp
new file mode 100644
index 0000000..35ec6b3
--- /dev/null
+++ b/media/libmedia/Metadata.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Metadata"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <media/Metadata.h>
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+// This file contains code to serialize Metadata triples (key, type,
+// value) into a parcel. The Parcel is destinated to be decoded by the
+// Metadata.java class.
+
+namespace {
+// All these constants below must be kept in sync with Metadata.java.
+enum MetadataId {
+    FIRST_SYSTEM_ID = 1,
+    LAST_SYSTEM_ID = 31,
+    FIRST_CUSTOM_ID = 8192
+};
+
+// Types
+enum Types {
+    STRING_VAL = 1,
+    INTEGER_VAL,
+    BOOLEAN_VAL,
+    LONG_VAL,
+    DOUBLE_VAL,
+    TIMED_TEXT_VAL,
+    DATE_VAL,
+    BYTE_ARRAY_VAL,
+};
+
+const size_t kRecordHeaderSize = 3 * sizeof(int32_t);
+const int32_t kMetaMarker = 0x4d455441;  // 'M' 'E' 'T' 'A'
+
+}  // anonymous namespace
+
+namespace android {
+namespace media {
+
+Metadata::Metadata(Parcel *p)
+    :mData(p),
+     mBegin(p->dataPosition()) { }
+
+Metadata::~Metadata() { }
+
+void Metadata::resetParcel()
+{
+    mData->setDataPosition(mBegin);
+}
+
+// Update the 4 bytes int at the beginning of the parcel which holds
+// the number of bytes written so far.
+void Metadata::updateLength()
+{
+    const size_t end = mData->dataPosition();
+
+    mData->setDataPosition(mBegin);
+    mData->writeInt32(end - mBegin);
+    mData->setDataPosition(end);
+}
+
+// Write the header. The java layer will look for the marker.
+bool Metadata::appendHeader()
+{
+    bool ok = true;
+
+    // Placeholder for the length of the metadata
+    ok = ok && mData->writeInt32(-1) == OK;
+    ok = ok && mData->writeInt32(kMetaMarker) == OK;
+    return ok;
+}
+
+bool Metadata::appendBool(int key, bool val)
+{
+    if (!checkKey(key)) {
+        return false;
+    }
+
+    const size_t begin = mData->dataPosition();
+    bool ok = true;
+
+    // 4 int32s: size, key, type, value.
+    ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
+    ok = ok && mData->writeInt32(key) == OK;
+    ok = ok && mData->writeInt32(BOOLEAN_VAL) == OK;
+    ok = ok && mData->writeInt32(val ? 1 : 0) == OK;
+    if (!ok) {
+        mData->setDataPosition(begin);
+    }
+    return ok;
+}
+
+bool Metadata::appendInt32(int key, int32_t val)
+{
+    if (!checkKey(key)) {
+        return false;
+    }
+
+    const size_t begin = mData->dataPosition();
+    bool ok = true;
+
+    // 4 int32s: size, key, type, value.
+    ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
+    ok = ok && mData->writeInt32(key) == OK;
+    ok = ok && mData->writeInt32(INTEGER_VAL) == OK;
+    ok = ok && mData->writeInt32(val) == OK;
+    if (!ok) {
+        mData->setDataPosition(begin);
+    }
+    return ok;
+}
+
+// Check the key (i.e metadata id) is valid if it is a system one.
+// Loop over all the exiting ones in the Parcel to check for duplicate
+// (not allowed).
+bool Metadata::checkKey(int key)
+{
+    if (key < FIRST_SYSTEM_ID ||
+        (LAST_SYSTEM_ID < key && key < FIRST_CUSTOM_ID)) {
+        LOGE("Bad key %d", key);
+        return false;
+    }
+    size_t curr = mData->dataPosition();
+    // Loop over the keys to check if it has been used already.
+    mData->setDataPosition(mBegin);
+
+    bool error = false;
+    size_t left = curr - mBegin;
+    while (left > 0) {
+        size_t pos = mData->dataPosition();
+        size_t size = mData->readInt32();
+        if (size < kRecordHeaderSize || size > left) {
+            error = true;
+            break;
+        }
+        if (mData->readInt32() == key) {
+            LOGE("Key exists already %d", key);
+            error = true;
+            break;
+        }
+        mData->setDataPosition(pos + size);
+        left -= size;
+    }
+    mData->setDataPosition(curr);
+    return !error;
+}
+
+}  // namespace android::media
+}  // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 5e62f9d..77f7434 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -47,10 +47,9 @@
 #include <media/MediaPlayerInterface.h>
 #include <media/mediarecorder.h>
 #include <media/MediaMetadataRetrieverInterface.h>
+#include <media/Metadata.h>
 #include <media/AudioTrack.h>
 
-#include <utils/SortedVector.h>
-
 #include "MediaRecorderClient.h"
 #include "MediaPlayerService.h"
 #include "MetadataRetrieverClient.h"
@@ -85,21 +84,17 @@
 #endif
 
 namespace {
+using android::media::Metadata;
 using android::status_t;
 using android::OK;
 using android::BAD_VALUE;
 using android::NOT_ENOUGH_DATA;
-using android::MetadataType;
 using android::Parcel;
-using android::SortedVector;
 
 // Max number of entries in the filter.
 const int kMaxFilterSize = 64;  // I pulled that out of thin air.
 
-// Keep in sync with ANY in Metadata.java
-const int32_t kAny = 0;
-
-const int32_t kMetaMarker = 0x4d455441;  // 'M' 'E' 'T' 'A'
+// FIXME: Move all the metadata related function in the Metadata.cpp
 
 
 // Unmarshall a filter from a Parcel.
@@ -124,7 +119,7 @@
 // @param[out] status On exit contains the status code to be returned.
 // @return true if the parcel starts with a valid filter.
 bool unmarshallFilter(const Parcel& p,
-                      SortedVector<MetadataType> *filter,
+                      Metadata::Filter *filter,
                       status_t *status)
 {
     int32_t val;
@@ -147,7 +142,7 @@
     filter->clear();
     filter->setCapacity(num);
 
-    size_t size = num * sizeof(MetadataType);
+    size_t size = num * sizeof(Metadata::Type);
 
 
     if (p.dataAvail() < size)
@@ -157,7 +152,8 @@
         return false;
     }
 
-    const MetadataType *data = static_cast<const MetadataType*>(p.readInplace(size));
+    const Metadata::Type *data =
+            static_cast<const Metadata::Type*>(p.readInplace(size));
 
     if (NULL == data)
     {
@@ -181,11 +177,11 @@
 // @param filter Of metadata type.
 // @param val To be searched.
 // @return true if a match was found.
-bool findMetadata(const SortedVector<MetadataType>& filter, const int32_t val)
+bool findMetadata(const Metadata::Filter& filter, const int32_t val)
 {
     // Deal with empty and ANY right away
     if (filter.isEmpty()) return false;
-    if (filter[0] == kAny) return true;
+    if (filter[0] == Metadata::kAny) return true;
 
     return filter.indexOf(val) >= 0;
 }
@@ -857,7 +853,7 @@
 status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
 {
     status_t status;
-    SortedVector<MetadataType> allow, drop;
+    media::Metadata::Filter allow, drop;
 
     if (unmarshallFilter(filter, &allow, &status) &&
         unmarshallFilter(filter, &drop, &status)) {
@@ -872,14 +868,14 @@
 status_t MediaPlayerService::Client::getMetadata(
         bool update_only, bool apply_filter, Parcel *reply)
 {
-    sp<MediaPlayerBase> p = getPlayer();
-    if (p == 0) return UNKNOWN_ERROR;
+    sp<MediaPlayerBase> player = getPlayer();
+    if (player == 0) return UNKNOWN_ERROR;
 
     status_t status;
     // Placeholder for the return code, updated by the caller.
     reply->writeInt32(-1);
 
-    SortedVector<MetadataType> ids;
+    media::Metadata::Filter ids;
 
     // We don't block notifications while we fetch the data. We clear
     // mMetadataUpdated first so we don't lose notifications happening
@@ -892,14 +888,13 @@
         mMetadataUpdated.clear();
     }
 
-    const size_t begin = reply->dataPosition();
-    reply->writeInt32(-1);  // Placeholder for the length of the metadata
-    reply->writeInt32(kMetaMarker);
+    media::Metadata metadata(reply);
 
-    status = p->getMetadata(ids, reply);
+    metadata.appendHeader();
+    status = player->getMetadata(ids, reply);
 
     if (status != OK) {
-        reply->setDataPosition(begin);
+        metadata.resetParcel();
         LOGE("getMetadata failed %d", status);
         return status;
     }
@@ -908,12 +903,8 @@
     // filtering takes place on the update notifications already. This
     // would be when all the metadata are fetch and a filter is set.
 
-    const size_t end = reply->dataPosition();
-
     // Everything is fine, update the metadata length.
-    reply->setDataPosition(begin);
-    reply->writeInt32(end - begin);
-    reply->setDataPosition(end);
+    metadata.updateLength();
     return OK;
 }
 
@@ -1043,7 +1034,7 @@
 
     if (MEDIA_INFO == msg &&
         MEDIA_INFO_METADATA_UPDATE == ext1) {
-        const MetadataType metadata_type = ext2;
+        const media::Metadata::Type metadata_type = ext2;
 
         if(client->shouldDropMetadata(metadata_type)) {
             return;
@@ -1058,7 +1049,7 @@
 }
 
 
-bool MediaPlayerService::Client::shouldDropMetadata(MetadataType code) const
+bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
 {
     Mutex::Autolock lock(mLock);
 
@@ -1074,7 +1065,7 @@
 }
 
 
-void MediaPlayerService::Client::addNewMetadataUpdate(MetadataType metadata_type) {
+void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
     Mutex::Autolock lock(mLock);
     if (mMetadataUpdated.indexOf(metadata_type) < 0) {
         mMetadataUpdated.add(metadata_type);
@@ -1499,4 +1490,4 @@
     p->mSignal.signal();
 }
 
-}; // namespace android
+} // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 94cb917..a4be414 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -23,15 +23,14 @@
 #include <utils/List.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
-#include <utils/SortedVector.h>
 #include <utils/Vector.h>
 #include <ui/SurfaceComposerClient.h>
 
 #include <media/IMediaPlayerService.h>
 #include <media/MediaPlayerInterface.h>
+#include <media/Metadata.h>
 
 namespace android {
-typedef int32_t MetadataType;
 
 class IMediaRecorder;
 class IMediaMetadataRetriever;
@@ -239,12 +238,12 @@
         // @param type Of the metadata to be tested.
         // @return true if the metadata should be dropped according to
         //              the filters.
-        bool shouldDropMetadata(MetadataType type) const;
+        bool shouldDropMetadata(media::Metadata::Type type) const;
 
         // Add a new element to the set of metadata updated. Noop if
         // the element exists already.
         // @param type Of the metadata to be recorded.
-        void addNewMetadataUpdate(MetadataType type);
+        void addNewMetadataUpdate(media::Metadata::Type type);
 
         mutable     Mutex                       mLock;
                     sp<MediaPlayerBase>         mPlayer;
@@ -257,14 +256,14 @@
                     int32_t                     mConnId;
 
         // Metadata filters.
-        SortedVector<int32_t>       mMetadataAllow;  // protected by mLock
-        SortedVector<int32_t>       mMetadataDrop;  // protected by mLock
+        media::Metadata::Filter mMetadataAllow;  // protected by mLock
+        media::Metadata::Filter mMetadataDrop;  // protected by mLock
 
         // Metadata updated. For each MEDIA_INFO_METADATA_UPDATE
         // notification we try to update mMetadataUpdated which is a
         // set: no duplicate.
         // getMetadata clears this set.
-        SortedVector<int32_t>       mMetadataUpdated;  // protected by mLock
+        media::Metadata::Filter mMetadataUpdated;  // protected by mLock
 
 #if CALLBACK_ANTAGONIZER
                     Antagonizer*                mAntagonizer;
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index 30b6a2e..25d4a1b 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -49,10 +49,6 @@
     virtual status_t    invoke(const Parcel& request, Parcel *reply) {
         return INVALID_OPERATION;
     }
-    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
-                                    Parcel *records)  {
-        return INVALID_OPERATION;
-    }
 
 private:
             status_t    createOutputTrack();
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 8597275..9a06d13 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -144,7 +144,7 @@
     if (mPlayer == NULL) {
         return NO_INIT;
     }
-    
+
     status_t err = mPlayer->seekTo((int64_t)msec * 1000);
 
     sendEvent(MEDIA_SEEK_COMPLETE);
@@ -205,9 +205,4 @@
     }
 }
 
-status_t StagefrightPlayer::getMetadata(
-        const SortedVector<MetadataType> &ids, Parcel *records) {
-    return INVALID_OPERATION;
-}
-
 }  // namespace android
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index f93c1f8..f214872c 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -48,9 +48,6 @@
     virtual status_t invoke(const Parcel &request, Parcel *reply);
     virtual void setAudioSink(const sp<AudioSink> &audioSink);
 
-    virtual status_t getMetadata(
-            const SortedVector<MetadataType> &ids, Parcel *records);
-
 private:
     MediaPlayerImpl *mPlayer;
 
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
index 339b108..80d53a8 100644
--- a/media/libmediaplayerservice/TestPlayerStub.h
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -94,10 +94,6 @@
     virtual status_t invoke(const android::Parcel& in, android::Parcel *out) {
         return mPlayer->invoke(in, out);
     }
-    virtual status_t getMetadata(const SortedVector<MetadataType>& ids,
-                                 Parcel *records) {
-        return INVALID_OPERATION;
-    }
 
 
     // @return true if the current build is 'eng' or 'test' and the
diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h
index 040eb36..4024654 100644
--- a/media/libmediaplayerservice/VorbisPlayer.h
+++ b/media/libmediaplayerservice/VorbisPlayer.h
@@ -54,10 +54,6 @@
     virtual status_t    setLooping(int loop);
     virtual player_type playerType() { return VORBIS_PLAYER; }
     virtual status_t    invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
-    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
-                                    Parcel *records)  {
-        return INVALID_OPERATION;
-    }
 
 private:
             status_t    setdatasource(const char *path, int fd, int64_t offset, int64_t length);
diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp
index 8d575a3..77bb5b2 100644
--- a/media/tests/players/invoke_mock_media_player.cpp
+++ b/media/tests/players/invoke_mock_media_player.cpp
@@ -27,7 +27,6 @@
 using android::INVALID_OPERATION;
 using android::ISurface;
 using android::MediaPlayerBase;
-using android::MetadataType;
 using android::OK;
 using android::Parcel;
 using android::SortedVector;
@@ -78,8 +77,6 @@
     virtual status_t    setLooping(int loop) {return OK;}
     virtual player_type playerType() {return TEST_PLAYER;}
     virtual status_t    invoke(const Parcel& request, Parcel *reply);
-    virtual status_t    getMetadata(const SortedVector<MetadataType>& ids,
-                                    Parcel *records) {return INVALID_OPERATION;}
 
   private:
     // Take a request, copy it to the reply.
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index 82067be..99d7723 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -65,9 +65,9 @@
 // ----------------------------------------------------------------------------
 class SynthProxyJniStorage {
     public :
-        //jclass                    tts_class;
         jobject                   tts_ref;
         TtsEngine*                mNativeSynthInterface;
+        void*                     mEngineLibHandle;
         AudioTrack*               mAudioOut;
         AudioSystem::stream_type  mStreamType;
         uint32_t                  mSampleRate;
@@ -77,9 +77,9 @@
         size_t                    mBufferSize;
 
         SynthProxyJniStorage() {
-            //tts_class = NULL;
             tts_ref = NULL;
             mNativeSynthInterface = NULL;
+            mEngineLibHandle = NULL;
             mAudioOut = NULL;
             mStreamType = DEFAULT_TTS_STREAM_TYPE;
             mSampleRate = DEFAULT_TTS_RATE;
@@ -91,11 +91,17 @@
         }
 
         ~SynthProxyJniStorage() {
+            //LOGV("entering ~SynthProxyJniStorage()");
             killAudio();
             if (mNativeSynthInterface) {
                 mNativeSynthInterface->shutdown();
                 mNativeSynthInterface = NULL;
             }
+            if (mEngineLibHandle) {
+                //LOGE("~SynthProxyJniStorage(): before close library");
+                int res = dlclose(mEngineLibHandle);
+                LOGE_IF( res != 0, "~SynthProxyJniStorage(): dlclose returned %d", res);
+            }
             delete mBuffer;
         }
 
@@ -138,13 +144,14 @@
                     0, 0, 0, 0); // not using an AudioTrack callback
 
             if (mAudioOut->initCheck() != NO_ERROR) {
-              LOGI("AudioTrack error");
+              LOGE("createAudioOut(): AudioTrack error");
               delete mAudioOut;
               mAudioOut = NULL;
             } else {
               //LOGI("AudioTrack OK");
+              mAudioOut->setVolume(2.0f, 2.0f);
               mAudioOut->start();
-              LOGI("AudioTrack started");
+              LOGV("AudioTrack started");
             }
         }
 };
@@ -259,16 +266,18 @@
 
     void *engine_lib_handle = dlopen(nativeSoLibNativeString,
             RTLD_NOW | RTLD_LOCAL);
-    if (engine_lib_handle==NULL) {
-       LOGI("engine_lib_handle==NULL");
+    if (engine_lib_handle == NULL) {
+       LOGE("android_tts_SynthProxy_native_setup(): engine_lib_handle == NULL");
        // TODO report error so the TTS can't be used
     } else {
         TtsEngine *(*get_TtsEngine)() =
             reinterpret_cast<TtsEngine* (*)()>(dlsym(engine_lib_handle, "getTtsEngine"));
 
         pJniStorage->mNativeSynthInterface = (*get_TtsEngine)();
+        pJniStorage->mEngineLibHandle = engine_lib_handle;
 
         if (pJniStorage->mNativeSynthInterface) {
+            Mutex::Autolock l(engineMutex);
             pJniStorage->mNativeSynthInterface->init(ttsSynthDoneCB);
         }
     }
@@ -287,11 +296,29 @@
 static void
 android_tts_SynthProxy_native_finalize(JNIEnv *env, jobject thiz, jint jniData)
 {
-    if (jniData) {
-        SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-        env->DeleteGlobalRef(pSynthData->tts_ref);
-        delete pSynthData;
+    //LOGV("entering android_tts_SynthProxy_finalize()");
+    if (jniData == 0) {
+        //LOGE("android_tts_SynthProxy_native_finalize(): invalid JNI data");
+        return;
     }
+
+    Mutex::Autolock l(engineMutex);
+
+    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
+    env->DeleteGlobalRef(pSynthData->tts_ref);
+    delete pSynthData;
+
+    env->SetIntField(thiz, javaTTSFields.synthProxyFieldJniData, 0);
+}
+
+
+static void
+android_tts_SynthProxy_shutdown(JNIEnv *env, jobject thiz, jint jniData)
+{
+    //LOGV("entering android_tts_SynthProxy_shutdown()");
+
+    // do everything a call to finalize would
+    android_tts_SynthProxy_native_finalize(env, thiz, jniData);
 }
 
 
@@ -604,24 +631,6 @@
 }
 
 
-static void
-android_tts_SynthProxy_shutdown(JNIEnv *env, jobject thiz, jint jniData)
-{
-    if (jniData == 0) {
-        LOGE("android_tts_SynthProxy_shutdown(): invalid JNI data");
-        return;
-    }
-
-    Mutex::Autolock l(engineMutex);
-
-    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-    if (pSynthData->mNativeSynthInterface) {
-        pSynthData->mNativeSynthInterface->shutdown();
-        pSynthData->mNativeSynthInterface = NULL;
-    }
-}
-
-
 static jobjectArray
 android_tts_SynthProxy_getLanguage(JNIEnv *env, jobject thiz, jint jniData)
 {
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index 9a4c97d..e52ba80 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -139,16 +139,18 @@
     private final ReentrantLock speechQueueLock = new ReentrantLock();
     private final ReentrantLock synthesizerLock = new ReentrantLock();
 
-    private SynthProxy nativeSynth;
+    private static SynthProxy sNativeSynth = null;
     @Override
     public void onCreate() {
         super.onCreate();
-        Log.i("TTS", "TTS starting");
+        Log.i("TtsService", "TtsService.onCreate()");
 
         mResolver = getContentResolver();
 
         String soLibPath = "/system/lib/libttspico.so";
-        nativeSynth = new SynthProxy(soLibPath);
+        if (sNativeSynth == null) {
+            sNativeSynth = new SynthProxy(soLibPath);
+        }
 
         mSelf = this;
         mIsSpeaking = false;
@@ -171,7 +173,8 @@
         // Don't hog the media player
         cleanUpPlayer();
 
-        nativeSynth.shutdown();
+        sNativeSynth.shutdown();
+        sNativeSynth = null;
 
         // Unregister all callbacks.
         mCallbacks.kill();
@@ -239,36 +242,36 @@
 
     private int setSpeechRate(String callingApp, int rate) {
         if (isDefaultEnforced()) {
-            return nativeSynth.setSpeechRate(getDefaultRate());
+            return sNativeSynth.setSpeechRate(getDefaultRate());
         } else {
-            return nativeSynth.setSpeechRate(rate);
+            return sNativeSynth.setSpeechRate(rate);
         }
     }
 
 
     private int setPitch(String callingApp, int pitch) {
-        return nativeSynth.setPitch(pitch);
+        return sNativeSynth.setPitch(pitch);
     }
 
 
     private int isLanguageAvailable(String lang, String country, String variant) {
-        //Log.v("TTS", "TtsService.isLanguageAvailable(" + lang + ", " + country + ", " +variant+")");
-        return nativeSynth.isLanguageAvailable(lang, country, variant);
+        //Log.v("TtsService", "TtsService.isLanguageAvailable(" + lang + ", " + country + ", " +variant+")");
+        return sNativeSynth.isLanguageAvailable(lang, country, variant);
     }
 
 
     private String[] getLanguage() {
-        return nativeSynth.getLanguage();
+        return sNativeSynth.getLanguage();
     }
 
 
     private int setLanguage(String callingApp, String lang, String country, String variant) {
-        //Log.v("TTS", "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")");
+        Log.v("TtsService", "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")");
         if (isDefaultEnforced()) {
-            return nativeSynth.setLanguage(getDefaultLanguage(), getDefaultCountry(),
+            return sNativeSynth.setLanguage(getDefaultLanguage(), getDefaultCountry(),
                     getDefaultLocVariant());
         } else {
-            return nativeSynth.setLanguage(lang, country, variant);
+            return sNativeSynth.setLanguage(lang, country, variant);
         }
     }
 
@@ -340,7 +343,7 @@
      *            engines.
      */
     private int speak(String callingApp, String text, int queueMode, ArrayList<String> params) {
-        Log.i("TTS service received", text);
+        Log.v("TtsService", "TTS service received " + text);
         if (queueMode == TextToSpeech.TTS_QUEUE_FLUSH) {
             stop(callingApp);
         } else if (queueMode == 2) {
@@ -390,7 +393,7 @@
             // something has gone very wrong with processSpeechQueue.
             speechQueueAvailable = speechQueueLock.tryLock(1000, TimeUnit.MILLISECONDS);
             if (speechQueueAvailable) {
-                Log.i("TTS", "Stopping");
+                Log.i("TtsService", "Stopping");
                 for (int i = mSpeechQueue.size() - 1; i > -1; i--){
                     if (mSpeechQueue.get(i).mCallingApp.equals(callingApp)){
                         mSpeechQueue.remove(i);
@@ -398,7 +401,7 @@
                 }
                 if ((mCurrentSpeechItem != null) &&
                      mCurrentSpeechItem.mCallingApp.equals(callingApp)) {
-                    result = nativeSynth.stop();
+                    result = sNativeSynth.stop();
                     mKillList.put(mCurrentSpeechItem, true);
                     if (mPlayer != null) {
                         try {
@@ -412,10 +415,10 @@
                 } else {
                     result = TextToSpeech.TTS_SUCCESS;
                 }
-                Log.i("TTS", "Stopped");
+                Log.i("TtsService", "Stopped");
             }
         } catch (InterruptedException e) {
-          Log.e("TTS stop", "tryLock interrupted");
+          Log.e("TtsService", "TTS stop: tryLock interrupted");
           e.printStackTrace();
         } finally {
             // This check is needed because finally will always run; even if the
@@ -448,7 +451,7 @@
                 if ((mCurrentSpeechItem != null) &&
                     ((mCurrentSpeechItem.mType != SpeechItem.TEXT_TO_FILE) ||
                       mCurrentSpeechItem.mCallingApp.equals(callingApp))) {
-                    result = nativeSynth.stop();
+                    result = sNativeSynth.stop();
                     mKillList.put(mCurrentSpeechItem, true);
                     if (mPlayer != null) {
                         try {
@@ -462,10 +465,10 @@
                 } else {
                     result = TextToSpeech.TTS_SUCCESS;
                 }
-                Log.i("TTS", "Stopped all");
+                Log.i("TtsService", "Stopped all");
             }
         } catch (InterruptedException e) {
-          Log.e("TTS stopAll", "tryLock interrupted");
+          Log.e("TtsService", "TTS stopAll: tryLock interrupted");
           e.printStackTrace();
         } finally {
             // This check is needed because finally will always run; even if the
@@ -588,10 +591,10 @@
                         if (speechRate.length() > 0){
                             setSpeechRate("", Integer.parseInt(speechRate));
                         }
-                        nativeSynth.speak(speechItem.mText, streamType);
+                        sNativeSynth.speak(speechItem.mText, streamType);
                     }
                 } catch (InterruptedException e) {
-                    Log.e("TTS speakInternalOnly", "tryLock interrupted");
+                    Log.e("TtsService", "TTS speakInternalOnly(): tryLock interrupted");
                     e.printStackTrace();
                 } finally {
                     // This check is needed because finally will always run;
@@ -617,7 +620,7 @@
             public void run() {
                 boolean synthAvailable = false;
                 String utteranceId = "";
-                Log.i("TTS", "Synthesizing to " + speechItem.mFilename);
+                Log.i("TtsService", "Synthesizing to " + speechItem.mFilename);
                 try {
                     synthAvailable = synthesizerLock.tryLock();
                     if (!synthAvailable) {
@@ -657,10 +660,10 @@
                         if (speechRate.length() > 0){
                             setSpeechRate("", Integer.parseInt(speechRate));
                         }
-                        nativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename);
+                        sNativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename);
                     }
                 } catch (InterruptedException e) {
-                    Log.e("TTS synthToFileInternalOnly", "tryLock interrupted");
+                    Log.e("TtsService", "TTS synthToFileInternalOnly(): tryLock interrupted");
                     e.printStackTrace();
                 } finally {
                     // This check is needed because finally will always run;
@@ -705,7 +708,7 @@
         if (cb == null){
             return;
         }
-        Log.i("TTS callback", "dispatch started");
+        Log.i("TtsService", "TTS callback: dispatch started");
         // Broadcast to all clients the new value.
         final int N = mCallbacks.beginBroadcast();
         try {
@@ -715,7 +718,7 @@
             // the dead object for us.
         }
         mCallbacks.finishBroadcast();
-        Log.i("TTS callback", "dispatch completed to " + N);
+        Log.i("TtsService", "TTS callback: dispatch completed to " + N);
     }
 
     private SpeechItem splitCurrentTextIfNeeded(SpeechItem currentSpeechItem){
@@ -764,7 +767,7 @@
             SoundResource sr = getSoundResource(mCurrentSpeechItem);
             // Synth speech as needed - synthesizer should call
             // processSpeechQueue to continue running the queue
-            Log.i("TTS processing: ", mCurrentSpeechItem.mText);
+            Log.i("TtsService", "TTS processing: " + mCurrentSpeechItem.mText);
             if (sr == null) {
                 if (mCurrentSpeechItem.mType == SpeechItem.TEXT) {
                     mCurrentSpeechItem = splitCurrentTextIfNeeded(mCurrentSpeechItem);
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
index 26322f4..87bd780 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
@@ -161,6 +161,7 @@
 
     synchronized void onDisconnect(boolean cleanUpServices) {
         try {
+            Log.d(TAG, "       disconnecting VPN...");
             mState = VpnState.DISCONNECTING;
             broadcastConnectivity(VpnState.DISCONNECTING);
             mNotification.showDisconnect();
@@ -217,6 +218,8 @@
                 synchronized (VpnService.this) {
                     if (mState == VpnState.CONNECTING) {
                         Log.d(TAG, "       connecting timed out !!");
+                        mError = newConnectingError(
+                                new IOException("Connecting timed out"));
                         onError();
                     }
                 }
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index a71c39a..3e98132 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -26,6 +26,9 @@
     /** Amount that trackball needs to move in order to generate a key event. */
     static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
 
+    /** Maximum number of pointers we will track and report. */
+    static final int MAX_POINTERS = 2;
+    
     final int id;
     final int classes;
     final String name;
@@ -34,7 +37,7 @@
     final AbsoluteInfo absPressure;
     final AbsoluteInfo absSize;
     
-    long mDownTime = 0;
+    long mKeyDownTime = 0;
     int mMetaKeysState = 0;
     
     final MotionState mAbs = new MotionState(0, 0);
@@ -48,13 +51,13 @@
         float yMoveScale;
         MotionEvent currentMove = null;
         boolean changed = false;
-        boolean down = false;
-        boolean lastDown = false;
-        long downTime = 0;
-        int x = 0;
-        int y = 0;
-        int pressure = 1;
-        int size = 0;
+        boolean mLastAnyDown = false;
+        long mDownTime = 0;
+        final boolean[] mLastDown = new boolean[MAX_POINTERS];
+        final boolean[] mDown = new boolean[MAX_POINTERS];
+        final int[] mLastData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
+        final int[] mCurData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
+        final float[] mReportData = new float[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
         
         MotionState(int mx, int my) {
             xPrecision = mx;
@@ -63,46 +66,207 @@
             yMoveScale = my != 0 ? (1.0f/my) : 1.0f;
         }
         
-        MotionEvent generateMotion(InputDevice device, long curTime, long curTimeNano,
-                boolean isAbs, Display display, int orientation,
+        MotionEvent generateAbsMotion(InputDevice device, long curTime,
+                long curTimeNano, Display display, int orientation,
                 int metaState) {
-            float scaledX = x;
-            float scaledY = y;
-            float temp;
-            float scaledPressure = 1.0f;
-            float scaledSize = 0;
+            
+            final float[] scaled = mReportData;
+            final int[] cur = mCurData;
+            
+            boolean anyDown = false;
+            int firstDownChanged = -1;
+            int numPointers = 0;
+            for (int i=0; i<MAX_POINTERS; i++) {
+                boolean d = mDown[i];
+                anyDown |= d;
+                if (d != mLastDown[i] && firstDownChanged < 0) {
+                    firstDownChanged = i;
+                    mLastDown[i] = mDown[i];
+                    d = true;
+                }
+                
+                if (d) {
+                    final int src = i * MotionEvent.NUM_SAMPLE_DATA;
+                    final int dest = numPointers * MotionEvent.NUM_SAMPLE_DATA;
+                    numPointers++;
+                    scaled[dest + MotionEvent.SAMPLE_X] = cur[src + MotionEvent.SAMPLE_X];
+                    scaled[dest + MotionEvent.SAMPLE_Y] = cur[src + MotionEvent.SAMPLE_Y];
+                    scaled[dest + MotionEvent.SAMPLE_PRESSURE] = cur[src + MotionEvent.SAMPLE_PRESSURE];
+                    scaled[dest + MotionEvent.SAMPLE_SIZE] = cur[src + MotionEvent.SAMPLE_SIZE];
+                }
+            }
+            
+            if (numPointers <= 0) {
+                return null;
+            }
+            
+            int action;
+            int edgeFlags = 0;
+            if (anyDown != mLastAnyDown) {
+                final AbsoluteInfo absX = device.absX;
+                final AbsoluteInfo absY = device.absY;
+                if (anyDown && absX != null && absY != null) {
+                    // We don't let downs start unless we are
+                    // inside of the screen.  There are two reasons for
+                    // this: to avoid spurious touches when holding
+                    // the edges of the device near the touchscreen,
+                    // and to avoid reporting events if there are virtual
+                    // keys on the touchscreen outside of the display
+                    // area.
+                    // Note that we are only looking at the first pointer,
+                    // since what we are handling here is the first pointer
+                    // going down, and this is the coordinate that will be
+                    // used to dispatch the event.
+                    if (cur[MotionEvent.SAMPLE_X] < absX.minValue
+                            || cur[MotionEvent.SAMPLE_X] > absX.maxValue
+                            || cur[MotionEvent.SAMPLE_Y] < absY.minValue
+                            || cur[MotionEvent.SAMPLE_Y] > absY.maxValue) {
+                        if (false) Log.v("InputDevice", "Rejecting ("
+                                + cur[MotionEvent.SAMPLE_X] + ","
+                                + cur[MotionEvent.SAMPLE_Y] + "): outside of ("
+                                + absX.minValue + "," + absY.minValue
+                                + ")-(" + absX.maxValue + ","
+                                + absY.maxValue + ")");
+                        return null;
+                    }
+                }
+                mLastAnyDown = anyDown;
+                if (anyDown) {
+                    action = MotionEvent.ACTION_DOWN;
+                    mDownTime = curTime;
+                } else {
+                    action = MotionEvent.ACTION_UP;
+                }
+                currentMove = null;
+            } else if (firstDownChanged >= 0) {
+                if (mDown[firstDownChanged]) {
+                    action = MotionEvent.ACTION_POINTER_DOWN
+                            | (firstDownChanged << MotionEvent.ACTION_POINTER_SHIFT);
+                } else {
+                    action = MotionEvent.ACTION_POINTER_UP
+                            | (firstDownChanged << MotionEvent.ACTION_POINTER_SHIFT);
+                }
+                currentMove = null;
+            } else {
+                action = MotionEvent.ACTION_MOVE;
+            }
+            
+            final int dispW = display.getWidth()-1;
+            final int dispH = display.getHeight()-1;
+            int w = dispW;
+            int h = dispH;
+            if (orientation == Surface.ROTATION_90
+                    || orientation == Surface.ROTATION_270) {
+                int tmp = w;
+                w = h;
+                h = tmp;
+            }
+            
+            final AbsoluteInfo absX = device.absX;
+            final AbsoluteInfo absY = device.absY;
+            final AbsoluteInfo absPressure = device.absPressure;
+            final AbsoluteInfo absSize = device.absSize;
+            for (int i=0; i<numPointers; i++) {
+                final int j = i * MotionEvent.NUM_SAMPLE_DATA;
+            
+                if (absX != null) {
+                    scaled[j + MotionEvent.SAMPLE_X] =
+                            ((scaled[j + MotionEvent.SAMPLE_X]-absX.minValue)
+                                / absX.range) * w;
+                }
+                if (absY != null) {
+                    scaled[j + MotionEvent.SAMPLE_Y] =
+                            ((scaled[j + MotionEvent.SAMPLE_Y]-absY.minValue)
+                                / absY.range) * h;
+                }
+                if (absPressure != null) {
+                    scaled[j + MotionEvent.SAMPLE_PRESSURE] = 
+                            ((scaled[j + MotionEvent.SAMPLE_PRESSURE]-absPressure.minValue)
+                                / (float)absPressure.range);
+                }
+                if (absSize != null) {
+                    scaled[j + MotionEvent.SAMPLE_SIZE] = 
+                            ((scaled[j + MotionEvent.SAMPLE_SIZE]-absSize.minValue)
+                                / (float)absSize.range);
+                }
+                
+                switch (orientation) {
+                    case Surface.ROTATION_90: {
+                        final float temp = scaled[MotionEvent.SAMPLE_X];
+                        scaled[j + MotionEvent.SAMPLE_X] = scaled[j + MotionEvent.SAMPLE_Y];
+                        scaled[j + MotionEvent.SAMPLE_Y] = w-temp;
+                        break;
+                    }
+                    case Surface.ROTATION_180: {
+                        scaled[j + MotionEvent.SAMPLE_X] = w-scaled[j + MotionEvent.SAMPLE_X];
+                        scaled[j + MotionEvent.SAMPLE_Y] = h-scaled[j + MotionEvent.SAMPLE_Y];
+                        break;
+                    }
+                    case Surface.ROTATION_270: {
+                        final float temp = scaled[i + MotionEvent.SAMPLE_X];
+                        scaled[j + MotionEvent.SAMPLE_X] = h-scaled[j + MotionEvent.SAMPLE_Y];
+                        scaled[j + MotionEvent.SAMPLE_Y] = temp;
+                        break;
+                    }
+                }
+            }
+            
+            // We only consider the first pointer when computing the edge
+            // flags, since they are global to the event.
+            if (action != MotionEvent.ACTION_DOWN) {
+                if (scaled[MotionEvent.SAMPLE_X] <= 0) {
+                    edgeFlags |= MotionEvent.EDGE_LEFT;
+                } else if (scaled[MotionEvent.SAMPLE_X] >= dispW) {
+                    edgeFlags |= MotionEvent.EDGE_RIGHT;
+                }
+                if (scaled[MotionEvent.SAMPLE_Y] <= 0) {
+                    edgeFlags |= MotionEvent.EDGE_TOP;
+                } else if (scaled[MotionEvent.SAMPLE_Y] >= dispH) {
+                    edgeFlags |= MotionEvent.EDGE_BOTTOM;
+                }
+            }
+            
+            if (currentMove != null) {
+                if (false) Log.i("InputDevice", "Adding batch x="
+                        + scaled[MotionEvent.SAMPLE_X]
+                        + " y=" + scaled[MotionEvent.SAMPLE_Y]
+                        + " to " + currentMove);
+                currentMove.addBatch(curTime, scaled, metaState);
+                if (WindowManagerPolicy.WATCH_POINTER) {
+                    Log.i("KeyInputQueue", "Updating: " + currentMove);
+                }
+                return null;
+            }
+            
+            MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
+                    curTimeNano, action, numPointers, scaled, metaState,
+                    xPrecision, yPrecision, device.id, edgeFlags);
+            if (action == MotionEvent.ACTION_MOVE) {
+                currentMove = me;
+            }
+            return me;
+        }
+        
+        MotionEvent generateRelMotion(InputDevice device, long curTime,
+                long curTimeNano, int orientation, int metaState) {
+            
+            final float[] scaled = mReportData;
+            
+            // For now we only support 1 pointer with relative motions.
+            scaled[MotionEvent.SAMPLE_X] = mCurData[MotionEvent.SAMPLE_X];
+            scaled[MotionEvent.SAMPLE_Y] = mCurData[MotionEvent.SAMPLE_Y];
+            scaled[MotionEvent.SAMPLE_PRESSURE] = 1.0f;
+            scaled[MotionEvent.SAMPLE_SIZE] = 0;
             int edgeFlags = 0;
             
             int action;
-            if (down != lastDown) {
-                if (isAbs) {
-                    final AbsoluteInfo absX = device.absX;
-                    final AbsoluteInfo absY = device.absY;
-                    if (down && absX != null && absY != null) {
-                        // We don't let downs start unless we are
-                        // inside of the screen.  There are two reasons for
-                        // this: to avoid spurious touches when holding
-                        // the edges of the device near the touchscreen,
-                        // and to avoid reporting events if there are virtual
-                        // keys on the touchscreen outside of the display
-                        // area.
-                        if (scaledX < absX.minValue || scaledX > absX.maxValue
-                                || scaledY < absY.minValue || scaledY > absY.maxValue) {
-                            if (false) Log.v("InputDevice", "Rejecting (" + scaledX + ","
-                                    + scaledY + "): outside of ("
-                                    + absX.minValue + "," + absY.minValue
-                                    + ")-(" + absX.maxValue + ","
-                                    + absY.maxValue + ")");
-                            return null;
-                        }
-                    }
-                } else {
-                    x = y = 0;
-                }
-                lastDown = down;
-                if (down) {
+            if (mDown[0] != mLastDown[0]) {
+                mCurData[MotionEvent.SAMPLE_X] =
+                        mCurData[MotionEvent.SAMPLE_Y] = 0;
+                mLastDown[0] = mDown[0];
+                if (mDown[0]) {
                     action = MotionEvent.ACTION_DOWN;
-                    downTime = curTime;
+                    mDownTime = curTime;
                 } else {
                     action = MotionEvent.ACTION_UP;
                 }
@@ -111,100 +275,42 @@
                 action = MotionEvent.ACTION_MOVE;
             }
             
-            if (isAbs) {
-                final int dispW = display.getWidth()-1;
-                final int dispH = display.getHeight()-1;
-                int w = dispW;
-                int h = dispH;
-                if (orientation == Surface.ROTATION_90
-                        || orientation == Surface.ROTATION_270) {
-                    int tmp = w;
-                    w = h;
-                    h = tmp;
+            scaled[MotionEvent.SAMPLE_X] *= xMoveScale;
+            scaled[MotionEvent.SAMPLE_Y] *= yMoveScale;
+            switch (orientation) {
+                case Surface.ROTATION_90: {
+                    final float temp = scaled[MotionEvent.SAMPLE_X];
+                    scaled[MotionEvent.SAMPLE_X] = scaled[MotionEvent.SAMPLE_Y];
+                    scaled[MotionEvent.SAMPLE_Y] = -temp;
+                    break;
                 }
-                if (device.absX != null) {
-                    scaledX = ((scaledX-device.absX.minValue)
-                                / device.absX.range) * w;
+                case Surface.ROTATION_180: {
+                    scaled[MotionEvent.SAMPLE_X] = -scaled[MotionEvent.SAMPLE_X];
+                    scaled[MotionEvent.SAMPLE_Y] = -scaled[MotionEvent.SAMPLE_Y];
+                    break;
                 }
-                if (device.absY != null) {
-                    scaledY = ((scaledY-device.absY.minValue)
-                                / device.absY.range) * h;
-                }
-                if (device.absPressure != null) {
-                    scaledPressure = 
-                        ((pressure-device.absPressure.minValue)
-                                / (float)device.absPressure.range);
-                }
-                if (device.absSize != null) {
-                    scaledSize = 
-                        ((size-device.absSize.minValue)
-                                / (float)device.absSize.range);
-                }
-                switch (orientation) {
-                    case Surface.ROTATION_90:
-                        temp = scaledX;
-                        scaledX = scaledY;
-                        scaledY = w-temp;
-                        break;
-                    case Surface.ROTATION_180:
-                        scaledX = w-scaledX;
-                        scaledY = h-scaledY;
-                        break;
-                    case Surface.ROTATION_270:
-                        temp = scaledX;
-                        scaledX = h-scaledY;
-                        scaledY = temp;
-                        break;
-                }
-
-                if (action != MotionEvent.ACTION_DOWN) {
-                    if (scaledX <= 0) {
-                        edgeFlags += MotionEvent.EDGE_LEFT;
-                    } else if (scaledX >= dispW) {
-                        edgeFlags += MotionEvent.EDGE_RIGHT;
-                    }
-                    if (scaledY <= 0) {
-                        edgeFlags += MotionEvent.EDGE_TOP;
-                    } else if (scaledY >= dispH) {
-                        edgeFlags += MotionEvent.EDGE_BOTTOM;
-                    }
-                }
-                
-            } else {
-                scaledX *= xMoveScale;
-                scaledY *= yMoveScale;
-                switch (orientation) {
-                    case Surface.ROTATION_90:
-                        temp = scaledX;
-                        scaledX = scaledY;
-                        scaledY = -temp;
-                        break;
-                    case Surface.ROTATION_180:
-                        scaledX = -scaledX;
-                        scaledY = -scaledY;
-                        break;
-                    case Surface.ROTATION_270:
-                        temp = scaledX;
-                        scaledX = -scaledY;
-                        scaledY = temp;
-                        break;
+                case Surface.ROTATION_270: {
+                    final float temp = scaled[MotionEvent.SAMPLE_X];
+                    scaled[MotionEvent.SAMPLE_X] = -scaled[MotionEvent.SAMPLE_Y];
+                    scaled[MotionEvent.SAMPLE_Y] = temp;
+                    break;
                 }
             }
             
             if (currentMove != null) {
-                if (false) Log.i("InputDevice", "Adding batch x=" + scaledX
-                        + " y=" + scaledY + " to " + currentMove);
-                currentMove.addBatch(curTime, scaledX, scaledY,
-                        scaledPressure, scaledSize, metaState);
+                if (false) Log.i("InputDevice", "Adding batch x="
+                        + scaled[MotionEvent.SAMPLE_X]
+                        + " y=" + scaled[MotionEvent.SAMPLE_Y]
+                        + " to " + currentMove);
+                currentMove.addBatch(curTime, scaled, metaState);
                 if (WindowManagerPolicy.WATCH_POINTER) {
                     Log.i("KeyInputQueue", "Updating: " + currentMove);
                 }
                 return null;
             }
             
-            MotionEvent me = MotionEvent.obtainNano(downTime, curTime,
-                    curTimeNano, action, scaledX, scaledY,
-                    scaledPressure, scaledSize, metaState,
+            MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
+                    curTimeNano, action, 1, scaled, metaState,
                     xPrecision, yPrecision, device.id, edgeFlags);
             if (action == MotionEvent.ACTION_MOVE) {
                 currentMove = me;
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index 77051bd..17e9625 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -446,14 +446,14 @@
                             boolean down;
                             if (ev.value != 0) {
                                 down = true;
-                                di.mDownTime = curTime;
+                                di.mKeyDownTime = curTime;
                             } else {
                                 down = false;
                             }
                             int keycode = rotateKeyCodeLocked(ev.keycode);
                             addLocked(di, curTimeNano, ev.flags,
                                     RawInputEvent.CLASS_KEYBOARD,
-                                    newKeyEvent(di, di.mDownTime, curTime, down,
+                                    newKeyEvent(di, di.mKeyDownTime, curTime, down,
                                             keycode, 0, scancode,
                                             ((ev.flags & WindowManagerPolicy.FLAG_WOKE_HERE) != 0)
                                              ? KeyEvent.FLAG_WOKE_HERE : 0));
@@ -461,29 +461,47 @@
                             if (ev.scancode == RawInputEvent.BTN_TOUCH &&
                                     (classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
                                 di.mAbs.changed = true;
-                                di.mAbs.down = ev.value != 0;
-                            }
-                            if (ev.scancode == RawInputEvent.BTN_MOUSE &&
+                                di.mAbs.mDown[0] = ev.value != 0;
+                            } else if (ev.scancode == RawInputEvent.BTN_2 &&
+                                    (classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
+                                di.mAbs.changed = true;
+                                di.mAbs.mDown[1] = ev.value != 0;
+                            } else if (ev.scancode == RawInputEvent.BTN_MOUSE &&
                                     (classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
                                 di.mRel.changed = true;
-                                di.mRel.down = ev.value != 0;
+                                di.mRel.mDown[0] = ev.value != 0;
                                 send = true;
                             }
     
                         } else if (ev.type == RawInputEvent.EV_ABS &&
                                 (classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
+                            // Finger 1
                             if (ev.scancode == RawInputEvent.ABS_X) {
                                 di.mAbs.changed = true;
-                                di.mAbs.x = ev.value;
+                                di.mAbs.mCurData[MotionEvent.SAMPLE_X] = ev.value;
                             } else if (ev.scancode == RawInputEvent.ABS_Y) {
                                 di.mAbs.changed = true;
-                                di.mAbs.y = ev.value;
+                                di.mAbs.mCurData[MotionEvent.SAMPLE_Y] = ev.value;
                             } else if (ev.scancode == RawInputEvent.ABS_PRESSURE) {
                                 di.mAbs.changed = true;
-                                di.mAbs.pressure = ev.value;
+                                di.mAbs.mCurData[MotionEvent.SAMPLE_PRESSURE] = ev.value;
+                                di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
+                                                 + MotionEvent.SAMPLE_PRESSURE] = ev.value;
                             } else if (ev.scancode == RawInputEvent.ABS_TOOL_WIDTH) {
                                 di.mAbs.changed = true;
-                                di.mAbs.size = ev.value;
+                                di.mAbs.mCurData[MotionEvent.SAMPLE_SIZE] = ev.value;
+                                di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
+                                                 + MotionEvent.SAMPLE_SIZE] = ev.value;
+
+                            // Finger 2
+                            } else if (ev.scancode == RawInputEvent.ABS_HAT0X) {
+                                di.mAbs.changed = true;
+                                di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
+                                                 + MotionEvent.SAMPLE_X] = ev.value;
+                            } else if (ev.scancode == RawInputEvent.ABS_HAT0Y) {
+                                di.mAbs.changed = true;
+                                di.mAbs.mCurData[MotionEvent.NUM_SAMPLE_DATA
+                                                 + MotionEvent.SAMPLE_Y] = ev.value;
                             }
     
                         } else if (ev.type == RawInputEvent.EV_REL &&
@@ -491,10 +509,10 @@
                             // Add this relative movement into our totals.
                             if (ev.scancode == RawInputEvent.REL_X) {
                                 di.mRel.changed = true;
-                                di.mRel.x += ev.value;
+                                di.mRel.mCurData[MotionEvent.SAMPLE_X] += ev.value;
                             } else if (ev.scancode == RawInputEvent.REL_Y) {
                                 di.mRel.changed = true;
-                                di.mRel.y += ev.value;
+                                di.mRel.mCurData[MotionEvent.SAMPLE_Y] += ev.value;
                             }
                         }
                         
@@ -516,33 +534,33 @@
                                     VirtualKey vk = mPressedVirtualKey;
                                     if (vk != null) {
                                         doMotion = false;
-                                        if (!ms.down) {
+                                        if (!ms.mDown[0]) {
                                             mPressedVirtualKey = null;
-                                            ms.lastDown = ms.down;
+                                            ms.mLastDown[0] = ms.mDown[0];
                                             if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
                                                     "Generate key up for: " + vk.scancode);
                                             addLocked(di, curTimeNano, ev.flags,
                                                     RawInputEvent.CLASS_KEYBOARD,
-                                                    newKeyEvent(di, di.mDownTime,
+                                                    newKeyEvent(di, di.mKeyDownTime,
                                                             curTime, false,
                                                             vk.lastKeycode,
                                                             0, vk.scancode, 0));
                                         }
-                                    } else if (ms.down && !ms.lastDown) {
+                                    } else if (ms.mDown[0] && !ms.mLastDown[0]) {
                                         vk = findSoftButton(di);
                                         if (vk != null) {
                                             doMotion = false;
                                             mPressedVirtualKey = vk;
                                             vk.lastKeycode = scancodeToKeycode(
                                                     di.id, vk.scancode);
-                                            ms.lastDown = ms.down;
-                                            di.mDownTime = curTime;
+                                            ms.mLastDown[0] = ms.mDown[0];
+                                            di.mKeyDownTime = curTime;
                                             if (DEBUG_VIRTUAL_KEYS) Log.v(TAG,
                                                     "Generate key down for: " + vk.scancode
                                                     + " (keycode=" + vk.lastKeycode + ")");
                                             addLocked(di, curTimeNano, ev.flags,
                                                     RawInputEvent.CLASS_KEYBOARD,
-                                                    newKeyEvent(di, di.mDownTime,
+                                                    newKeyEvent(di, di.mKeyDownTime,
                                                             curTime, true,
                                                             vk.lastKeycode, 0,
                                                             vk.scancode, 0));
@@ -550,11 +568,18 @@
                                     }
                                     
                                     if (doMotion) {
-                                        me = ms.generateMotion(di, curTime,
-                                                curTimeNano, true, mDisplay,
+                                        // XXX Need to be able to generate
+                                        // multiple events here, for example
+                                        // if two fingers change up/down state
+                                        // at the same time.
+                                        me = ms.generateAbsMotion(di, curTime,
+                                                curTimeNano, mDisplay,
                                                 mOrientation, mGlobalMetaState);
-                                        if (false) Log.v(TAG, "Absolute: x=" + di.mAbs.x
-                                                + " y=" + di.mAbs.y + " ev=" + me);
+                                        if (false) Log.v(TAG, "Absolute: x="
+                                                + di.mAbs.mCurData[MotionEvent.SAMPLE_X]
+                                                + " y="
+                                                + di.mAbs.mCurData[MotionEvent.SAMPLE_Y]
+                                                + " ev=" + me);
                                         if (me != null) {
                                             if (WindowManagerPolicy.WATCH_POINTER) {
                                                 Log.i(TAG, "Enqueueing: " + me);
@@ -569,11 +594,14 @@
                                 if (ms.changed) {
                                     ms.changed = false;
                                     
-                                    me = ms.generateMotion(di, curTime,
-                                            curTimeNano, false, mDisplay,
+                                    me = ms.generateRelMotion(di, curTime,
+                                            curTimeNano,
                                             mOrientation, mGlobalMetaState);
-                                    if (false) Log.v(TAG, "Relative: x=" + di.mRel.x
-                                            + " y=" + di.mRel.y + " ev=" + me);
+                                    if (false) Log.v(TAG, "Relative: x="
+                                            + di.mRel.mCurData[MotionEvent.SAMPLE_X]
+                                            + " y="
+                                            + di.mRel.mCurData[MotionEvent.SAMPLE_Y]
+                                            + " ev=" + me);
                                     if (me != null) {
                                         addLocked(di, curTimeNano, ev.flags,
                                                 RawInputEvent.CLASS_TRACKBALL, me);
@@ -603,21 +631,28 @@
             return null;
         }
         
-        if (absm.x >= absx.minValue && absm.x <= absx.maxValue
-                && absm.y >= absy.minValue && absm.y <= absy.maxValue) {
-            if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Input (" + absm.x
-                    + "," + absm.y + ") inside of display");
+        if (absm.mCurData[MotionEvent.SAMPLE_X] >= absx.minValue
+                && absm.mCurData[MotionEvent.SAMPLE_X] <= absx.maxValue
+                && absm.mCurData[MotionEvent.SAMPLE_Y] >= absy.minValue
+                && absm.mCurData[MotionEvent.SAMPLE_Y] <= absy.maxValue) {
+            if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Input ("
+                    + absm.mCurData[MotionEvent.SAMPLE_X]
+                    + "," + absm.mCurData[MotionEvent.SAMPLE_Y]
+                    + ") inside of display");
             return null;
         }
         
         for (int i=0; i<N; i++) {
             VirtualKey sb = mVirtualKeys.get(i);
             sb.computeHitRect(dev, mDisplayWidth, mDisplayHeight);
-            if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Hit test (" + absm.x + ","
-                    + absm.y + ") in code " + sb.scancode + " - (" + sb.hitLeft
+            if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Hit test ("
+                    + absm.mCurData[MotionEvent.SAMPLE_X] + ","
+                    + absm.mCurData[MotionEvent.SAMPLE_Y] + ") in code "
+                    + sb.scancode + " - (" + sb.hitLeft
                     + "," + sb.hitTop + ")-(" + sb.hitRight + ","
                     + sb.hitBottom + ")");
-            if (sb.checkHit(absm.x, absm.y)) {
+            if (sb.checkHit(absm.mCurData[MotionEvent.SAMPLE_X],
+                    absm.mCurData[MotionEvent.SAMPLE_Y])) {
                 if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Hit!");
                 return sb;
             }
@@ -772,8 +807,8 @@
             if (ev.event == ev.inputDevice.mRel.currentMove) {
                 if (false) Log.i(TAG, "Detach rel " + ev.event);
                 ev.inputDevice.mRel.currentMove = null;
-                ev.inputDevice.mRel.x = 0;
-                ev.inputDevice.mRel.y = 0;
+                ev.inputDevice.mRel.mCurData[MotionEvent.SAMPLE_X] = 0;
+                ev.inputDevice.mRel.mCurData[MotionEvent.SAMPLE_Y] = 0;
             }
             recycleLocked(ev);
         }
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 7025e79..d6cd4ef 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -262,7 +262,6 @@
     final ResolveInfo mResolveInfo = new ResolveInfo();
     ComponentName mResolveComponentName;
     PackageParser.Package mPlatformPackage;
-    private boolean mCompatibilityModeEnabled = true;
 
     public static final IPackageManager main(Context context, boolean factoryTest) {
         PackageManagerService m = new PackageManagerService(context, factoryTest);
@@ -765,7 +764,7 @@
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
             if (Config.LOGV) Log.v(
-                TAG, "getApplicationInfo " + packageName
+                TAG, "getPackageInfo " + packageName
                 + ": " + p);
             if (p != null) {
                 return generatePackageInfo(p, flags);
@@ -796,7 +795,7 @@
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
             if (Config.LOGV) Log.v(
-                TAG, "getApplicationInfo " + packageName
+                TAG, "getPackageGids" + packageName
                 + ": " + p);
             if (p != null) {
                 final PackageSetting ps = (PackageSetting)p.mExtras;
@@ -894,11 +893,7 @@
                     + ": " + p);
             if (p != null) {
                 // Note: isEnabledLP() does not apply here - always return info
-                ApplicationInfo appInfo = PackageParser.generateApplicationInfo(p, flags);
-                if (!mCompatibilityModeEnabled) {
-                    appInfo.disableCompatibilityMode();
-                }
-                return appInfo;
+                return PackageParser.generateApplicationInfo(p, flags);
             }
             if ("android".equals(packageName)||"system".equals(packageName)) {
                 return mAndroidApplication;
@@ -4820,11 +4815,12 @@
         mSystemReady = true;
 
         // Read the compatibilty setting when the system is ready.
-        mCompatibilityModeEnabled = android.provider.Settings.System.getInt(
+        boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
                 mContext.getContentResolver(),
                 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
+        PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
         if (DEBUG_SETTINGS) {
-            Log.d(TAG, "compatibility mode:" + mCompatibilityModeEnabled);
+            Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
         }
     }
 
@@ -4909,22 +4905,40 @@
                     if (ps.pkg != null) {
                         pw.print("    dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
                         pw.print("    targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
-                        pw.print("    densities="); pw.println(ps.pkg.supportsDensityList);
-                        ArrayList<String> screens = new ArrayList<String>();
+                        pw.print("    supportsScreens=[");
+                        boolean first = true;
                         if ((ps.pkg.applicationInfo.flags & 
                                 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
-                            screens.add("medium");
+                            if (!first) pw.print(", ");
+                            first = false;
+                            pw.print("medium");
                         }
                         if ((ps.pkg.applicationInfo.flags & 
                                 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
-                            screens.add("large");
+                            if (!first) pw.print(", ");
+                            first = false;
+                            pw.print("large");
                         }
                         if ((ps.pkg.applicationInfo.flags & 
                                 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
-                            screens.add("small,");
+                            if (!first) pw.print(", ");
+                            first = false;
+                            pw.print("small");
                         }
-                        pw.print("    supportsScreens="); pw.println(screens);
+                        if ((ps.pkg.applicationInfo.flags & 
+                                ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
+                            if (!first) pw.print(", ");
+                            first = false;
+                            pw.print("resizeable");
+                        }
+                        if ((ps.pkg.applicationInfo.flags & 
+                                ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
+                            if (!first) pw.print(", ");
+                            first = false;
+                            pw.print("anyDensity");
+                        }
                     }
+                    pw.println("]");
                     pw.print("    timeStamp="); pw.println(ps.getTimeStampStr());
                     pw.print("    signatures="); pw.println(ps.signatures);
                     pw.print("    permissionsFixed="); pw.print(ps.permissionsFixed);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 67e8cf3..f25c221 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -888,6 +888,17 @@
                 break setVariables;
             }
 
+            if ((config.phase2 != null) && !WifiNative.setNetworkVariableCommand(
+                    netId,
+                    WifiConfiguration.phase2VarName,
+                    config.phase2)) {
+                if (DBG) {
+                    Log.d(TAG, config.SSID + ": failed to set phase2: "+
+                          config.phase2);
+                }
+                break setVariables;
+            }
+
             if ((config.identity != null) && !WifiNative.setNetworkVariableCommand(
                     netId,
                     WifiConfiguration.identityVarName,
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index f04cfd6..b43acaf 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -27,6 +27,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
 import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
@@ -422,7 +423,7 @@
     final Rect mTempRect = new Rect();
 
     final Configuration mTempConfiguration = new Configuration();
-    int screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
+    int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED;
 
     // The frame use to limit the size of the app running in compatibility mode.
     Rect mCompatibleScreenFrame = new Rect();
@@ -1864,7 +1865,7 @@
         // is running.
         if (!mDisplayFrozen) {
             Animation a;
-            if ((lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
+            if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
                 a = new FadeInOutAnimation(enter);
                 if (DEBUG_ANIM) Log.v(TAG,
                         "applying FadeInOutAnimation for a window in compatibility mode");
@@ -3765,7 +3766,7 @@
         mDisplay.getMetrics(dm);
         CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
 
-        if (screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
+        if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_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.
@@ -3785,16 +3786,35 @@
             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;
+                mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
+                        | Configuration.SCREENLAYOUT_LONG_NO;
             } else {
-                screenLayout = Configuration.SCREENLAYOUT_NORMAL;
+                // Is this a large screen?
+                if (longSize > 640 && shortSize >= 480) {
+                    // VGA or larger screens at medium density are the point
+                    // at which we consider it to be a large screen.
+                    mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
+                } else {
+                    mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
+                    
+                    // If this screen is wider than normal HVGA, or taller
+                    // than FWVGA, then for old apps we want to run in size
+                    // compatibility mode.
+                    if (shortSize > 321 || longSize > 570) {
+                        mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
+                    }
+                }
+                
+                // Is this a long screen?
+                if (((longSize*3)/5) >= (shortSize-1)) {
+                    // Anything wider than WVGA (5:3) is considering to be long.
+                    mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
+                } else {
+                    mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
+                }
             }
         }
-        config.screenLayout = screenLayout;
+        config.screenLayout = mScreenLayout;
         
         config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
         config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
@@ -5920,7 +5940,9 @@
 
             if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
                 container.intersect(mCompatibleScreenFrame);
-                display.intersect(mCompatibleScreenFrame);
+                if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
+                    display.intersect(mCompatibleScreenFrame);
+                }
             }
 
             final int pw = container.right - container.left;
@@ -6637,12 +6659,17 @@
                 return false;
             }
             final Rect frame = shownFrame ? mShownFrame : mFrame;
-            if (frame.left <= 0 && frame.top <= 0
-                    && frame.right >= screenWidth
-                    && frame.bottom >= screenHeight) {
-                return true;
+
+            if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
+                return frame.left <= mCompatibleScreenFrame.left &&
+                        frame.top <= mCompatibleScreenFrame.top &&
+                        frame.right >= mCompatibleScreenFrame.right &&
+                        frame.bottom >= mCompatibleScreenFrame.bottom;
+            } else {
+                return frame.left <= 0 && frame.top <= 0
+                        && frame.right >= screenWidth
+                        && frame.bottom >= screenHeight;
             }
-            return false;
         }
 
         /**
@@ -6659,16 +6686,13 @@
                  (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
                  // only if it's visible
                  mHasDrawn && mViewVisibility == View.VISIBLE &&
-                 // and only if the application wanted to fill the screen
-                 mAttrs.width == mAttrs.FILL_PARENT &&
-                 mAttrs.height == mAttrs.FILL_PARENT &&
-                 // and only if the window is not hidden
-                 mFrame.left == mCompatibleScreenFrame.left &&
+                 // and only if the application fills the compatible screen
+                 mFrame.left <= mCompatibleScreenFrame.left &&
+                 mFrame.top <= mCompatibleScreenFrame.top &&
+                 mFrame.right >= mCompatibleScreenFrame.right &&
+                 mFrame.bottom >= mCompatibleScreenFrame.bottom &&
                  // and starting window do not need background filler
-                 mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING &&
-                 // and only if the screen is bigger
-                 ((mFrame.right - mFrame.right) < screenWidth ||
-                         (mFrame.bottom - mFrame.top) < screenHeight);
+                 mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING;
         }
 
         boolean isFullscreen(int screenWidth, int screenHeight) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index e1ca201..7d4a2c2 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -184,8 +184,7 @@
     static final int LOG_BOOT_PROGRESS_ENABLE_SCREEN = 3050;
 
     // The flags that are set for all calls we make to the package manager.
-    static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES
-            | PackageManager.GET_SUPPORTS_DENSITIES;
+    static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
     
     private static final String SYSTEM_SECURE = "ro.secure";
 
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 39a1ee0..c834b34 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -41,7 +41,7 @@
     
     final BatteryStatsImpl mStats;
     Context mContext;
-    
+
     BatteryStatsService(String filename) {
         mStats = new BatteryStatsImpl(filename);
     }
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
index 2d58659..d458911 100755
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -39,6 +39,7 @@
 import java.util.Calendar;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -617,7 +618,7 @@
     }
     
     private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput,
-            boolean deleteAfterPrint) {
+            boolean deleteAfterPrint, HashSet<String> packages) {
         List<String> fileList = getUsageStatsFileListFLOCK();
         if (fileList == null) {
             return;
@@ -633,7 +634,8 @@
             String dateStr = file.substring(FILE_PREFIX.length());
             try {
                 Parcel in = getParcelForFile(dFile);
-                collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput);
+                collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput,
+                        packages);
                 if (deleteAfterPrint) {
                     // Delete old file after collecting info only for checkin requests
                     dFile.delete();
@@ -648,7 +650,7 @@
     }
     
     private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw,
-            String date, boolean isCompactOutput) {
+            String date, boolean isCompactOutput, HashSet<String> packages) {
         StringBuilder sb = new StringBuilder(512);
         if (isCompactOutput) {
             sb.append("D:");
@@ -678,7 +680,10 @@
             }
             sb.setLength(0);
             PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
-            if (isCompactOutput) {
+            if (packages != null && !packages.contains(pkgName)) {
+                // This package has not been requested -- don't print
+                // anything for it.
+            } else if (isCompactOutput) {
                 sb.append("P:");
                 sb.append(pkgName);
                 sb.append(',');
@@ -765,6 +770,25 @@
         return false;
     }
     
+    /**
+     * Searches array of arguments for the specified string's data
+     * @param args array of argument strings
+     * @param value value to search for
+     * @return the string of data after the arg, or null if there is none
+     */
+    private static String scanArgsData(String[] args, String value) {
+        if (args != null) {
+            final int N = args.length;
+            for (int i=0; i<N; i++) {
+                if (value.equals(args[i])) {
+                    i++;
+                    return i < N ? args[i] : null;
+                }
+            }
+        }
+        return null;
+    }
+    
     @Override
     /*
      * The data persisted to file is parsed and the stats are computed. 
@@ -773,6 +797,7 @@
         final boolean isCheckinRequest = scanArgs(args, "--checkin");
         final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c");
         final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d");
+        final String rawPackages = scanArgsData(args, "--packages");
         
         // Make sure the current stats are written to the file.  This
         // doesn't need to be done if we are deleting files after printing,
@@ -781,8 +806,27 @@
             writeStatsToFile(true);
         }
         
+        HashSet<String> packages = null;
+        if (rawPackages != null) {
+            if (!"*".equals(rawPackages)) {
+                // A * is a wildcard to show all packages.
+                String[] names = rawPackages.split(",");
+                for (String n : names) {
+                    if (packages == null) {
+                        packages = new HashSet<String>();
+                    }
+                    packages.add(n);
+                }
+            }
+        } else if (isCheckinRequest) {
+            // If checkin doesn't specify any packages, then we simply won't
+            // show anything.
+            Log.w(TAG, "Checkin without packages");
+            return;
+        }
+        
         synchronized (mFileLock) {
-            collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint);
+            collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages);
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index 025382d..905dedf 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -161,8 +161,8 @@
 
         isIncoming = false;
         cnapName = null;
-        cnapNamePresentation = 0;
-        numberPresentation = 0;
+        cnapNamePresentation = Connection.PRESENTATION_ALLOWED;
+        numberPresentation = Connection.PRESENTATION_ALLOWED;
         createTime = System.currentTimeMillis();
 
         if (parent != null) {
diff --git a/tests/CoreTests/android/AndroidManifest.xml b/tests/CoreTests/android/AndroidManifest.xml
index 4809f844..98cc9e5 100644
--- a/tests/CoreTests/android/AndroidManifest.xml
+++ b/tests/CoreTests/android/AndroidManifest.xml
@@ -30,6 +30,7 @@
     <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
     <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/tests/CoreTests/android/database/MatrixCursorTest.java b/tests/CoreTests/android/database/MatrixCursorTest.java
index fb8a12f..cddc6c4 100644
--- a/tests/CoreTests/android/database/MatrixCursorTest.java
+++ b/tests/CoreTests/android/database/MatrixCursorTest.java
@@ -32,6 +32,12 @@
         cursor.newRow().add(null);
         cursor.moveToNext();
         assertTrue(cursor.isNull(0));
+        assertNull(cursor.getString(0));
+        assertEquals(0, cursor.getShort(0));
+        assertEquals(0, cursor.getInt(0));
+        assertEquals(0L, cursor.getLong(0));
+        assertEquals(0.0f, cursor.getFloat(0));
+        assertEquals(0.0d, cursor.getDouble(0));
     }
 
     public void testMatrixCursor() {
diff --git a/tests/DpiTest/res/drawable-240dpi/logo240dpi.png b/tests/DpiTest/res/drawable-hdpi/logo240dpi.png
similarity index 100%
rename from tests/DpiTest/res/drawable-240dpi/logo240dpi.png
rename to tests/DpiTest/res/drawable-hdpi/logo240dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-120dpi/logo120dpi.png b/tests/DpiTest/res/drawable-ldpi/logo120dpi.png
similarity index 100%
rename from tests/DpiTest/res/drawable-120dpi/logo120dpi.png
rename to tests/DpiTest/res/drawable-ldpi/logo120dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/values-largeScreen/strings.xml b/tests/DpiTest/res/values-large-long/strings.xml
similarity index 91%
copy from tests/DpiTest/res/values-largeScreen/strings.xml
copy to tests/DpiTest/res/values-large-long/strings.xml
index f4dd543..be304a7 100644
--- a/tests/DpiTest/res/values-largeScreen/strings.xml
+++ b/tests/DpiTest/res/values-large-long/strings.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <string name="act_title">DpiTest: Large Screen</string>
+    <string name="act_title">DpiTest: Large Long</string>
 </resources>
diff --git a/tests/DpiTest/res/values-largeScreen/strings.xml b/tests/DpiTest/res/values-large-notlong/strings.xml
similarity index 91%
copy from tests/DpiTest/res/values-largeScreen/strings.xml
copy to tests/DpiTest/res/values-large-notlong/strings.xml
index f4dd543..9681f44 100644
--- a/tests/DpiTest/res/values-largeScreen/strings.xml
+++ b/tests/DpiTest/res/values-large-notlong/strings.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <string name="act_title">DpiTest: Large Screen</string>
+    <string name="act_title">DpiTest: Large NotLong</string>
 </resources>
diff --git a/tests/DpiTest/res/values-largeScreen/strings.xml b/tests/DpiTest/res/values-large/strings.xml
similarity index 91%
copy from tests/DpiTest/res/values-largeScreen/strings.xml
copy to tests/DpiTest/res/values-large/strings.xml
index f4dd543..faa95f2 100644
--- a/tests/DpiTest/res/values-largeScreen/strings.xml
+++ b/tests/DpiTest/res/values-large/strings.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <string name="act_title">DpiTest: Large Screen</string>
+    <string name="act_title">DpiTest: Large</string>
 </resources>
diff --git a/tests/DpiTest/res/values-largeScreen/strings.xml b/tests/DpiTest/res/values-long/strings.xml
similarity index 91%
copy from tests/DpiTest/res/values-largeScreen/strings.xml
copy to tests/DpiTest/res/values-long/strings.xml
index f4dd543..d6e5d93 100644
--- a/tests/DpiTest/res/values-largeScreen/strings.xml
+++ b/tests/DpiTest/res/values-long/strings.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <string name="act_title">DpiTest: Large Screen</string>
+    <string name="act_title">DpiTest: Long</string>
 </resources>
diff --git a/tests/DpiTest/res/values-largeScreen/strings.xml b/tests/DpiTest/res/values-normal-long/strings.xml
similarity index 91%
copy from tests/DpiTest/res/values-largeScreen/strings.xml
copy to tests/DpiTest/res/values-normal-long/strings.xml
index f4dd543..6406083 100644
--- a/tests/DpiTest/res/values-largeScreen/strings.xml
+++ b/tests/DpiTest/res/values-normal-long/strings.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <string name="act_title">DpiTest: Large Screen</string>
+    <string name="act_title">DpiTest: Normal Long</string>
 </resources>
diff --git a/tests/DpiTest/res/values-largeScreen/strings.xml b/tests/DpiTest/res/values-normal-notlong/strings.xml
similarity index 91%
rename from tests/DpiTest/res/values-largeScreen/strings.xml
rename to tests/DpiTest/res/values-normal-notlong/strings.xml
index f4dd543..3265e4c5 100644
--- a/tests/DpiTest/res/values-largeScreen/strings.xml
+++ b/tests/DpiTest/res/values-normal-notlong/strings.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <string name="act_title">DpiTest: Large Screen</string>
+    <string name="act_title">DpiTest: Normal NotLong</string>
 </resources>
diff --git a/tests/DpiTest/res/values-largeScreen/strings.xml b/tests/DpiTest/res/values-normal/strings.xml
similarity index 91%
copy from tests/DpiTest/res/values-largeScreen/strings.xml
copy to tests/DpiTest/res/values-normal/strings.xml
index f4dd543..1e27da4 100644
--- a/tests/DpiTest/res/values-largeScreen/strings.xml
+++ b/tests/DpiTest/res/values-normal/strings.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <string name="act_title">DpiTest: Large Screen</string>
+    <string name="act_title">DpiTest: Normal</string>
 </resources>
diff --git a/tests/DpiTest/res/values-normalScreen/strings.xml b/tests/DpiTest/res/values-normalScreen/strings.xml
deleted file mode 100644
index 256d696..0000000
--- a/tests/DpiTest/res/values-normalScreen/strings.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?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-largeScreen/strings.xml b/tests/DpiTest/res/values-notlong/strings.xml
similarity index 91%
copy from tests/DpiTest/res/values-largeScreen/strings.xml
copy to tests/DpiTest/res/values-notlong/strings.xml
index f4dd543..4b9d5da 100644
--- a/tests/DpiTest/res/values-largeScreen/strings.xml
+++ b/tests/DpiTest/res/values-notlong/strings.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <string name="act_title">DpiTest: Large Screen</string>
+    <string name="act_title">DpiTest: NotLong</string>
 </resources>
diff --git a/tests/DpiTest/res/values-largeScreen/strings.xml b/tests/DpiTest/res/values-small-long/strings.xml
similarity index 91%
copy from tests/DpiTest/res/values-largeScreen/strings.xml
copy to tests/DpiTest/res/values-small-long/strings.xml
index f4dd543..2575b0d 100644
--- a/tests/DpiTest/res/values-largeScreen/strings.xml
+++ b/tests/DpiTest/res/values-small-long/strings.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <string name="act_title">DpiTest: Large Screen</string>
+    <string name="act_title">DpiTest: Small Long</string>
 </resources>
diff --git a/tests/DpiTest/res/values-largeScreen/strings.xml b/tests/DpiTest/res/values-small-notlong/strings.xml
similarity index 91%
copy from tests/DpiTest/res/values-largeScreen/strings.xml
copy to tests/DpiTest/res/values-small-notlong/strings.xml
index f4dd543..2df2b29 100644
--- a/tests/DpiTest/res/values-largeScreen/strings.xml
+++ b/tests/DpiTest/res/values-small-notlong/strings.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <string name="act_title">DpiTest: Large Screen</string>
+    <string name="act_title">DpiTest: Small NotLong</string>
 </resources>
diff --git a/tests/DpiTest/res/values-largeScreen/strings.xml b/tests/DpiTest/res/values-small/strings.xml
similarity index 91%
copy from tests/DpiTest/res/values-largeScreen/strings.xml
copy to tests/DpiTest/res/values-small/strings.xml
index f4dd543..9fd5e40 100644
--- a/tests/DpiTest/res/values-largeScreen/strings.xml
+++ b/tests/DpiTest/res/values-small/strings.xml
@@ -15,5 +15,5 @@
 -->
 
 <resources>
-    <string name="act_title">DpiTest: Large Screen</string>
+    <string name="act_title">DpiTest: Small</string>
 </resources>
diff --git a/tests/DpiTest/res/values-smallScreen/strings.xml b/tests/DpiTest/res/values-smallScreen/strings.xml
deleted file mode 100644
index cdb4ac9..0000000
--- a/tests/DpiTest/res/values-smallScreen/strings.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?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/src/com/google/android/test/dpi/DpiTestActivity.java b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
index 8c69305..dd4fae3 100644
--- a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
+++ b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
@@ -52,13 +52,13 @@
             // be doing it.
             Application app = ActivityThread.currentActivityThread().getApplication();
             ApplicationInfo ai = app.getPackageManager().getApplicationInfo(
-                    "com.google.android.test.dpi",
-                    PackageManager.GET_SUPPORTS_DENSITIES);
+                    "com.google.android.test.dpi", 0);
             if (noCompat) {
                 ai.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS
                     | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS
-                    | ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
-                ai.supportsDensities = new int[] { ApplicationInfo.ANY_DENSITY };
+                    | ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS
+                    | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS
+                    | ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
                 app.getResources().setCompatibilityInfo(new CompatibilityInfo(ai));
             }
         } catch (PackageManager.NameNotFoundException e) {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
index 39ce1f2..97a8b25 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
@@ -341,7 +341,7 @@
     }
 
     public void clearAllDatabases() {
-        WebStorage.getInstance().deleteAllDatabases();
+        WebStorage.getInstance().deleteAllData();
     }
 
     public void setDatabaseQuota(long quota) {
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 14cad2f..dbcef6d 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -138,6 +138,20 @@
         return 0;
     }
 
+    // screen layout size
+    if (getScreenLayoutSizeName(part.string(), &config)) {
+        *axis = AXIS_SCREENLAYOUTSIZE;
+        *value = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
+        return 0;
+    }
+
+    // screen layout long
+    if (getScreenLayoutLongName(part.string(), &config)) {
+        *axis = AXIS_SCREENLAYOUTLONG;
+        *value = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
+        return 0;
+    }
+
     // orientation
     if (getOrientationName(part.string(), &config)) {
         *axis = AXIS_ORIENTATION;
@@ -187,13 +201,6 @@
         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;
@@ -209,7 +216,8 @@
 {
     Vector<String8> parts;
 
-    String8 mcc, mnc, loc, orient, den, touch, key, keysHidden, nav, size, layout, vers;
+    String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
+    String8 touch, key, keysHidden, nav, size, vers;
 
     const char *p = dir;
     const char *q;
@@ -296,6 +304,30 @@
         //printf("not region: %s\n", part.string());
     }
 
+    if (getScreenLayoutSizeName(part.string())) {
+        layoutsize = part;
+
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index];
+    } else {
+        //printf("not screen layout size: %s\n", part.string());
+    }
+
+    if (getScreenLayoutLongName(part.string())) {
+        layoutlong = part;
+
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index];
+    } else {
+        //printf("not screen layout long: %s\n", part.string());
+    }
+
     // orientation
     if (getOrientationName(part.string())) {
         orient = part;
@@ -385,18 +417,6 @@
         //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;
 
@@ -416,6 +436,8 @@
     this->mcc = mcc;
     this->mnc = mnc;
     this->locale = loc;
+    this->screenLayoutSize = layoutsize;
+    this->screenLayoutLong = layoutlong;
     this->orientation = orient;
     this->density = den;
     this->touchscreen = touch;
@@ -423,7 +445,6 @@
     this->keyboard = key;
     this->navigation = nav;
     this->screenSize = size;
-    this->screenLayout = layout;
     this->version = vers;
 
     // what is this anyway?
@@ -441,6 +462,10 @@
     s += ",";
     s += this->locale;
     s += ",";
+    s += screenLayoutSize;
+    s += ",";
+    s += screenLayoutLong;
+    s += ",";
     s += this->orientation;
     s += ",";
     s += density;
@@ -455,8 +480,6 @@
     s += ",";
     s += screenSize;
     s += ",";
-    s += screenLayout;
-    s += ",";
     s += version;
     return s;
 }
@@ -477,6 +500,14 @@
         s += "-";
         s += locale;
     }
+    if (this->screenLayoutSize != "") {
+        s += "-";
+        s += screenLayoutSize;
+    }
+    if (this->screenLayoutLong != "") {
+        s += "-";
+        s += screenLayoutLong;
+    }
     if (this->orientation != "") {
         s += "-";
         s += orientation;
@@ -505,10 +536,6 @@
         s += "-";
         s += screenSize;
     }
-    if (this->screenLayout != "") {
-        s += "-";
-        s += screenLayout;
-    }
     if (this->version != "") {
         s += "-";
         s += version;
@@ -630,6 +657,57 @@
     return false;
 }
 
+bool AaptGroupEntry::getScreenLayoutSizeName(const char* name,
+                                     ResTable_config* out)
+{
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
+                | ResTable_config::SCREENSIZE_ANY;
+        return true;
+    } else if (strcmp(name, "small") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
+                | ResTable_config::SCREENSIZE_SMALL;
+        return true;
+    } else if (strcmp(name, "normal") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
+                | ResTable_config::SCREENSIZE_NORMAL;
+        return true;
+    } else if (strcmp(name, "large") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
+                | ResTable_config::SCREENSIZE_LARGE;
+        return true;
+    }
+
+    return false;
+}
+
+bool AaptGroupEntry::getScreenLayoutLongName(const char* name,
+                                     ResTable_config* out)
+{
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
+                | ResTable_config::SCREENLONG_ANY;
+        return true;
+    } else if (strcmp(name, "long") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
+                | ResTable_config::SCREENLONG_YES;
+        return true;
+    } else if (strcmp(name, "notlong") == 0) {
+        if (out) out->screenLayout =
+                (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
+                | ResTable_config::SCREENLONG_NO;
+        return true;
+    }
+
+    return false;
+}
+
 bool AaptGroupEntry::getOrientationName(const char* name,
                                         ResTable_config* out)
 {
@@ -663,6 +741,21 @@
         return true;
     }
     
+    if (strcmp(name, "ldpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_LOW;
+        return true;
+    }
+    
+    if (strcmp(name, "mdpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_MEDIUM;
+        return true;
+    }
+    
+    if (strcmp(name, "hdpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_HIGH;
+        return true;
+    }
+    
     char* c = (char*)name;
     while (*c >= '0' && *c <= '9') {
         c++;
@@ -818,26 +911,6 @@
     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)
 {
@@ -873,6 +946,8 @@
     if (v == 0) v = mnc.compare(o.mnc);
     if (v == 0) v = locale.compare(o.locale);
     if (v == 0) v = vendor.compare(o.vendor);
+    if (v == 0) v = screenLayoutSize.compare(o.screenLayoutSize);
+    if (v == 0) v = screenLayoutLong.compare(o.screenLayoutLong);
     if (v == 0) v = orientation.compare(o.orientation);
     if (v == 0) v = density.compare(o.density);
     if (v == 0) v = touchscreen.compare(o.touchscreen);
@@ -880,7 +955,6 @@
     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;
 }
@@ -892,6 +966,8 @@
     getMccName(mcc.string(), &params);
     getMncName(mnc.string(), &params);
     getLocaleName(locale.string(), &params);
+    getScreenLayoutSizeName(screenLayoutSize.string(), &params);
+    getScreenLayoutLongName(screenLayoutLong.string(), &params);
     getOrientationName(orientation.string(), &params);
     getDensityName(density.string(), &params);
     getTouchscreenName(touchscreen.string(), &params);
@@ -899,7 +975,6 @@
     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 e8c7395..5724349 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -30,6 +30,8 @@
     AXIS_MNC,
     AXIS_LANGUAGE,
     AXIS_REGION,
+    AXIS_SCREENLAYOUTSIZE,
+    AXIS_SCREENLAYOUTLONG,
     AXIS_ORIENTATION,
     AXIS_DENSITY,
     AXIS_TOUCHSCREEN,
@@ -37,7 +39,6 @@
     AXIS_KEYBOARD,
     AXIS_NAVIGATION,
     AXIS_SCREENSIZE,
-    AXIS_SCREENLAYOUT,
     AXIS_VERSION
 };
 
@@ -56,6 +57,8 @@
     String8 mnc;
     String8 locale;
     String8 vendor;
+    String8 screenLayoutSize;
+    String8 screenLayoutLong;
     String8 orientation;
     String8 density;
     String8 touchscreen;
@@ -63,7 +66,6 @@
     String8 keyboard;
     String8 navigation;
     String8 screenSize;
-    String8 screenLayout;
     String8 version;
 
     bool initFromDirName(const char* dir, String8* resType);
@@ -73,6 +75,8 @@
     static bool getMccName(const char* name, ResTable_config* out = NULL);
     static bool getMncName(const char* name, ResTable_config* out = NULL);
     static bool getLocaleName(const char* name, ResTable_config* out = NULL);
+    static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL);
+    static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL);
     static bool getOrientationName(const char* name, ResTable_config* out = NULL);
     static bool getDensityName(const char* name, ResTable_config* out = NULL);
     static bool getTouchscreenName(const char* name, ResTable_config* out = NULL);
@@ -80,7 +84,6 @@
     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/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
index 48998db..10421de 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
@@ -39,7 +39,7 @@
  * TODO: describe.
  */
 public final class BridgeTypedArray extends TypedArray {
-    
+
     @SuppressWarnings("hiding")
     private BridgeResources mResources;
     private BridgeContext mContext;
@@ -47,7 +47,7 @@
     private IResourceValue[] mData;
     private String[] mNames;
     private final boolean mPlatformFile;
-    
+
     public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
             boolean platformFile) {
         super(null, null, null, 0);
@@ -58,12 +58,12 @@
         mNames = new String[len];
     }
 
-    /** A bridge-specific method that sets a value in the type array */ 
+    /** A bridge-specific method that sets a value in the type array */
     public void bridgeSetValue(int index, String name, IResourceValue value) {
         mData[index] = value;
         mNames[index] = name;
     }
-    
+
     /**
      * Seals the array after all calls to {@link #bridgeSetValue(int, String, IResourceValue)} have
      * been done.
@@ -79,11 +79,11 @@
                 count++;
             }
         }
-        
+
         // allocate the table with an extra to store the size
         mIndices = new int[count+1];
         mIndices[0] = count;
-        
+
         // fill the array with the indices.
         int index = 1;
         for (int i = 0 ; i < mData.length ; i++) {
@@ -100,7 +100,7 @@
     public int length() {
         return mData.length;
     }
-    
+
     /**
      * Return the Resources object this array was loaded from.
      */
@@ -108,13 +108,13 @@
     public Resources getResources() {
         return mResources;
     }
-    
+
     /**
      * Retrieve the styled string value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
-     * @return CharSequence holding string data.  May be styled.  Returns 
+     *
+     * @return CharSequence holding string data.  May be styled.  Returns
      *         null if the attribute is not defined.
      */
     @Override
@@ -129,9 +129,9 @@
 
     /**
      * Retrieve the string value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return String holding string data.  Any styling information is
      * removed.  Returns null if the attribute is not defined.
      */
@@ -140,16 +140,16 @@
         if (mData[index] != null) {
             return mData[index].getValue();
         }
-        
+
         return null;
     }
 
     /**
      * Retrieve the boolean value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined.
-     * 
+     *
      * @return Attribute boolean value, or defValue if not defined.
      */
     @Override
@@ -162,16 +162,16 @@
         if (s != null) {
             return XmlUtils.convertValueToBoolean(s, defValue);
         }
-        
+
         return defValue;
     }
 
     /**
      * Retrieve the integer value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined.
-     * 
+     *
      * @return Attribute int value, or defValue if not defined.
      */
     @Override
@@ -181,7 +181,7 @@
         }
 
         String s = mData[index].getValue();
-        
+
         try {
             return (s == null) ? defValue : XmlUtils.convertValueToInt(s, defValue);
         } catch (NumberFormatException e) {
@@ -192,11 +192,11 @@
         // Check for possible constants and try to find them.
         // Get the map of attribute-constant -> IntegerValue
         Map<String, Integer> map = Bridge.getEnumValues(mNames[index]);
-        
+
         if (map != null) {
             // accumulator to store the value of the 1+ constants.
             int result = 0;
-            
+
             // split the value in case this is a mix of several flags.
             String[] keywords = s.split("\\|");
             for (String keyword : keywords) {
@@ -217,9 +217,9 @@
 
     /**
      * Retrieve the float value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return Attribute float value, or defValue if not defined..
      */
     @Override
@@ -237,23 +237,23 @@
                 mContext.getLogger().warning(String.format(
                         "Unable to convert \"%s\" into a float in attribute \"%2$s\"",
                         s, mNames[index]));
-                
+
                 // we'll return the default value below.
             }
         }
         return defValue;
     }
-    
+
     /**
      * Retrieve the color value for the attribute at <var>index</var>.  If
      * the attribute references a color resource holding a complex
      * {@link android.content.res.ColorStateList}, then the default color from
      * the set is returned.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
+     *
      * @return Attribute color value, or defValue if not defined.
      */
     @Override
@@ -261,7 +261,7 @@
         if (mData[index] == null) {
             return defValue;
         }
-        
+
         String s = mData[index].getValue();
         try {
             return ResourceHelper.getColor(s);
@@ -280,9 +280,9 @@
      * Retrieve the ColorStateList for the attribute at <var>index</var>.
      * The value may be either a single solid color or a reference to
      * a color or complex {@link android.content.res.ColorStateList} description.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return ColorStateList for the attribute, or null if not defined.
      */
     @Override
@@ -296,14 +296,14 @@
         if (value == null) {
             return null;
         }
-        
+
         try {
             int color = ResourceHelper.getColor(value);
             return ColorStateList.valueOf(color);
         } catch (NumberFormatException e) {
             // if it's not a color value, we'll attempt to read the xml based color below.
         }
-        
+
         // let the framework inflate the ColorStateList from the XML file.
         try {
             File f = new File(value);
@@ -311,7 +311,7 @@
                 KXmlParser parser = new KXmlParser();
                 parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
                 parser.setInput(new FileReader(f));
-                
+
                 ColorStateList colorStateList = ColorStateList.createFromXml(
                         mContext.getResources(),
                         // FIXME: we need to know if this resource is platform or not
@@ -325,22 +325,22 @@
 
             // return null below.
         }
-        
+
         // looks like were unable to resolve the color value.
         mContext.getLogger().warning(String.format(
                 "Unable to resolve color value \"%1$s\" in attribute \"%2$s\"",
                 value, mNames[index]));
-        
+
         return null;
     }
-    
+
     /**
      * Retrieve the integer value for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
+     *
      * @return Attribute integer value, or defValue if not defined.
      */
     @Override
@@ -362,23 +362,23 @@
                 // The default value is returned below.
             }
         }
-        
+
         return defValue;
     }
 
     /**
-     * Retrieve a dimensional unit attribute at <var>index</var>.  Unit 
-     * conversions are based on the current {@link DisplayMetrics} 
-     * associated with the resources this {@link TypedArray} object 
-     * came from. 
-     * 
+     * Retrieve a dimensional unit attribute at <var>index</var>.  Unit
+     * conversions are based on the current {@link DisplayMetrics}
+     * associated with the resources this {@link TypedArray} object
+     * came from.
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric, or defValue if not defined.
-     * 
+     *
      * @see #getDimensionPixelOffset
      * @see #getDimensionPixelSize
      */
@@ -397,11 +397,11 @@
         } else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
             return LayoutParams.WRAP_CONTENT;
         }
-        
+
         if (ResourceHelper.stringToFloat(s, mValue)) {
             return mValue.getDimension(mResources.mMetrics);
         }
-        
+
         // looks like we were unable to resolve the dimension value
         mContext.getLogger().warning(String.format(
                 "Unable to resolve dimension value \"%1$s\" in attribute \"%2$s\"",
@@ -416,14 +416,14 @@
      * {@link #getDimension}, except the returned value is converted to
      * integer pixels for you.  An offset conversion involves simply
      * truncating the base value to an integer.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric and truncated to integer pixels, or defValue if not defined.
-     * 
+     *
      * @see #getDimension
      * @see #getDimensionPixelSize
      */
@@ -439,14 +439,14 @@
      * integer pixels for use as a size.  A size conversion involves
      * rounding the base value, and ensuring that a non-zero base value
      * is at least one pixel in size.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric and truncated to integer pixels, or defValue if not defined.
-     *  
+     *
      * @see #getDimension
      * @see #getDimensionPixelOffset
      */
@@ -465,7 +465,7 @@
         } else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
             return LayoutParams.WRAP_CONTENT;
         }
-        
+
         // FIXME huh?
 
         float f = getDimension(index, defValue);
@@ -483,11 +483,11 @@
      * {@link android.view.ViewGroup}'s layout_width and layout_height
      * attributes.  This is only here for performance reasons; applications
      * should use {@link #getDimensionPixelSize}.
-     * 
+     *
      * @param index Index of the attribute to retrieve.
      * @param name Textual name of attribute for error reporting.
-     * 
-     * @return Attribute dimension value multiplied by the appropriate 
+     *
+     * @return Attribute dimension value multiplied by the appropriate
      * metric and truncated to integer pixels.
      */
     @Override
@@ -495,20 +495,25 @@
         return getDimensionPixelSize(index, 0);
     }
 
+    @Override
+    public int getLayoutDimension(int index, int defValue) {
+        return getDimensionPixelSize(index, defValue);
+    }
+
     /**
      * Retrieve a fractional unit attribute at <var>index</var>.
-     * 
-     * @param index Index of attribute to retrieve. 
-     * @param base The base value of this fraction.  In other words, a 
+     *
+     * @param index Index of attribute to retrieve.
+     * @param base The base value of this fraction.  In other words, a
      *             standard fraction is multiplied by this value.
-     * @param pbase The parent base value of this fraction.  In other 
+     * @param pbase The parent base value of this fraction.  In other
      *             words, a parent fraction (nn%p) is multiplied by this
      *             value.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
-     * @return Attribute fractional value multiplied by the appropriate 
-     * base value, or defValue if not defined. 
+     *
+     * @return Attribute fractional value multiplied by the appropriate
+     * base value, or defValue if not defined.
      */
     @Override
     public float getFraction(int index, int base, int pbase, float defValue) {
@@ -520,7 +525,7 @@
         if (value == null) {
             return defValue;
         }
-        
+
         if (ResourceHelper.stringToFloat(value, mValue)) {
             return mValue.getFraction(base, pbase);
         }
@@ -529,29 +534,29 @@
         mContext.getLogger().warning(String.format(
                 "Unable to resolve fraction value \"%1$s\" in attribute \"%2$s\"",
                 value, mNames[index]));
-        
+
         return defValue;
     }
 
     /**
      * Retrieve the resource identifier for the attribute at
-     * <var>index</var>.  Note that attribute resource as resolved when 
-     * the overall {@link TypedArray} object is retrieved.  As a 
-     * result, this function will return the resource identifier of the 
-     * final resource value that was found, <em>not</em> necessarily the 
-     * original resource that was specified by the attribute. 
-     * 
+     * <var>index</var>.  Note that attribute resource as resolved when
+     * the overall {@link TypedArray} object is retrieved.  As a
+     * result, this function will return the resource identifier of the
+     * final resource value that was found, <em>not</em> necessarily the
+     * original resource that was specified by the attribute.
+     *
      * @param index Index of attribute to retrieve.
      * @param defValue Value to return if the attribute is not defined or
      *                 not a resource.
-     * 
+     *
      * @return Attribute resource identifier, or defValue if not defined.
      */
     @Override
     public int getResourceId(int index, int defValue) {
         // get the IResource for this index
         IResourceValue resValue = mData[index];
-        
+
         // no data, return the default value.
         if (resValue == null) {
             return defValue;
@@ -562,7 +567,7 @@
             // get the id that will represent this style.
             return mContext.getDynamicIdByStyle((IStyleResourceValue)resValue);
         }
-        
+
         // if the attribute was a reference to an id, and not a declaration of an id (@+id), then
         // the xml attribute value was "resolved" which leads us to a IResourceValue with
         // getType() returning "id" and getName() returning the id name
@@ -583,7 +588,7 @@
         if (value == null) {
             return defValue;
         }
-        
+
         // if the value is just an integer, return it.
         try {
             int i = Integer.parseInt(value);
@@ -601,14 +606,14 @@
         // fact in the android.R and com.android.internal.R classes.
         // The field mPlatformFile will indicate that all IDs are to be looked up in the android R
         // classes exclusively.
-        
+
         // if this is a reference to an id, find it.
         if (value.startsWith("@id/") || value.startsWith("@+") ||
                 value.startsWith("@android:id/")) {
-            
+
             int pos = value.indexOf('/');
             String idName = value.substring(pos + 1);
-            
+
             // if this is a framework id
             if (mPlatformFile || value.startsWith("@android") || value.startsWith("@+android")) {
                 // look for idName in the android R classes
@@ -621,7 +626,7 @@
 
         // not a direct id valid reference? resolve it
         Integer idValue = null;
-        
+
         if (resValue.isFramework()) {
             idValue = Bridge.getResourceValue(resValue.getType(), resValue.getName());
         } else {
@@ -632,7 +637,7 @@
         if (idValue != null) {
             return idValue.intValue();
         }
-        
+
         mContext.getLogger().warning(String.format(
                 "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]));
         return defValue;
@@ -643,9 +648,9 @@
      * gets the resource ID of the selected attribute, and uses
      * {@link Resources#getDrawable Resources.getDrawable} of the owning
      * Resources object to retrieve its Drawable.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return Drawable for the attribute, or null if not defined.
      */
     @Override
@@ -658,13 +663,13 @@
         if (value == null || BridgeConstants.REFERENCE_NULL.equals(value)) {
             return null;
         }
-        
+
         Drawable d = ResourceHelper.getDrawable(value, mContext, mData[index].isFramework());
-        
+
         if (d != null) {
             return d;
         }
-        
+
         // looks like we were unable to resolve the drawable
         mContext.getLogger().warning(String.format(
                 "Unable to resolve drawable \"%1$s\" in attribute \"%2$s\"", value, mNames[index]));
@@ -678,9 +683,9 @@
      * This gets the resource ID of the selected attribute, and uses
      * {@link Resources#getTextArray Resources.getTextArray} of the owning
      * Resources object to retrieve its String[].
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return CharSequence[] for the attribute, or null if not defined.
      */
     @Override
@@ -693,7 +698,7 @@
         if (value != null) {
             return new CharSequence[] { value };
         }
-        
+
         mContext.getLogger().warning(String.format(
                 String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
                 index, mData[index].getName())));
@@ -703,44 +708,44 @@
 
     /**
      * Retrieve the raw TypedValue for the attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
      * @param outValue TypedValue object in which to place the attribute's
      *                 data.
-     * 
-     * @return Returns true if the value was retrieved, else false. 
+     *
+     * @return Returns true if the value was retrieved, else false.
      */
     @Override
     public boolean getValue(int index, TypedValue outValue) {
         if (mData[index] == null) {
             return false;
         }
-        
+
         String s = mData[index].getValue();
-        
+
         return ResourceHelper.stringToFloat(s, outValue);
     }
 
     /**
      * Determines whether there is an attribute at <var>index</var>.
-     * 
+     *
      * @param index Index of attribute to retrieve.
-     * 
+     *
      * @return True if the attribute has a value, false otherwise.
      */
     @Override
     public boolean hasValue(int index) {
         return mData[index] != null;
     }
-    
+
     /**
-     * Retrieve the raw TypedValue for the attribute at <var>index</var> 
-     * and return a temporary object holding its data.  This object is only 
-     * valid until the next call on to {@link TypedArray}. 
-     * 
+     * Retrieve the raw TypedValue for the attribute at <var>index</var>
+     * and return a temporary object holding its data.  This object is only
+     * valid until the next call on to {@link TypedArray}.
+     *
      * @param index Index of attribute to retrieve.
-     * 
-     * @return Returns a TypedValue object if the attribute is defined, 
+     *
+     * @return Returns a TypedValue object if the attribute is defined,
      *         containing its data; otherwise returns null.  (You will not
      *         receive a TypedValue whose type is TYPE_NULL.)
      */
@@ -749,7 +754,7 @@
         if (getValue(index, mValue)) {
             return mValue;
         }
-        
+
         return null;
     }
 
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index eda2f2d..f85aadd 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -45,6 +45,8 @@
     /** {@hide} */
     public static final String eapVarName = "eap";
     /** {@hide} */
+    public static final String phase2VarName = "phase2";
+    /** {@hide} */
     public static final String identityVarName = "identity";
     /** {@hide} */
     public static final String anonymousIdentityVarName = "anonymous_identity";
@@ -273,6 +275,11 @@
      */
     public String eap;
     /**
+     * The phase2 authenication could be PAP, MSCHAP, MSCHAP2, GTC.
+     * {@hide}
+     */
+    public String phase2;
+    /**
      * The identity of the user in string,
      * which is used for the authentication.
      * {@hide}
@@ -314,6 +321,7 @@
         for (int i = 0; i < wepKeys.length; i++)
             wepKeys[i] = null;
         eap = null;
+        phase2 = null;
         identity = null;
         anonymousIdentity = null;
         password = null;
@@ -399,6 +407,10 @@
         if (this.eap != null) {
             sbuf.append(eap);
         }
+        sbuf.append('\n').append(" phase2: ");
+        if (this.phase2 != null) {
+            sbuf.append(phase2);
+        }
         sbuf.append('\n').append(" Identity: ");
         if (this.identity != null) {
             sbuf.append(identity);
@@ -486,6 +498,7 @@
         writeBitSet(dest, allowedPairwiseCiphers);
         writeBitSet(dest, allowedGroupCiphers);
         dest.writeString(eap);
+        dest.writeString(phase2);
         dest.writeString(identity);
         dest.writeString(anonymousIdentity);
         dest.writeString(password);
@@ -516,6 +529,7 @@
                 config.allowedPairwiseCiphers = readBitSet(in);
                 config.allowedGroupCiphers    = readBitSet(in);
                 config.eap = in.readString();
+                config.phase2 = in.readString();
                 config.identity = in.readString();
                 config.anonymousIdentity = in.readString();
                 config.password = in.readString();