Merge change 3305 into donut

* changes:
  Fix parameter mismatch for a couple of RIL commands.
diff --git a/api/current.xml b/api/current.xml
index 9e9eaad4..69660d6 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -34943,6 +34943,16 @@
  visibility="public"
 >
 </field>
+<field name="expandable"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="flags"
  type="int"
  transient="false"
@@ -36787,6 +36797,17 @@
  visibility="public"
 >
 </field>
+<field name="GET_EXPANDABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="131072"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="GET_GIDS"
  type="int"
  transient="false"
@@ -48750,6 +48771,16 @@
  visibility="public"
 >
 </field>
+<field name="inInputShareable"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="inJustDecodeBounds"
  type="boolean"
  transient="false"
@@ -107249,6 +107280,50 @@
  visibility="public"
 >
 </field>
+<field name="TTS_DEFAULT_PITCH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;tts_default_pitch&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_DEFAULT_RATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;tts_default_rate&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_DEFAULT_SYNTH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;tts_default_synth&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_USE_DEFAULTS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;tts_use_defaults&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="USB_MASS_STORAGE_ENABLED"
  type="java.lang.String"
  transient="false"
@@ -108297,6 +108372,17 @@
  visibility="public"
 >
 </field>
+<field name="SHOW_WEB_SUGGESTIONS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;show_web_suggestions&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SOUND_EFFECTS_ENABLED"
  type="java.lang.String"
  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 88ad265..2a4a672 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -526,7 +526,7 @@
 
     private void showUsage() {
         System.err.println("usage: am [start|broadcast|instrument|profile]");
-        System.err.println("       am start -D INTENT");
+        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> ");
diff --git a/cmds/backup/backup.cpp b/cmds/backup/backup.cpp
index 51ac943..22dd486 100644
--- a/cmds/backup/backup.cpp
+++ b/cmds/backup/backup.cpp
@@ -1,5 +1,20 @@
+/*
+ * 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.
+ */
 
-#include <utils/backup_helpers.h>
+#include <utils/BackupHelpers.h>
 #include <utils/String8.h>
 
 #include <fcntl.h>
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 29e57cd..d08fc11 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -162,7 +162,7 @@
         return metrics;
     }
 
-    Resources getTopLevelResources(String appDir, float applicationScale) {
+    Resources getTopLevelResources(String appDir, PackageInfo pkgInfo) {
         synchronized (mPackages) {
             //Log.w(TAG, "getTopLevelResources: " + appDir);
             WeakReference<Resources> wr = mActiveResources.get(appDir);
@@ -181,23 +181,17 @@
             if (assets.addAssetPath(appDir) == 0) {
                 return null;
             }
-            DisplayMetrics metrics = getDisplayMetricsLocked(false);
-            // density used to load resources
-            // scaledDensity is calculated in Resources constructor
-            //
-            boolean usePreloaded = true;
-
-            // TODO: use explicit flag to indicate the compatibility mode.
-            if (applicationScale != 1.0f) {
-                usePreloaded = false;
-                DisplayMetrics newMetrics = new DisplayMetrics();
-                newMetrics.setTo(metrics);
-                float newDensity = metrics.density / applicationScale;
-                newMetrics.updateDensity(newDensity);
-                metrics = newMetrics;
+            ApplicationInfo appInfo;
+            try {
+                appInfo = getPackageManager().getApplicationInfo(
+                        pkgInfo.getPackageName(),
+                        PackageManager.GET_SUPPORTS_DENSITIES | PackageManager.GET_EXPANDABLE);
+            } catch (RemoteException e) {
+                throw new AssertionError(e);
             }
             //Log.i(TAG, "Resource:" + appDir + ", display metrics=" + metrics);
-            r = new Resources(assets, metrics, getConfiguration(), usePreloaded);
+            DisplayMetrics metrics = getDisplayMetricsLocked(false);
+            r = new Resources(assets, metrics, getConfiguration(), appInfo);
             //Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration());
             // XXX need to remove entries when weak references go away
             mActiveResources.put(appDir, new WeakReference<Resources>(r));
@@ -225,7 +219,6 @@
         private Resources mResources;
         private ClassLoader mClassLoader;
         private Application mApplication;
-        private float mApplicationScale;
 
         private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
             = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
@@ -268,8 +261,6 @@
                 mClassLoader = mSystemContext.getClassLoader();
                 mResources = mSystemContext.getResources();
             }
-
-            mApplicationScale = -1.0f;
         }
 
         public PackageInfo(ActivityThread activityThread, String name,
@@ -288,7 +279,6 @@
             mIncludeCode = true;
             mClassLoader = systemContext.getClassLoader();
             mResources = systemContext.getResources();
-            mApplicationScale = systemContext.getApplicationScale();
         }
 
         public String getPackageName() {
@@ -299,45 +289,6 @@
             return mSecurityViolation;
         }
 
-        public float getApplicationScale() {
-            if (mApplicationScale > 0.0f) {
-                return mApplicationScale;
-            }
-            DisplayMetrics metrics = mActivityThread.getDisplayMetricsLocked(false);
-            // Find out the density scale (relative to 160) of the supported density  that
-            // is closest to the system's density.
-            try {
-                ApplicationInfo ai = getPackageManager().getApplicationInfo(
-                        mPackageName, PackageManager.GET_SUPPORTS_DENSITIES);
-
-                float appScale = -1.0f;
-                if (ai.supportsDensities != null) {
-                    int minDiff = Integer.MAX_VALUE;
-                    for (int density : ai.supportsDensities) {
-                        int tmpDiff = (int) Math.abs(DisplayMetrics.DEVICE_DENSITY - density);
-                        if (tmpDiff == 0) {
-                            appScale = 1.0f;
-                            break;
-                        }
-                        // prefer higher density (appScale>1.0), unless that's only option.
-                        if (tmpDiff < minDiff && appScale < 1.0f) {
-                            appScale = DisplayMetrics.DEVICE_DENSITY / density;
-                            minDiff = tmpDiff;
-                        }
-                    }
-                }
-                if (appScale < 0.0f) {
-                    mApplicationScale = metrics.density;
-                } else {
-                    mApplicationScale = appScale;
-                }
-            } catch (RemoteException e) {
-                throw new AssertionError(e);
-            }
-            if (localLOGV) Log.v(TAG, "appScale=" + mApplicationScale + ", pkg=" + mPackageName);
-            return mApplicationScale;
-        }
-
         /**
          * Gets the array of shared libraries that are listed as
          * used by the given package.
@@ -495,7 +446,7 @@
 
         public Resources getResources(ActivityThread mainThread) {
             if (mResources == null) {
-                mResources = mainThread.getTopLevelResources(mResDir, getApplicationScale());
+                mResources = mainThread.getTopLevelResources(mResDir, this);
             }
             return mResources;
         }
@@ -3606,8 +3557,6 @@
             }
             mConfiguration.updateFrom(config);
             DisplayMetrics dm = getDisplayMetricsLocked(true);
-            DisplayMetrics appDm = new DisplayMetrics();
-            appDm.setTo(dm);
 
             // set it for java, this also affects newly created Resources
             if (config.locale != null) {
@@ -3627,11 +3576,7 @@
                     WeakReference<Resources> v = it.next();
                     Resources r = v.get();
                     if (r != null) {
-                        // keep the original density based on application cale.
-                        appDm.updateDensity(r.getDisplayMetrics().density);
-                        r.updateConfiguration(config, appDm);
-                        // reset
-                        appDm.setTo(dm);
+                        r.updateConfiguration(config, dm);
                         //Log.i(TAG, "Updated app resources " + v.getKey()
                         //        + " " + r + ": " + r.getConfiguration());
                     } else {
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 2d6381a..98bbf7b 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -551,19 +551,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public float getApplicationScale() {
-        if (mPackageInfo != null) {
-            return mPackageInfo.getApplicationScale();
-        } else {
-            // same as system density
-            return 1.0f;
-        }
-    }
-
     @Override
     public void setWallpaper(Bitmap bitmap) throws IOException  {
         try {
@@ -2028,8 +2015,7 @@
             ActivityThread.PackageInfo pi = mContext.mMainThread.getPackageInfoNoCheck(app);
             Resources r = mContext.mMainThread.getTopLevelResources(
                     app.uid == Process.myUid() ? app.sourceDir
-                    : app.publicSourceDir,
-                    pi.getApplicationScale());
+                    : app.publicSourceDir, pi);
             if (r != null) {
                 return r;
             }
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index e28fd0f..6750d12 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -350,6 +350,14 @@
             scheduleCreateBackupAgent(appInfo, backupMode);
             return true;
         }
+
+        case SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION:
+        {
+            data.enforceInterface(IApplicationThread.descriptor);
+            ApplicationInfo appInfo = ApplicationInfo.CREATOR.createFromParcel(data);
+            scheduleDestroyBackupAgent(appInfo);
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index 39eb4f1..374423e 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -23,4 +23,7 @@
 interface ISearchManager {
    SearchableInfo getSearchableInfo(in ComponentName launchActivity, boolean globalSearch);
    List<SearchableInfo> getSearchablesInGlobalSearch();
+   List<SearchableInfo> getSearchablesForWebSearch();
+   SearchableInfo getDefaultSearchableForWebSearch();
+   void setDefaultWebSearch(in ComponentName component);
 }
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index bcb2791..0bb483b 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -1202,16 +1202,7 @@
     protected boolean launchSuggestion(int position, int actionKey, String actionMsg) {
         Cursor c = mSuggestionsAdapter.getCursor();
         if ((c != null) && c.moveToPosition(position)) {
-            // let the cursor know which position was clicked
-            final Bundle clickResponse = new Bundle(1);
-            clickResponse.putInt(SearchManager.RESPOND_EXTRA_POSITION_CLICKED, position);
-            final Bundle response = c.respond(clickResponse);
-
-            // the convention is to send a position to select in response to a click (if applicable)
-            final int posToSelect = response.getInt(
-                    SearchManager.RESPOND_EXTRA_POSITION_SELECTED,
-                    SuggestionsAdapter.NO_ITEM_TO_SELECT);
-            mSuggestionsAdapter.setListItemToSelect(posToSelect);            
+            mSuggestionsAdapter.callCursorOnClick(c, position);
 
             // launch the intent
             Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg);
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index b4a3a78..f1cc24a 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1167,38 +1167,50 @@
      */
     public final static String EXTRA_DATA_KEY = "intent_extra_data_key";
 
-
     /**
-     * Used by the search dialog to ask the global search provider whether there are any pending
-     * sources that have yet to respond.  Specifically, the search dialog will call
-     * {@link Cursor#respond} with a bundle containing this extra as a key, and expect the same key
-     * to be in the response, with a boolean value indicating whether there are pending sources.
+     * Defines the constants used in the communication between {@link android.app.SearchDialog} and
+     * the global search provider via {@link Cursor#respond(android.os.Bundle)}.
      *
-     * {@hide}
+     * @hide
      */
-    public final static String RESPOND_EXTRA_PENDING_SOURCES = "respond_extra_pending_sources";
+    public static class DialogCursorProtocol {
 
-    /**
-     * Used by the search dialog to tell the cursor that supplied suggestions which item was clicked
-     * before launching the intent.  The search dialog will call {@link Cursor#respond} with a
-     * bundle containing this extra as a key and the position that was clicked as the value.
-     *
-     * The response bundle will use {@link #RESPOND_EXTRA_POSITION_SELECTED} to return an int value
-     * of the index that should be selected, if applicable.
-     *
-     * {@hide}
-     */
-    public final static String RESPOND_EXTRA_POSITION_CLICKED = "respond_extra_position_clicked";
+        /**
+         * The sent bundle will contain this integer key, with a value set to one of the events
+         * below.
+         */
+        public final static String METHOD = "DialogCursorProtocol.method";
 
-    /**
-     * Used as a key in the response bundle from a call to {@link Cursor#respond} that sends the
-     * position that is clicked.
-     *
-     * @see #RESPOND_EXTRA_POSITION_CLICKED
-     *
-     * {@hide}
-     */
-    public final static String RESPOND_EXTRA_POSITION_SELECTED = "respond_extra_position_selected";
+        /**
+         * After data has been refreshed.
+         */
+        public final static int POST_REFRESH = 0;
+        public final static String POST_REFRESH_RECEIVE_ISPENDING
+                = "DialogCursorProtocol.POST_REFRESH.isPending";
+        public final static String POST_REFRESH_RECEIVE_DISPLAY_NOTIFY
+                = "DialogCursorProtocol.POST_REFRESH.displayNotify";
+
+        /**
+         * Just before closing the cursor.
+         */
+        public final static int PRE_CLOSE = 1;
+        public final static String PRE_CLOSE_SEND_MAX_DISPLAY_POS
+                = "DialogCursorProtocol.PRE_CLOSE.sendDisplayPosition";
+
+        /**
+         * When a position has been clicked.
+         */
+        public final static int CLICK = 2;
+        public final static String CLICK_SEND_POSITION
+                = "DialogCursorProtocol.CLICK.sendPosition";
+        public final static String CLICK_RECEIVE_SELECTED_POS
+                = "DialogCursorProtocol.CLICK.receiveSelectedPosition";
+
+        /**
+         * When the threshold received in {@link #POST_REFRESH_RECEIVE_DISPLAY_NOTIFY} is displayed.
+         */
+        public final static int THRESH_HIT = 3;
+    }
 
     /**
      * Intent extra data key: Use this key with Intent.ACTION_SEARCH and
@@ -1292,28 +1304,6 @@
      */
     public final static String SUGGEST_COLUMN_ICON_2 = "suggest_icon_2";
     /**
-     * Column name for suggestions cursor.  <i>Optional.</i>  If your cursor includes this column,
-     *  then all suggestions will be provided in a format that includes space for two small icons,
-     *  one at the left and one at the right of each suggestion.  The data in the column must
-     *  be a blob that contains a bitmap.
-     * 
-     * This column overrides any icon provided in the {@link #SUGGEST_COLUMN_ICON_1} column.
-     *
-     * @hide
-     */
-    public final static String SUGGEST_COLUMN_ICON_1_BITMAP = "suggest_icon_1_bitmap";
-    /**
-     * Column name for suggestions cursor.  <i>Optional.</i>  If your cursor includes this column,
-     *  then all suggestions will be provided in a format that includes space for two small icons,
-     *  one at the left and one at the right of each suggestion.  The data in the column must
-     *  be a blob that contains a bitmap.
-     * 
-     * This column overrides any icon provided in the {@link #SUGGEST_COLUMN_ICON_2} column.
-     *
-     * @hide
-     */
-    public final static String SUGGEST_COLUMN_ICON_2_BITMAP = "suggest_icon_2_bitmap";
-    /**
      * Column name for suggestions cursor.  <i>Optional.</i>  If this column exists <i>and</i>
      * this element exists at the given row, this is the action that will be used when
      * forming the suggestion's intent.  If the element is not provided, the action will be taken
@@ -1415,6 +1405,26 @@
      */
     public final static String INTENT_ACTION_SEARCH_SETTINGS 
             = "android.search.action.SEARCH_SETTINGS";
+    
+    /**
+     * 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";
+
+    /**
+     * 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";
 
     /**
      * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION},
@@ -1744,4 +1754,48 @@
             return null;
         }
     }
+
+    /**
+     * Returns a list of the searchable activities that handle web searches.
+     *
+     * @return a a list of all searchable activities that handle {@link SearchManager#ACTION_WEB_SEARCH}.
+     *
+     * @hide because SearchableInfo is not part of the API.
+     */
+    public static List<SearchableInfo> getSearchablesForWebSearch() {
+        try {
+            return sService.getSearchablesForWebSearch();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the default searchable activity for web searches.
+     *
+     * @return searchable information for the activity handling web searches by default.
+     *
+     * @hide because SearchableInfo is not part of the API.
+     */
+    public static SearchableInfo getDefaultSearchableForWebSearch() {
+        try {
+            return sService.getDefaultSearchableForWebSearch();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Sets the default searchable activity for web searches.
+     *
+     * @param component Name of the component to set as default activity for web searches.
+     *
+     * @hide
+     */
+    public static void setDefaultWebSearch(ComponentName component) {
+        try {
+            sService.setDefaultWebSearch(component);
+        } catch (RemoteException e) {
+        }
+    }
 }
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 747bec9..e515594 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -20,9 +20,6 @@
 import android.content.Context;
 import android.content.res.Resources.NotFoundException;
 import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
@@ -36,6 +33,8 @@
 import android.widget.ResourceCursorAdapter;
 import android.widget.TextView;
 
+import static android.app.SearchManager.DialogCursorProtocol;
+
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -47,15 +46,7 @@
  * @hide
  */
 class SuggestionsAdapter extends ResourceCursorAdapter {
-    // The value used to query a cursor whether it is still expecting more input,
-    // so we can correctly display (or not display) the 'working' spinner in the search dialog.
-    public static final String IS_WORKING = "isWorking";
-    
-    // The value used to tell a cursor to display the corpus selectors, if this is global
-    // search. Also returns the index of the more results item to allow the SearchDialog
-    // to tell the ListView to scroll to that list item.
-    public static final String SHOW_CORPUS_SELECTORS = "showCorpusSelectors";
-    
+
     private static final boolean DBG = false;
     private static final String LOG_TAG = "SuggestionsAdapter";
     
@@ -71,17 +62,21 @@
     private int mText2Col;
     private int mIconName1Col;
     private int mIconName2Col;
-    private int mIconBitmap1Col;
-    private int mIconBitmap2Col;
 
     // This value is stored in SuggestionsAdapter by the SearchDialog to indicate whether
     // a particular list item should be selected upon the next call to notifyDataSetChanged.
     // This is used to indicate the index of the "More results..." list item so that when
     // the data set changes after a click of "More results...", we can correctly tell the
-    // ListView to scroll to the right line item. It gets reset to NO_ITEM_TO_SELECT every time it
+    // ListView to scroll to the right line item. It gets reset to NONE every time it
     // is consumed.
-    private int mListItemToSelect = NO_ITEM_TO_SELECT;
-    static final int NO_ITEM_TO_SELECT = -1;
+    private int mListItemToSelect = NONE;
+    static final int NONE = -1;
+
+    // holds the maximum position that has been displayed to the user
+    int mMaxDisplayed = NONE;
+
+    // holds the position that, when displayed, should result in notifying the cursor
+    int mDisplayNotifyPos = NONE;
 
     public SuggestionsAdapter(Context context, SearchDialog searchDialog, SearchableInfo searchable,
             WeakHashMap<String, Drawable> outsideDrawablesCache, boolean globalSearchMode) {
@@ -132,6 +127,11 @@
     @Override
     public void changeCursor(Cursor c) {
         if (DBG) Log.d(LOG_TAG, "changeCursor(" + c + ")");
+
+        if (mCursor != null) {
+            callCursorPreClose(mCursor);
+        }
+
         super.changeCursor(c);
         if (c != null) {
             mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT);
@@ -139,42 +139,73 @@
             mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
             mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
             mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
-            mIconBitmap1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1_BITMAP);
-            mIconBitmap2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2_BITMAP);
         }
-        updateWorking();
     }
-        
+
+    /**
+     * Handle sending and receiving information associated with
+     * {@link DialogCursorProtocol#PRE_CLOSE}.
+     *
+     * @param cursor The cursor to call.
+     */
+    private void callCursorPreClose(Cursor cursor) {
+        if (!mGlobalSearchMode) return;
+        final Bundle request = new Bundle();
+        request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.PRE_CLOSE);
+        request.putInt(DialogCursorProtocol.PRE_CLOSE_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
+        final Bundle response = cursor.respond(request);
+
+        mMaxDisplayed = -1;
+    }
+
     @Override
     public void notifyDataSetChanged() {
+        if (DBG) Log.d(LOG_TAG, "notifyDataSetChanged");
         super.notifyDataSetChanged();
-        updateWorking();
-        if (mListItemToSelect != NO_ITEM_TO_SELECT) {
+
+        callCursorPostRefresh(mCursor);
+
+        // look out for the pending item we are supposed to scroll to
+        if (mListItemToSelect != NONE) {
             mSearchDialog.setListSelection(mListItemToSelect);
-            mListItemToSelect = NO_ITEM_TO_SELECT;
+            mListItemToSelect = NONE;
         }
     }
-    
-    /**
-     * Specifies the list item to select upon next call of {@link #notifyDataSetChanged()},
-     * in order to let us scroll the "More results..." list item to the top of the screen
-     * (or as close as it can get) when clicked.
-     */
-    public void setListItemToSelect(int index) {
-        mListItemToSelect = index;
-    }
-    
-    /**
-     * Updates the search dialog according to the current working status of the cursor.
-     */
-    private void updateWorking() {
-        if (!mGlobalSearchMode || mCursor == null) return;
-        
-        Bundle request = new Bundle();
-        request.putString(SearchManager.RESPOND_EXTRA_PENDING_SOURCES, "DUMMY");
-        Bundle response = mCursor.respond(request);
 
-        mSearchDialog.setWorking(response.getBoolean(SearchManager.RESPOND_EXTRA_PENDING_SOURCES));
+    /**
+     * Handle sending and receiving information associated with
+     * {@link DialogCursorProtocol#POST_REFRESH}.
+     * 
+     * @param cursor The cursor to call.
+     */
+    private void callCursorPostRefresh(Cursor cursor) {
+        if (!mGlobalSearchMode) return;
+        final Bundle request = new Bundle();
+        request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.POST_REFRESH);
+        final Bundle response = cursor.respond(request);
+
+        mSearchDialog.setWorking(
+                response.getBoolean(DialogCursorProtocol.POST_REFRESH_RECEIVE_ISPENDING, false));
+
+        mDisplayNotifyPos =
+                response.getInt(DialogCursorProtocol.POST_REFRESH_RECEIVE_DISPLAY_NOTIFY, -1);
+    }
+
+    /**
+     * Tell the cursor which position was clicked, handling sending and receiving information
+     * associated with {@link DialogCursorProtocol#CLICK}.
+     *
+     * @param cursor The cursor
+     * @param position The position that was clicked.
+     */
+    void callCursorOnClick(Cursor cursor, int position) {
+        if (!mGlobalSearchMode) return;
+        final Bundle request = new Bundle(1);
+        request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK);
+        request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position);
+        final Bundle response = cursor.respond(request);
+        mListItemToSelect = response.getInt(
+                DialogCursorProtocol.CLICK_RECEIVE_SELECTED_POS, SuggestionsAdapter.NONE);
     }
 
     /**
@@ -186,7 +217,7 @@
         v.setTag(new ChildViewCache(v));
         return v;
     }
-    
+
     /**
      * Cache of the child views of drop-drown list items, to avoid looking up the children
      * each time the contents of a list item are changed.
@@ -208,15 +239,26 @@
     @Override
     public void bindView(View view, Context context, Cursor cursor) {
         ChildViewCache views = (ChildViewCache) view.getTag();
-        boolean isHtml = false;
-        if (mFormatCol >= 0) {
-            String format = cursor.getString(mFormatCol);
-            isHtml = "html".equals(format);    
+        final int pos = cursor.getPosition();
+
+        // update the maximum position displayed since last refresh
+        if (pos > mMaxDisplayed) {
+            mMaxDisplayed = pos;
         }
+
+        // if the cursor wishes to be notified about this position, send it
+        if (mGlobalSearchMode && mDisplayNotifyPos != NONE && pos == mDisplayNotifyPos) {
+            final Bundle request = new Bundle();
+            request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.THRESH_HIT);
+            mCursor.respond(request);
+            mDisplayNotifyPos = NONE;  // only notify the first time
+        }
+
+        final boolean isHtml = mFormatCol > 0 && "html".equals(cursor.getString(mFormatCol));
         setViewText(cursor, views.mText1, mText1Col, isHtml);
         setViewText(cursor, views.mText2, mText2Col, isHtml);
-        setViewIcon(cursor, views.mIcon1, mIconBitmap1Col, mIconName1Col);
-        setViewIcon(cursor, views.mIcon2, mIconBitmap2Col, mIconName2Col);
+        setViewIcon(cursor, views.mIcon1, mIconName1Col);
+        setViewIcon(cursor, views.mIcon2, mIconName2Col);
     }
     
     private void setViewText(Cursor cursor, TextView v, int textCol, boolean isHtml) {
@@ -238,26 +280,15 @@
         }
     }
     
-    private void setViewIcon(Cursor cursor, ImageView v, int iconBitmapCol, int iconNameCol) {
+    private void setViewIcon(Cursor cursor, ImageView v, int iconNameCol) {
         if (v == null) {
             return;
         }
-        Drawable drawable = null;
-        // First try the bitmap column
-        if (iconBitmapCol >= 0) {
-            byte[] data = cursor.getBlob(iconBitmapCol);
-            if (data != null) {
-                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
-                if (bitmap != null) {
-                    drawable = new BitmapDrawable(bitmap);
-                }
-            }
+        if (iconNameCol < 0) {
+            return;
         }
-        // If there was no bitmap, try the icon resource column.
-        if (drawable == null && iconNameCol >= 0) {
-            String value = cursor.getString(iconNameCol);
-            drawable = getDrawableFromResourceValue(value);
-        }
+        String value = cursor.getString(iconNameCol);
+        Drawable drawable = getDrawableFromResourceValue(value);
         // Set the icon even if the drawable is null, since we need to clear any
         // previous icon.
         v.setImageDrawable(drawable);
@@ -418,7 +449,7 @@
      */
     public static String getColumnString(Cursor cursor, String columnName) {
         int col = cursor.getColumnIndex(columnName);
-        if (col == NO_ITEM_TO_SELECT) {
+        if (col == NONE) {
             return null;
         }
         return cursor.getString(col);
diff --git a/core/java/android/backup/BackupManager.java b/core/java/android/backup/BackupManager.java
index 6f0b2ee..30f781e 100644
--- a/core/java/android/backup/BackupManager.java
+++ b/core/java/android/backup/BackupManager.java
@@ -42,6 +42,12 @@
     private IBackupManager mService;
 
     /**
+     * Defined backup transports understood by {@link IBackupManager.selectBackupTransport}.
+     */
+    public static final int TRANSPORT_ADB = 1;
+    public static final int TRANSPORT_GOOGLE = 2;
+
+    /**
      * Constructs a BackupManager object through which the application can
      * communicate with the Android backup system.
      *
diff --git a/core/java/android/backup/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl
index 3468d70..f5b82fe 100644
--- a/core/java/android/backup/IBackupManager.aidl
+++ b/core/java/android/backup/IBackupManager.aidl
@@ -36,20 +36,28 @@
     /**
      * Notifies the Backup Manager Service that an agent has become available.  This
      * method is only invoked by the Activity Manager.
-     * !!! TODO: permission
      */
     oneway void agentConnected(String packageName, IBinder agent);
 
     /**
      * Notify the Backup Manager Service that an agent has unexpectedly gone away.
      * This method is only invoked by the Activity Manager.
-     * !!! TODO: permission
      */
     oneway void agentDisconnected(String packageName);
 
     /**
-     * Schedule a full backup of the given package.
-     * !!! TODO: permission
+     * Schedule a full backup of the given package.  Callers must hold the
+     * android.permission.BACKUP permission to use this method.
      */
     oneway void scheduleFullBackup(String packageName);
+
+    /**
+     * Specify a default backup transport.  Callers must hold the
+     * android.permission.BACKUP permission to use this method.
+     *
+     * @param transportID The ID of the transport to select.  This should be one
+     * of {@link BackupManager.TRANSPORT_GOOGLE} or {@link BackupManager.TRANSPORT_ADB}.
+     * @return The ID of the previously selected transport.
+     */
+    int selectBackupTransport(int transportID);
 }
diff --git a/core/java/android/content/AbstractTableMerger.java b/core/java/android/content/AbstractTableMerger.java
index 700f1d8..94afcee 100644
--- a/core/java/android/content/AbstractTableMerger.java
+++ b/core/java/android/content/AbstractTableMerger.java
@@ -61,8 +61,10 @@
             _SYNC_ID +"=? and " + _SYNC_ACCOUNT + "=?";
     private static final String SELECT_BY_ID = BaseColumns._ID +"=?";
 
+    // The last clause rejects events with a null _SYNC_VERSION if they've already been synced
     private static final String SELECT_UNSYNCED = ""
-            + _SYNC_DIRTY + " > 0 and (" + _SYNC_ACCOUNT + "=? or " + _SYNC_ACCOUNT + " is null)";
+            + _SYNC_DIRTY + " > 0 and (" + _SYNC_ACCOUNT + "=? or " + _SYNC_ACCOUNT + " is null) "
+            + "and (" + _SYNC_VERSION + " is not null or " + _SYNC_ACCOUNT + " is null)";
 
     public AbstractTableMerger(SQLiteDatabase database,
             String table, Uri tableURL, String deletedTable,
@@ -365,26 +367,32 @@
 
             if (!TextUtils.isEmpty(localSyncID)) {
                 // An existing server item has changed
-                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);
+                // 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;
                         }
-                        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 {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c328d1614..ec847a4 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -527,16 +527,6 @@
     public abstract int getWallpaperDesiredMinimumHeight();
 
     /**
-     * Returns the scale in which the application will be drawn on the
-     * screen. This is usually 1.0f if the application supports the device's
-     * resolution/density. This will be 1.5f, for example, if the application
-     * that supports only 160 density runs on 240 density screen.
-     *
-     * @hide
-     */
-    public abstract float getApplicationScale();
-
-    /**
      * Change the current system wallpaper to a bitmap.  The given bitmap is
      * converted to a PNG and stored as the wallpaper.  On success, the intent
      * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 25b2cae..36e1c34 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -419,12 +419,4 @@
         throws PackageManager.NameNotFoundException {
         return mBase.createPackageContext(packageName, flags);
     }
-
-    /**
-     * @hide
-     */
-    @Override
-    public float getApplicationScale() {
-        return mBase.getApplicationScale();
-    }
 }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index f16eb74..f3dfc5a 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -186,7 +186,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
@@ -195,6 +194,12 @@
     public int[] supportsDensities;
 
     /**
+     * True when the application's window can be expanded over default window
+     * size in target density (320x480 for 1.0 density, 480x720 for 1.5 density etc)
+     */
+    public boolean expandable = false;
+
+    /**
      * 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}
@@ -228,6 +233,7 @@
         pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);
         pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes));
         pw.println(prefix + "supportsDensities=" + supportsDensities);
+        pw.println(prefix + "expandable=" + expandable);
         super.dumpBack(pw, prefix);
     }
     
@@ -275,6 +281,7 @@
         manageSpaceActivityName = orig.manageSpaceActivityName;
         descriptionRes = orig.descriptionRes;
         supportsDensities = orig.supportsDensities;
+        expandable = orig.expandable;
     }
 
 
@@ -307,6 +314,7 @@
         dest.writeString(backupAgentName);
         dest.writeInt(descriptionRes);
         dest.writeIntArray(supportsDensities);
+        dest.writeInt(expandable ? 1 : 0);
     }
 
     public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -338,6 +346,7 @@
         backupAgentName = source.readString();
         descriptionRes = source.readInt();
         supportsDensities = source.createIntArray();
+        expandable = source.readInt() != 0;
     }
 
     /**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a2c82e8..65783917 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -180,6 +180,12 @@
     public static final int MATCH_DEFAULT_ONLY   = 0x00010000;
 
     /**
+     * {@link ApplicationInfo} flag: return the
+     * {link ApplicationInfo#expandable} boolean flag of the package.
+     */
+    public static final int GET_EXPANDABLE = 0x00020000;
+
+    /**
      * Permission check result: this is returned by {@link #checkPermission}
      * if the permission has been granted to the given package.
      */
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 212b590..e2c0fe6 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -835,6 +835,26 @@
                     + parser.getName();
                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                 return null;
+
+
+            } 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("expandable")) {
+                pkg.expandable = true;
+                XmlUtils.skipCurrentTag(parser);
             } else {
                 Log.w(TAG, "Bad element under <manifest>: "
                       + parser.getName());
@@ -866,7 +886,8 @@
             pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()];
             pkg.usesLibraries.toArray(pkg.usesLibraryFiles);
         }
-
+        // TODO: enable all density & expandable if target sdk is higher than donut 
+        
         int size = pkg.supportsDensityList.size();
         if (size > 0) {
             int densities[] = pkg.supportsDensities = new int[size];
@@ -1345,21 +1366,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 && !owner.supportsDensityList.contains(density)) {
-                    owner.supportsDensityList.add(density);
-                }
-
-                XmlUtils.skipCurrentTag(parser);
-
             } else {
                 if (!RIGID_PARSER) {
                     Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
@@ -2244,6 +2250,9 @@
         public final ArrayList<Integer> supportsDensityList = new ArrayList<Integer>();
         public int[] supportsDensities = null;
 
+        // If the application's window is expandable.
+        public boolean expandable;
+        
         // If this is a 3rd party app, this is the path of the zip file.
         public String mPath;
 
@@ -2415,7 +2424,10 @@
             return true;
         }
         if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0
-            && p.supportsDensities != null) {
+                && p.supportsDensities != null) {
+            return true;
+        }
+        if ((flags & PackageManager.GET_EXPANDABLE) != 0) {
             return true;
         }
         return false;
@@ -2438,6 +2450,9 @@
         if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0) {
             ai.supportsDensities = p.supportsDensities;
         }
+        if ((flags & PackageManager.GET_EXPANDABLE) != 0) {
+            ai.expandable = p.expandable;
+        }
         return ai;
     }
 
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
new file mode 100644
index 0000000..19379fb
--- /dev/null
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.res;
+
+import android.content.pm.ApplicationInfo;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+
+/**
+ * CompatibilityInfo class keeps the information about compatibility mode that the application is
+ * running under.
+ * 
+ *  {@hide} 
+ */
+public class CompatibilityInfo {
+    /** default compatibility info object for compatible applications */
+    public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo(); 
+
+    /**
+     * The default width of the screen in portrait mode. 
+     */
+    public static final int DEFAULT_PORTRAIT_WIDTH = 320;
+
+    /**
+     * The default height of the screen in portrait mode. 
+     */    
+    public static final int DEFAULT_PORTRAIT_HEIGHT = 480;
+
+    /**
+     * Application's scale.
+     */
+    public final float mApplicationScale;
+
+    /**
+     * Application's inverted scale.
+     */
+    public final float mApplicationInvertedScale;
+    
+    /**
+     * 
+     * A boolean flag to indicates that the application can expand over the original size.
+     */
+    public final boolean mExpandable;
+    
+    /**
+     * A boolean flag to tell if the application needs scaling (when mApplicationScale != 1.0f)
+     */
+    public final boolean mScalingRequired;
+
+    public CompatibilityInfo(ApplicationInfo appInfo) {
+        // A temp workaround to fix rotation issue.
+        // mExpandable = appInfo.expandable;
+        mExpandable = true;
+        float packageDensityScale = -1.0f;
+        if (appInfo.supportsDensities != null) {
+            int minDiff = Integer.MAX_VALUE;
+            for (int density : appInfo.supportsDensities) {
+                int tmpDiff = Math.abs(DisplayMetrics.DEVICE_DENSITY - density);
+                if (tmpDiff == 0) {
+                    packageDensityScale = 1.0f;
+                    break;
+                }
+                // prefer higher density (appScale>1.0), unless that's only option.
+                if (tmpDiff < minDiff && packageDensityScale < 1.0f) {
+                    packageDensityScale = DisplayMetrics.DEVICE_DENSITY / (float) density;
+                    minDiff = tmpDiff;
+                }
+            }
+        }
+        if (packageDensityScale > 0.0f) {
+            mApplicationScale = packageDensityScale;
+        } else {
+            mApplicationScale = DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
+        }
+        mApplicationInvertedScale = 1.0f / mApplicationScale;
+        mScalingRequired = mApplicationScale != 1.0f;
+    }
+
+    private CompatibilityInfo() {
+        mApplicationScale = mApplicationInvertedScale = 1.0f;
+        mExpandable = true;
+        mScalingRequired = false;
+    }
+
+    @Override
+    public String toString() {
+        return "CompatibilityInfo{scale=" + mApplicationScale +
+                ", expandable=" + mExpandable + "}"; 
+    }
+}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 665e40c..976b618 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -22,6 +22,8 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.app.ActivityThread.PackageInfo;
+import android.content.pm.ApplicationInfo;
 import android.graphics.Movie;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.BitmapDrawable;
@@ -84,7 +86,9 @@
     private final Configuration mConfiguration = new Configuration();
     /*package*/ final DisplayMetrics mMetrics = new DisplayMetrics();
     PluralRules mPluralRule;
-
+    
+    private final CompatibilityInfo mCompatibilityInfo;
+    
     private static final SparseArray<Object> EMPTY_ARRAY = new SparseArray<Object>() {
         @Override
         public void put(int k, Object o) {
@@ -126,23 +130,36 @@
      */
     public Resources(AssetManager assets, DisplayMetrics metrics,
             Configuration config) {
-        this(assets, metrics, config, true);
+        this(assets, metrics, config, null);
     }
 
     /**
-     * Create a resource with an additional flag for preloaded
-     * drawable cache. Used by {@link ActivityThread}.
-     *
+     * Creates a new Resources object with ApplicationInfo.
+     * 
+     * @param assets Previously created AssetManager. 
+     * @param metrics Current display metrics to consider when 
+     *                selecting/computing resource values.
+     * @param config Desired device configuration to consider when 
+     *               selecting/computing resource values (optional).
+     * @param appInfo this resource's application info.
      * @hide
      */
     public Resources(AssetManager assets, DisplayMetrics metrics,
-        Configuration config, boolean usePreloadedCache) {
+            Configuration config, ApplicationInfo appInfo) {
         mAssets = assets;
         mConfiguration.setToDefaults();
         mMetrics.setToDefaults();
+        if (appInfo != null) {
+            mCompatibilityInfo = new CompatibilityInfo(appInfo);
+            if (DEBUG_CONFIG) {
+                Log.d(TAG, "compatibility for " + appInfo.packageName + " : " + mCompatibilityInfo);
+            }
+        } else {
+            mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+        }
         updateConfiguration(config, metrics);
         assets.ensureStringBlocks();
-        if (usePreloadedCache) {
+        if (!mCompatibilityInfo.mScalingRequired) {
             mPreloadedDrawables = sPreloadedDrawables;
         } else {
             mPreloadedDrawables = emptySparseArray();
@@ -1251,6 +1268,7 @@
             }
             if (metrics != null) {
                 mMetrics.setTo(metrics);
+                mMetrics.updateMetrics(mCompatibilityInfo, mConfiguration);
             }
             mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
 
@@ -1356,6 +1374,17 @@
     public Configuration getConfiguration() {
         return mConfiguration;
     }
+    
+    /**
+     * Return the compatibility mode information for the application.
+     * The returned object should be treated as read-only.
+     * 
+     * @return compatibility info. null if the app does not require compatibility mode.
+     * @hide
+     */
+    public CompatibilityInfo getCompatibilityInfo() {
+        return mCompatibilityInfo;
+    }
 
     /**
      * Return a resource identifier for the given resource name.  A fully
@@ -1920,5 +1949,6 @@
         updateConfiguration(null, null);
         mAssets.ensureStringBlocks();
         mPreloadedDrawables = sPreloadedDrawables;
+        mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
     }
 }
diff --git a/core/java/android/database/sqlite/SQLiteContentHelper.java b/core/java/android/database/sqlite/SQLiteContentHelper.java
new file mode 100644
index 0000000..2800d86
--- /dev/null
+++ b/core/java/android/database/sqlite/SQLiteContentHelper.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+package android.database.sqlite;
+
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.os.MemoryFile;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Some helper functions for using SQLite database to implement content providers.
+ *
+ * @hide
+ */
+public class SQLiteContentHelper {
+
+    /**
+     * Runs an SQLite query and returns an AssetFileDescriptor for the
+     * blob in column 0 of the first row. If the first column does
+     * not contain a blob, an unspecified exception is thrown.
+     *
+     * @param db Handle to a readable database.
+     * @param sql SQL query, possibly with query arguments.
+     * @param selectionArgs Query argument values, or {@code null} for no argument.
+     * @return If no exception is thrown, a non-null AssetFileDescriptor is returned.
+     * @throws FileNotFoundException If the query returns no results or the
+     *         value of column 0 is NULL, or if there is an error creating the
+     *         asset file descriptor.
+     */
+    public static AssetFileDescriptor getBlobColumnAsAssetFile(SQLiteDatabase db, String sql,
+            String[] selectionArgs) throws FileNotFoundException {
+        try {
+            MemoryFile file = simpleQueryForBlobMemoryFile(db, sql, selectionArgs);
+            if (file == null) {
+                throw new FileNotFoundException("No results.");
+            }
+            return AssetFileDescriptor.fromMemoryFile(file);
+        } catch (IOException ex) {
+            throw new FileNotFoundException(ex.toString());
+        }
+    }
+
+    /**
+     * Runs an SQLite query and returns a MemoryFile for the
+     * blob in column 0 of the first row. If the first column does
+     * not contain a blob, an unspecified exception is thrown.
+     *
+     * @return A memory file, or {@code null} if the query returns no results
+     *         or the value column 0 is NULL.
+     * @throws IOException If there is an error creating the memory file.
+     */
+    // TODO: make this native and use the SQLite blob API to reduce copying
+    private static MemoryFile simpleQueryForBlobMemoryFile(SQLiteDatabase db, String sql,
+            String[] selectionArgs) throws IOException {
+        Cursor cursor = db.rawQuery(sql, selectionArgs);
+        if (cursor == null) {
+            return null;
+        }
+        try {
+            if (!cursor.moveToFirst()) {
+                return null;
+            }
+            byte[] bytes = cursor.getBlob(0);
+            if (bytes == null) {
+                return null;
+            }
+            MemoryFile file = new MemoryFile(null, bytes.length);
+            file.writeBytes(bytes, 0, 0, bytes.length);
+            file.deactivate();
+            return file;
+        } finally {
+            cursor.close();
+        }
+    }
+
+}
diff --git a/core/java/android/gesture/GestureOverlayView.java b/core/java/android/gesture/GestureOverlayView.java
index 6f2c2a7..1251964 100755
--- a/core/java/android/gesture/GestureOverlayView.java
+++ b/core/java/android/gesture/GestureOverlayView.java
@@ -93,6 +93,7 @@
 
     private float mTotalLength;
     private boolean mIsGesturing = false;
+    private boolean mPreviousWasGesturing = false;
     private boolean mInterceptEvents = true;
     private boolean mIsListeningForGestures;
 
@@ -425,6 +426,7 @@
 
         clear(false);
         mIsGesturing = false;
+        mPreviousWasGesturing = false;
         mStrokeBuffer.clear();
 
         final ArrayList<OnGesturingListener> otherListeners = mOnGesturingListeners;
@@ -442,8 +444,10 @@
     @Override
     public boolean dispatchTouchEvent(MotionEvent event) {
         if (isEnabled()) {
-            boolean cancelDispatch = (mIsGesturing || (mCurrentGesture != null &&
-                    mCurrentGesture.getStrokesCount() > 0)) && mInterceptEvents;
+            final boolean cancelDispatch = (mIsGesturing || (mCurrentGesture != null &&
+                    mCurrentGesture.getStrokesCount() > 0 && mPreviousWasGesturing)) &&
+                    mInterceptEvents;
+
             processEvent(event);
 
             if (cancelDispatch) {
@@ -451,6 +455,7 @@
             }
 
             super.dispatchTouchEvent(event);
+
             return true;
         }
 
@@ -647,6 +652,7 @@
         }
 
         mStrokeBuffer.clear();
+        mPreviousWasGesturing = mIsGesturing;
         mIsGesturing = false;
 
         final ArrayList<OnGesturingListener> listeners = mOnGesturingListeners;
@@ -688,6 +694,7 @@
                         fireOnGesturePerformed();
                     }
 
+                    mPreviousWasGesturing = false;
                     mIsFadingOut = false;
                     mFadingHasStarted = false;
                     mPath.rewind();
@@ -707,6 +714,7 @@
                 mFadingHasStarted = false;
                 mPath.rewind();
                 mCurrentGesture = null;
+                mPreviousWasGesturing = false;
                 setPaintAlpha(255);
             }
 
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 358a546..528def5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -307,6 +307,13 @@
              * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
              */
             public abstract int getStarts(int which);
+
+            /**
+             * Returns the cpu time spent in microseconds while the process was in the foreground.
+             * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
+             * @return foreground cpu time in microseconds
+             */
+            public abstract long getForegroundTime(int which);
         }
 
         /**
@@ -364,7 +371,7 @@
     public abstract int getStartCount();
     
     /**
-     * Returns the time in milliseconds that the screen has been on while the device was
+     * Returns the time in microseconds that the screen has been on while the device was
      * running on battery.
      * 
      * {@hide}
@@ -384,7 +391,7 @@
     public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
     
     /**
-     * Returns the time in milliseconds that the screen has been on with
+     * Returns the time in microseconds that the screen has been on with
      * the given brightness
      * 
      * {@hide}
@@ -395,7 +402,7 @@
     public abstract int getInputEventCount(int which);
     
     /**
-     * Returns the time in milliseconds that the phone has been on while the device was
+     * Returns the time in microseconds that the phone has been on while the device was
      * running on battery.
      * 
      * {@hide}
@@ -415,7 +422,7 @@
     public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
     
     /**
-     * Returns the time in milliseconds that the phone has been running with
+     * Returns the time in microseconds that the phone has been running with
      * the given signal strength.
      * 
      * {@hide}
@@ -443,7 +450,7 @@
     public static final int NUM_DATA_CONNECTION_TYPES = 5;
     
     /**
-     * Returns the time in milliseconds that the phone has been running with
+     * Returns the time in microseconds that the phone has been running with
      * the given data connection.
      * 
      * {@hide}
@@ -460,7 +467,7 @@
     public abstract int getPhoneDataConnectionCount(int dataType, int which);
 
     /**
-     * Returns the time in milliseconds that wifi has been on while the device was
+     * Returns the time in microseconds that wifi has been on while the device was
      * running on battery.
      * 
      * {@hide}
@@ -468,7 +475,7 @@
     public abstract long getWifiOnTime(long batteryRealtime, int which);
 
     /**
-     * Returns the time in milliseconds that wifi has been on and the driver has
+     * Returns the time in microseconds that wifi has been on and the driver has
      * been in the running state while the device was running on battery.
      *
      * {@hide}
@@ -476,7 +483,7 @@
     public abstract long getWifiRunningTime(long batteryRealtime, int which);
 
     /**
-     * Returns the time in milliseconds that bluetooth has been on while the device was
+     * Returns the time in microseconds that bluetooth has been on while the device was
      * running on battery.
      * 
      * {@hide}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5d10675..42a5075 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1276,6 +1276,14 @@
          * boolean (1 or 0).
          */
         public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
+        
+        /**
+         * Whether live web suggestions while the user types into search dialogs are
+         * enabled. Browsers and other search UIs should respect this, as it allows
+         * a user to avoid sending partial queries to a search engine, if it poses
+         * any privacy concern. The value is boolean (1 or 0).
+         */
+        public static final String SHOW_WEB_SUGGESTIONS = "show_web_suggestions";
 
         // Settings moved to Settings.Secure
 
@@ -1916,6 +1924,29 @@
             "enabled_accessibility_services";
 
         /**
+         * Setting to always use the default text-to-speech settings regardless
+         * of the application settings.
+         * 1 = override application settings,
+         * 0 = use application settings (if specified).
+         */
+        public static final String TTS_USE_DEFAULTS = "tts_use_defaults";
+
+        /**
+         * Default text-to-speech engine speech rate. 100 = 1x
+         */
+        public static final String TTS_DEFAULT_RATE = "tts_default_rate";
+
+        /**
+         * Default text-to-speech engine pitch. 100 = 1x
+         */
+        public static final String TTS_DEFAULT_PITCH = "tts_default_pitch";
+
+        /**
+         * Default text-to-speech engine.
+         */
+        public static final String TTS_DEFAULT_SYNTH = "tts_default_synth";
+
+        /**
          * Whether to notify the user of open networks.
          * <p>
          * If not connected and the scan results have an open network, we will
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 952372f..060bcea 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -23,12 +23,13 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Handler;
+import android.os.RemoteException;
 
 import java.util.List;
 
 /**
  * This is a simplified version of the Search Manager service.  It no longer handles
- * presentation (UI).  Its function is to maintain the map & list of "searchable" 
+ * presentation (UI).  Its function is to maintain the map & list of "searchable"
  * items, which provides a mapping from individual activities (where a user might have
  * invoked search) to specific searchable activities (where the search will be dispatched).
  */
@@ -43,19 +44,19 @@
     private final Handler mHandler;
     private boolean mSearchablesDirty;
     private Searchables mSearchables;
-    
+
     /**
      * Initializes the Search Manager service in the provided system context.
      * Only one instance of this object should be created!
      *
      * @param context to use for accessing DB, window manager, etc.
      */
-    public SearchManagerService(Context context)  {     
+    public SearchManagerService(Context context)  {
         mContext = context;
         mHandler = new Handler();
         mSearchablesDirty = true;
         mSearchables = new Searchables(context);
-        
+
         // Setup the infrastructure for updating and maintaining the list
         // of searchable activities.
         IntentFilter filter = new IntentFilter();
@@ -64,15 +65,15 @@
         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addDataScheme("package");
         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
-        
+
         // After startup settles down, preload the searchables list,
         // which will reduce the delay when the search UI is invoked.
         mHandler.post(mRunUpdateSearchable);
     }
-    
+
     /**
      * Listens for intent broadcasts.
-     * 
+     *
      * The primary purpose here is to refresh the "searchables" list
      * if packages are added/removed.
      */
@@ -80,7 +81,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
-            
+
             // First, test for intents that matter at any time
             if (action.equals(Intent.ACTION_PACKAGE_ADDED) ||
                 action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
@@ -91,14 +92,14 @@
             }
         }
     };
-    
+
     /**
      * This runnable (for the main handler / UI thread) will update the searchables list.
      */
     private Runnable mRunUpdateSearchable = new Runnable() {
         public void run() {
             updateSearchablesIfDirty();
-        } 
+        }
     };
 
     /**
@@ -124,7 +125,7 @@
      *
      * @param launchActivity The activity from which we're launching this search.
      * @param globalSearch If false, this will only launch the search that has been specifically
-     * defined by the application (which is usually defined as a local search).  If no default 
+     * defined by the application (which is usually defined as a local search).  If no default
      * search is defined in the current application or activity, no search will be launched.
      * If true, this will always launch a platform-global (e.g. web-based) search instead.
      * @return Returns a SearchableInfo record describing the parameters of the search,
@@ -141,7 +142,7 @@
 
         return si;
     }
-    
+
     /**
      * Returns a list of the searchable activities that can be included in global search.
      */
@@ -150,4 +151,26 @@
         return mSearchables.getSearchablesInGlobalSearchList();
     }
 
+    /**
+     * Returns a list of the searchable activities that handle web searches.
+     */
+    public List<SearchableInfo> getSearchablesForWebSearch() {
+        updateSearchablesIfDirty();
+        return mSearchables.getSearchablesForWebSearchList();
+    }
+
+    /**
+     * Returns the default searchable activity for web searches.
+     */
+    public SearchableInfo getDefaultSearchableForWebSearch() {
+        updateSearchablesIfDirty();
+        return mSearchables.getDefaultSearchableForWebSearch();
+    }
+
+    /**
+     * Sets the default searchable activity for web searches.
+     */
+    public void setDefaultWebSearch(ComponentName component) {
+        mSearchables.setDefaultWebSearch(component);
+    }
 }
diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java
index 842fc75..c083142 100644
--- a/core/java/android/server/search/SearchableInfo.java
+++ b/core/java/android/server/search/SearchableInfo.java
@@ -40,7 +40,7 @@
 public final class SearchableInfo implements Parcelable {
 
     // general debugging support
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final String LOG_TAG = "SearchableInfo";
 
     // static strings used for XML lookups.
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index 62631d6..a27667b 100644
--- a/core/java/android/server/search/Searchables.java
+++ b/core/java/android/server/search/Searchables.java
@@ -16,13 +16,18 @@
 
 package android.server.search;
 
+import com.android.internal.app.ResolverActivity;
+import com.android.internal.R;
+
 import android.app.SearchManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
 import android.os.Bundle;
 import android.util.Log;
 
@@ -31,37 +36,39 @@
 import java.util.List;
 
 /**
- * This class maintains the information about all searchable activities. 
+ * This class maintains the information about all searchable activities.
  */
 public class Searchables {
 
     private static final String LOG_TAG = "Searchables";
 
     // static strings used for XML lookups, etc.
-    // TODO how should these be documented for the developer, in a more structured way than 
+    // TODO how should these be documented for the developer, in a more structured way than
     // the current long wordy javadoc in SearchManager.java ?
     private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable";
     private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*";
-    
+
     private Context mContext;
-    
+
     private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null;
     private ArrayList<SearchableInfo> mSearchablesList = null;
     private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null;
+    private ArrayList<SearchableInfo> mSearchablesForWebSearchList = null;
     private SearchableInfo mDefaultSearchable = null;
-    
+    private SearchableInfo mDefaultSearchableForWebSearch = null;
+
     /**
-     * 
+     *
      * @param context Context to use for looking up activities etc.
      */
     public Searchables (Context context) {
         mContext = context;
     }
-    
+
     /**
      * Look up, or construct, based on the activity.
-     * 
-     * The activities fall into three cases, based on meta-data found in 
+     *
+     * The activities fall into three cases, based on meta-data found in
      * the manifest entry:
      * <ol>
      * <li>The activity itself implements search.  This is indicated by the
@@ -73,16 +80,16 @@
      * case the factory will "redirect" and return the searchable data.</li>
      * <li>No searchability data is provided.  We return null here and other
      * code will insert the "default" (e.g. contacts) search.
-     * 
+     *
      * TODO: cache the result in the map, and check the map first.
      * TODO: it might make sense to implement the searchable reference as
      * an application meta-data entry.  This way we don't have to pepper each
      * and every activity.
      * TODO: can we skip the constructor step if it's a non-searchable?
-     * TODO: does it make sense to plug the default into a slot here for 
+     * TODO: does it make sense to plug the default into a slot here for
      * automatic return?  Probably not, but it's one way to do it.
      *
-     * @param activity The name of the current activity, or null if the 
+     * @param activity The name of the current activity, or null if the
      * activity does not define any explicit searchable metadata.
      */
     public SearchableInfo getSearchableInfo(ComponentName activity) {
@@ -92,18 +99,18 @@
             result = mSearchablesMap.get(activity);
             if (result != null) return result;
         }
-        
+
         // Step 2.  See if the current activity references a searchable.
         // Note:  Conceptually, this could be a while(true) loop, but there's
-        // no point in implementing reference chaining here and risking a loop.  
+        // no point in implementing reference chaining here and risking a loop.
         // References must point directly to searchable activities.
-       
+
         ActivityInfo ai = null;
         try {
             ai = mContext.getPackageManager().
                        getActivityInfo(activity, PackageManager.GET_META_DATA );
             String refActivityName = null;
-            
+
             // First look for activity-specific reference
             Bundle md = ai.metaData;
             if (md != null) {
@@ -116,11 +123,11 @@
                     refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
                 }
             }
-            
+
             // Irrespective of source, if a reference was found, follow it.
             if (refActivityName != null)
             {
-                // An app or activity can declare that we should simply launch 
+                // An app or activity can declare that we should simply launch
                 // "system default search" if search is invoked.
                 if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) {
                     return getDefaultSearchable();
@@ -146,80 +153,101 @@
         } catch (PackageManager.NameNotFoundException e) {
             // case 3: no metadata
         }
- 
+
         // Step 3.  None found. Return null.
         return null;
-        
+
     }
-    
+
     /**
      * Provides the system-default search activity, which you can use
      * whenever getSearchableInfo() returns null;
-     * 
+     *
      * @return Returns the system-default search activity, null if never defined
      */
     public synchronized SearchableInfo getDefaultSearchable() {
         return mDefaultSearchable;
     }
-    
+
     public synchronized boolean isDefaultSearchable(SearchableInfo searchable) {
         return searchable == mDefaultSearchable;
     }
-   
+
     /**
-     * Builds an entire list (suitable for display) of 
-     * activities that are searchable, by iterating the entire set of 
-     * ACTION_SEARCH intents.  
-     * 
+     * Builds an entire list (suitable for display) of
+     * activities that are searchable, by iterating the entire set of
+     * ACTION_SEARCH & ACTION_WEB_SEARCH intents.
+     *
      * Also clears the hash of all activities -> searches which will
      * refill as the user clicks "search".
-     * 
+     *
      * This should only be done at startup and again if we know that the
      * list has changed.
-     * 
+     *
      * TODO: every activity that provides a ACTION_SEARCH intent should
      * also provide searchability meta-data.  There are a bunch of checks here
      * that, if data is not found, silently skip to the next activity.  This
      * won't help a developer trying to figure out why their activity isn't
      * showing up in the list, but an exception here is too rough.  I would
      * like to find a better notification mechanism.
-     * 
+     *
      * TODO: sort the list somehow?  UI choice.
      */
     public void buildSearchableList() {
         // These will become the new values at the end of the method
-        HashMap<ComponentName, SearchableInfo> newSearchablesMap 
+        HashMap<ComponentName, SearchableInfo> newSearchablesMap
                                 = new HashMap<ComponentName, SearchableInfo>();
         ArrayList<SearchableInfo> newSearchablesList
                                 = new ArrayList<SearchableInfo>();
         ArrayList<SearchableInfo> newSearchablesInGlobalSearchList
                                 = new ArrayList<SearchableInfo>();
+        ArrayList<SearchableInfo> newSearchablesForWebSearchList
+                                = new ArrayList<SearchableInfo>();
 
         final PackageManager pm = mContext.getPackageManager();
-        
-        // use intent resolver to generate list of ACTION_SEARCH receivers
-        List<ResolveInfo> infoList;
+
+        // Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers.
+        List<ResolveInfo> searchList;
         final Intent intent = new Intent(Intent.ACTION_SEARCH);
-        infoList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
-        
+        searchList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
+
+        List<ResolveInfo> webSearchInfoList;
+        final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH);
+        webSearchInfoList = pm.queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
+
         // analyze each one, generate a Searchables record, and record
-        if (infoList != null) {
-            int count = infoList.size();
+        if (searchList != null || webSearchInfoList != null) {
+            int search_count = (searchList == null ? 0 : searchList.size());
+            int web_search_count = (webSearchInfoList == null ? 0 : webSearchInfoList.size());
+            int count = search_count + web_search_count;
             for (int ii = 0; ii < count; ii++) {
                 // for each component, try to find metadata
-                ResolveInfo info = infoList.get(ii);
+                ResolveInfo info = (ii < search_count)
+                        ? searchList.get(ii)
+                        : webSearchInfoList.get(ii - search_count);
                 ActivityInfo ai = info.activityInfo;
-                SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai);
-                if (searchable != null) {
-                    newSearchablesList.add(searchable);
-                    newSearchablesMap.put(searchable.getSearchActivity(), searchable);
-                    if (searchable.shouldIncludeInGlobalSearch()) {
-                        newSearchablesInGlobalSearchList.add(searchable);
+                // Check first to avoid duplicate entries.
+                if (newSearchablesMap.get(new ComponentName(ai.packageName, ai.name)) == null) {
+                    SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai);
+                    if (searchable != null) {
+                        newSearchablesList.add(searchable);
+                        newSearchablesMap.put(searchable.getSearchActivity(), searchable);
+                        if (searchable.shouldIncludeInGlobalSearch()) {
+                            newSearchablesInGlobalSearchList.add(searchable);
+                        }
                     }
                 }
             }
         }
-        
+
+        if (webSearchInfoList != null) {
+            for (int i = 0; i < webSearchInfoList.size(); ++i) {
+                ActivityInfo ai = webSearchInfoList.get(i).activityInfo;
+                ComponentName component = new ComponentName(ai.packageName, ai.name);
+                newSearchablesForWebSearchList.add(newSearchablesMap.get(component));
+            }
+        }
+
         // Find the global search provider
         Intent globalSearchIntent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
         ComponentName globalSearchActivity = globalSearchIntent.resolveActivity(pm);
@@ -230,15 +258,95 @@
                     + globalSearchActivity);
         }
 
+        // Find the default web search provider.
+        ComponentName webSearchActivity = getPreferredWebSearchActivity();
+        SearchableInfo newDefaultSearchableForWebSearch = null;
+        if (webSearchActivity != null) {
+            newDefaultSearchableForWebSearch = newSearchablesMap.get(webSearchActivity);
+        }
+        if (newDefaultSearchableForWebSearch == null) {
+            Log.w(LOG_TAG, "No searchable info found for new default web search activity "
+                    + webSearchActivity);
+        }
+
         // Store a consistent set of new values
         synchronized (this) {
             mSearchablesMap = newSearchablesMap;
             mSearchablesList = newSearchablesList;
             mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList;
+            mSearchablesForWebSearchList = newSearchablesForWebSearchList;
             mDefaultSearchable = newDefaultSearchable;
+            mDefaultSearchableForWebSearch = newDefaultSearchableForWebSearch;
         }
+
+        // Inform all listeners that the list of searchables has been updated.
+        mContext.sendBroadcast(new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED));
     }
-    
+
+    /**
+     * Checks if the given activity component is present in the system and if so makes it the
+     * preferred activity for handling ACTION_WEB_SEARCH.
+     * @param component Name of the component to check and set as preferred.
+     * @param action Intent action for which this activity is to be set as preferred.
+     * @return true if component was detected and set as preferred activity, false if not.
+     */
+    private boolean setPreferredActivity(ComponentName component, String action) {
+        Log.d(LOG_TAG, "Checking component " + component);
+        PackageManager pm = mContext.getPackageManager();
+        ActivityInfo ai;
+        try {
+            ai = pm.getActivityInfo(component, 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+
+        // The code here to find the value for bestMatch is heavily inspired by the code
+        // in ResolverActivity where the preferred activity is set.
+        Intent intent = new Intent(action);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        List<ResolveInfo> webSearchActivities = pm.queryIntentActivities(intent, 0);
+        ComponentName set[] = new ComponentName[webSearchActivities.size()];
+        int bestMatch = 0;
+        for (int i = 0; i < webSearchActivities.size(); ++i) {
+            ResolveInfo ri = webSearchActivities.get(i);
+            set[i] = new ComponentName(ri.activityInfo.packageName,
+                                       ri.activityInfo.name);
+            if (ri.match > bestMatch) bestMatch = ri.match;
+        }
+
+        Log.d(LOG_TAG, "Setting preferred web search activity to " + component);
+        IntentFilter filter = new IntentFilter(action);
+        filter.addCategory(Intent.CATEGORY_DEFAULT);
+        pm.replacePreferredActivity(filter, bestMatch, set, component);
+        return true;
+    }
+
+    public ComponentName getPreferredWebSearchActivity() {
+        // Check if we have a preferred web search activity.
+        Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
+        PackageManager pm = mContext.getPackageManager();
+        ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+
+        if (ri == null || ri.activityInfo.name.equals(ResolverActivity.class.getName())) {
+            Log.d(LOG_TAG, "No preferred activity set for action web search.");
+
+            // The components in the providers array are checked in the order of declaration so the
+            // first one has the highest priority. If the component exists in the system it is set
+            // as the preferred activity to handle intent action web search.
+            String[] preferredActivities = mContext.getResources().getStringArray(
+                    com.android.internal.R.array.default_web_search_providers);
+            for (String componentName : preferredActivities) {
+                ComponentName component = ComponentName.unflattenFromString(componentName);
+                if (setPreferredActivity(component, Intent.ACTION_WEB_SEARCH)) {
+                    return component;
+                }
+            }
+        }
+
+        if (ri == null) return null;
+        return new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
+    }
+
     /**
      * Returns the list of searchable activities.
      */
@@ -246,11 +354,33 @@
         ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(mSearchablesList);
         return result;
     }
-    
+
     /**
      * Returns a list of the searchable activities that can be included in global search.
      */
     public synchronized ArrayList<SearchableInfo> getSearchablesInGlobalSearchList() {
         return new ArrayList<SearchableInfo>(mSearchablesInGlobalSearchList);
     }
+
+    /**
+     * Returns a list of the searchable activities that handle web searches.
+     */
+    public synchronized ArrayList<SearchableInfo> getSearchablesForWebSearchList() {
+        return new ArrayList<SearchableInfo>(mSearchablesForWebSearchList);
+    }
+
+    /**
+     * Returns the default searchable activity for web searches.
+     */
+    public synchronized SearchableInfo getDefaultSearchableForWebSearch() {
+        return mDefaultSearchableForWebSearch;
+    }
+
+    /**
+     * Sets the default searchable activity for web searches.
+     */
+    public synchronized void setDefaultWebSearch(ComponentName component) {
+        setPreferredActivity(component, Intent.ACTION_WEB_SEARCH);
+        buildSearchableList();
+    }
 }
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index e4dd020..987be2b 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
 import android.os.*;
 
 
@@ -101,17 +103,46 @@
     }
 
     /**
-     * Set the display metrics' density and update parameters depend on it.
-     * @hide
+     * Update the display metrics based on the compatibility info and configuration.
+     * {@hide}
      */
-    public void updateDensity(float newDensity) {
-        float ratio = newDensity / density;
-        density = newDensity;
-        scaledDensity = density;
-        widthPixels *= ratio;
-        heightPixels *= ratio;
-        xdpi *= ratio;
-        ydpi *= ratio;
+    public void updateMetrics(CompatibilityInfo compatibilityInfo, Configuration configuration) {
+        if (compatibilityInfo.mScalingRequired) {
+            float invertedRatio = compatibilityInfo.mApplicationInvertedScale;
+            density *= invertedRatio;
+            scaledDensity *= invertedRatio;
+            xdpi *= invertedRatio;
+            ydpi *= invertedRatio;
+            widthPixels *= invertedRatio;
+            heightPixels *= invertedRatio;
+        }
+        if (!compatibilityInfo.mExpandable) {
+            // Note: this assume that configuration is updated before calling
+            // updateMetrics method.
+            int defaultWidth;
+            int defaultHeight;
+            switch (configuration.orientation) {
+                case Configuration.ORIENTATION_LANDSCAPE: {
+                    defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
+                    defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
+                    break;
+                }
+                case Configuration.ORIENTATION_UNDEFINED:
+                case Configuration.ORIENTATION_PORTRAIT:
+                case Configuration.ORIENTATION_SQUARE:
+                default: {
+                    defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
+                    defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
+                }
+            }
+            // adjust the size only when the device's screen is bigger.
+            if (defaultWidth < widthPixels) {
+                widthPixels = defaultWidth;
+            }
+            if (defaultHeight < heightPixels) {
+                heightPixels = defaultHeight;
+            }
+        }
     }
 
     public String toString() {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 0dc2570..082cca2 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.CompatibilityInfo;
 import android.graphics.Canvas;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
@@ -137,28 +138,24 @@
     int mFormat = -1;
     int mType = -1;
     final Rect mSurfaceFrame = new Rect();
-    private final float mAppScale;
-    private final float mAppScaleInverted;
+    private final CompatibilityInfo mCompatibilityInfo;
 
     public SurfaceView(Context context) {
         super(context);
         setWillNotDraw(true);
-        mAppScale = context.getApplicationScale();
-        mAppScaleInverted = 1.0f / mAppScale;
+        mCompatibilityInfo = context.getResources().getCompatibilityInfo();
     }
     
     public SurfaceView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setWillNotDraw(true);
-        mAppScale = context.getApplicationScale();
-        mAppScaleInverted = 1.0f / mAppScale;
+        mCompatibilityInfo = context.getResources().getCompatibilityInfo();
     }
 
     public SurfaceView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         setWillNotDraw(true);
-        mAppScale = context.getApplicationScale();
-        mAppScaleInverted = 1.0f / mAppScale;
+        mCompatibilityInfo = context.getResources().getCompatibilityInfo();
     }
     
     /**
@@ -261,9 +258,9 @@
     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 (mRequestedWidth < 0 && mAppScale != 1.0f) {
+        if (mRequestedWidth < 0 && mCompatibilityInfo.mScalingRequired) {
             MotionEvent scaledBack = MotionEvent.obtain(event);
-            scaledBack.scale(mAppScale);
+            scaledBack.scale(mCompatibilityInfo.mApplicationScale);
             try {
                 return super.dispatchTouchEvent(scaledBack);
             } finally {
@@ -300,6 +297,7 @@
         if (!mHaveFrame) {
             return;
         }
+        float appScale = mCompatibilityInfo.mApplicationScale;
         
         int myWidth = mRequestedWidth;
         if (myWidth <= 0) myWidth = getWidth();
@@ -307,9 +305,9 @@
         if (myHeight <= 0) myHeight = getHeight();
 
         // Use original size for surface unless fixed size is requested.
-        if (mRequestedWidth <= 0) {
-            myWidth *= mAppScale;
-            myHeight *= mAppScale;
+        if (mRequestedWidth <= 0 && mCompatibilityInfo.mScalingRequired) {
+            myWidth *= appScale;
+            myHeight *= appScale;
         }
 
         getLocationInWindow(mLocation);
@@ -337,11 +335,11 @@
                 mFormat = mRequestedFormat;
                 mType = mRequestedType;
 
-                // Scaling window's layout here beause mLayout is not used elsewhere.
-                mLayout.x = (int) (mLeft * mAppScale);
-                mLayout.y = (int) (mTop * mAppScale);
-                mLayout.width = (int) (getWidth() * mAppScale);
-                mLayout.height = (int) (getHeight() * mAppScale);
+                // Scaling window's layout here because mLayout is not used elsewhere.
+                mLayout.x = (int) (mLeft * appScale);
+                mLayout.y = (int) (mTop * appScale);
+                mLayout.width = (int) (getWidth() * appScale);
+                mLayout.height = (int) (getHeight() * appScale);
                 mLayout.format = mRequestedFormat;
                 mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                               | WindowManager.LayoutParams.FLAG_SCALED
@@ -367,14 +365,18 @@
                 
                 mSurfaceLock.lock();
                 mDrawingStopped = !visible;
+
                 final int relayoutResult = mSession.relayout(
                     mWindow, mLayout, mWidth, mHeight,
                         visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,
                         mVisibleInsets, mSurface);
 
-                mContentInsets.scale(mAppScaleInverted);
-                mVisibleInsets.scale(mAppScaleInverted);
-                mWinFrame.scale(mAppScaleInverted);
+                if (mCompatibilityInfo.mScalingRequired) {
+                    float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
+                    mContentInsets.scale(invertedScale);
+                    mVisibleInsets.scale(invertedScale);
+                    mWinFrame.scale(invertedScale);
+                }
 
                 if (localLOGV) Log.i(TAG, "New surface: " + mSurface
                         + ", vis=" + visible + ", frame=" + mWinFrame);
@@ -444,23 +446,23 @@
 
     private static class MyWindow extends IWindow.Stub {
         private final WeakReference<SurfaceView> mSurfaceView;
-        private final float mAppScale;
-        private final float mAppScaleInverted;
+        private final CompatibilityInfo mCompatibilityInfo;
 
         public MyWindow(SurfaceView surfaceView) {
             mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
-            mAppScale = surfaceView.getContext().getApplicationScale();
-            mAppScaleInverted = 1.0f / mAppScale;
+            mCompatibilityInfo = surfaceView.getContext().getResources().getCompatibilityInfo();
         }
 
         public void resized(int w, int h, Rect coveredInsets,
                 Rect visibleInsets, boolean reportDraw) {
             SurfaceView surfaceView = mSurfaceView.get();
-            float scale = mAppScaleInverted;
-            w *= scale;
-            h *= scale;
-            coveredInsets.scale(scale);
-            visibleInsets.scale(scale);
+            if (mCompatibilityInfo.mScalingRequired) {
+                float scale = mCompatibilityInfo.mApplicationInvertedScale;
+                w *= scale;
+                h *= scale;
+                coveredInsets.scale(scale);
+                visibleInsets.scale(scale);
+            }
 
             if (surfaceView != null) {
                 if (localLOGV) Log.v(
@@ -624,7 +626,9 @@
             Canvas c = null;
             if (!mDrawingStopped && mWindow != null) {
                 Rect frame = dirty != null ? dirty : mSurfaceFrame;
-                frame.scale(mAppScale);
+                if (mCompatibilityInfo.mScalingRequired) {
+                    frame.scale(mCompatibilityInfo.mApplicationScale);
+                }
                 try {
                     c = mSurface.lockCanvas(frame);
                 } catch (Exception e) {
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index aaaadef..46aea02 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -87,17 +87,17 @@
      * check that this value is set to true as not to affect performance.
      */
     public static final boolean TRACE_RECYCLER = false;
-    
+
     /**
      * The system property of dynamic switch for capturing view information
      * when it is set, we dump interested fields and methods for the view on focus
-     */    
+     */
     static final String SYSTEM_PROPERTY_CAPTURE_VIEW = "debug.captureview";
-        
+
     /**
      * The system property of dynamic switch for capturing event information
      * when it is set, we log key events, touch/motion and trackball events
-     */    
+     */
     static final String SYSTEM_PROPERTY_CAPTURE_EVENT = "debug.captureevent";
 
     /**
@@ -216,7 +216,7 @@
          * <pre>
          *
          * A specified String is output when the following is true:
-         * 
+         *
          * @return An array of int to String mappings
          */
         FlagToString[] flagMapping() default { };
@@ -228,7 +228,7 @@
          *
          * @return true if the properties of this property should be dumped
          *
-         * @see #prefix() 
+         * @see #prefix()
          */
         boolean deepExport() default false;
 
@@ -313,15 +313,15 @@
     @Retention(RetentionPolicy.RUNTIME)
     public @interface CapturedViewProperty {
         /**
-         * When retrieveReturn is true, we need to retrieve second level methods 
+         * When retrieveReturn is true, we need to retrieve second level methods
          * e.g., we need myView.getFirstLevelMethod().getSecondLevelMethod()
-         * we will set retrieveReturn = true on the annotation of 
+         * we will set retrieveReturn = true on the annotation of
          * myView.getFirstLevelMethod()
-         * @return true if we need the second level methods 
+         * @return true if we need the second level methods
          */
-        boolean retrieveReturn() default false;        
+        boolean retrieveReturn() default false;
     }
-        
+
     private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null;
     private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null;
 
@@ -401,7 +401,7 @@
      */
     public static long getViewRootInstanceCount() {
         return ViewRoot.getInstanceCount();
-    }    
+    }
 
     /**
      * Outputs a trace to the currently opened recycler traces. The trace records the type of
@@ -624,7 +624,7 @@
      *
      * This method will return immediately if TRACE_HIERARCHY is false.
      *
-     * @see #startHierarchyTracing(String, View) 
+     * @see #startHierarchyTracing(String, View)
      * @see #trace(View, android.view.ViewDebug.HierarchyTraceType)
      */
     public static void stopHierarchyTracing() {
@@ -671,7 +671,7 @@
 
         sHierarhcyRoot = null;
     }
-    
+
     static void dispatchCommand(View view, String command, String parameters,
             OutputStream clientStream) throws IOException {
 
@@ -1039,10 +1039,10 @@
 
         final ArrayList<Method> foundMethods = new ArrayList<Method>();
         methods = klass.getDeclaredMethods();
-        
+
         int count = methods.length;
         for (int i = 0; i < count; i++) {
-            final Method method = methods[i];            
+            final Method method = methods[i];
             if (method.getParameterTypes().length == 0 &&
                     method.isAnnotationPresent(ExportedProperty.class) &&
                     method.getReturnType() != Void.class) {
@@ -1075,7 +1075,7 @@
             klass = klass.getSuperclass();
         } while (klass != Object.class);
     }
-    
+
     private static void exportMethods(Context context, Object view, BufferedWriter out,
             Class<?> klass, String prefix) throws IOException {
 
@@ -1260,7 +1260,7 @@
 
         for (int j = 0; j < valuesCount; j++) {
             String name;
-            String value;
+            String value = null;
 
             final int intValue = array[j];
 
@@ -1276,7 +1276,6 @@
                 }
             }
 
-            value = String.valueOf(intValue);
             if (hasMapping) {
                 int mappingCount = mapping.length;
                 for (int k = 0; k < mappingCount; k++) {
@@ -1289,7 +1288,9 @@
             }
 
             if (resolveId) {
-                value = (String) resolveId(context, intValue);
+                if (value == null) value = (String) resolveId(context, intValue);
+            } else {
+                value = String.valueOf(intValue);
             }
 
             writeEntry(out, prefix, name, suffix, value);
@@ -1397,10 +1398,10 @@
 
         final ArrayList<Method> foundMethods = new ArrayList<Method>();
         methods = klass.getMethods();
-        
+
         int count = methods.length;
         for (int i = 0; i < count; i++) {
-            final Method method = methods[i];            
+            final Method method = methods[i];
             if (method.getParameterTypes().length == 0 &&
                     method.isAnnotationPresent(CapturedViewProperty.class) &&
                     method.getReturnType() != Void.class) {
@@ -1414,14 +1415,14 @@
 
         return methods;
     }
-              
-    private static String capturedViewExportMethods(Object obj, Class<?> klass, 
+
+    private static String capturedViewExportMethods(Object obj, Class<?> klass,
             String prefix) {
 
         if (obj == null) {
             return "null";
         }
-        
+
         StringBuilder sb = new StringBuilder();
         final Method[] methods = capturedViewGetPropertyMethods(klass);
 
@@ -1431,41 +1432,41 @@
             try {
                 Object methodValue = method.invoke(obj, (Object[]) null);
                 final Class<?> returnType = method.getReturnType();
-                
+
                 CapturedViewProperty property = method.getAnnotation(CapturedViewProperty.class);
                 if (property.retrieveReturn()) {
                     //we are interested in the second level data only
                     sb.append(capturedViewExportMethods(methodValue, returnType, method.getName() + "#"));
-                } else {                    
+                } else {
                     sb.append(prefix);
                     sb.append(method.getName());
                     sb.append("()=");
-                    
+
                     if (methodValue != null) {
-                        final String value = methodValue.toString().replace("\n", "\\n");                        
-                        sb.append(value);                        
+                        final String value = methodValue.toString().replace("\n", "\\n");
+                        sb.append(value);
                     } else {
                         sb.append("null");
                     }
                     sb.append("; ");
                 }
               } catch (IllegalAccessException e) {
-                  //Exception IllegalAccess, it is OK here 
+                  //Exception IllegalAccess, it is OK here
                   //we simply ignore this method
               } catch (InvocationTargetException e) {
-                  //Exception InvocationTarget, it is OK here 
+                  //Exception InvocationTarget, it is OK here
                   //we simply ignore this method
-              }              
-        }        
+              }
+        }
         return sb.toString();
     }
 
     private static String capturedViewExportFields(Object obj, Class<?> klass, String prefix) {
-        
+
         if (obj == null) {
             return "null";
         }
-        
+
         StringBuilder sb = new StringBuilder();
         final Field[] fields = capturedViewGetPropertyFields(klass);
 
@@ -1487,25 +1488,25 @@
                 }
                 sb.append(' ');
             } catch (IllegalAccessException e) {
-                //Exception IllegalAccess, it is OK here 
+                //Exception IllegalAccess, it is OK here
                 //we simply ignore this field
             }
         }
         return sb.toString();
     }
-    
+
     /**
-     * Dump view info for id based instrument test generation 
+     * Dump view info for id based instrument test generation
      * (and possibly further data analysis). The results are dumped
-     * to the log. 
+     * to the log.
      * @param tag for log
      * @param view for dump
      */
-    public static void dumpCapturedView(String tag, Object view) {        
+    public static void dumpCapturedView(String tag, Object view) {
         Class<?> klass = view.getClass();
         StringBuilder sb = new StringBuilder(klass.getName() + ": ");
         sb.append(capturedViewExportFields(view, klass, ""));
-        sb.append(capturedViewExportMethods(view, klass, ""));        
-        Log.d(tag, sb.toString());        
+        sb.append(capturedViewExportMethods(view, klass, ""));
+        Log.d(tag, sb.toString());
     }
 }
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 7cd65e2..d8bab56 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -30,6 +30,7 @@
 import android.os.SystemProperties;
 import android.util.AndroidRuntimeException;
 import android.util.Config;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.EventLog;
 import android.util.SparseArray;
@@ -40,6 +41,7 @@
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Scroller;
 import android.content.pm.PackageManager;
+import android.content.res.CompatibilityInfo;
 import android.content.Context;
 import android.app.ActivityManagerNative;
 import android.Manifest;
@@ -125,9 +127,8 @@
     int mHeight;
     Rect mDirty; // will be a graphics.Region soon
     boolean mIsAnimating;
-    // TODO: change these to scalar class.
-    private float mAppScale;
-    private float mAppScaleInverted; // = 1.0f / mAppScale
+    
+    private CompatibilityInfo mCompatibilityInfo;
     private int[] mWindowLayoutParamsBackup = null;
 
     final View.AttachInfo mAttachInfo;
@@ -386,12 +387,15 @@
         synchronized (this) {
             if (mView == null) {
                 mView = view;
-                mAppScale = mView.getContext().getApplicationScale();
-                if (mAppScale != 1.0f) {
+                mWindowAttributes.copyFrom(attrs);
+                mCompatibilityInfo =
+                        mView.getContext().getResources().getCompatibilityInfo();
+                if (mCompatibilityInfo.mScalingRequired) {
                     mWindowLayoutParamsBackup = new int[4];
                 }
-                mAppScaleInverted = 1.0f / mAppScale;
-                mWindowAttributes.copyFrom(attrs);
+                if (!mCompatibilityInfo.mExpandable) {
+                    adjustWindowAttributesForCompatibleMode(mWindowAttributes);
+                }
                 mSoftInputMode = attrs.softInputMode;
                 mWindowAttributesChanged = true;
                 mAttachInfo.mRootView = view;
@@ -406,9 +410,8 @@
                 // manager, to make sure we do the relayout before receiving
                 // any other events from the system.
                 requestLayout();
-
                 try {
-                    res = sWindowSession.add(mWindow, attrs,
+                    res = sWindowSession.add(mWindow, mWindowAttributes,
                             getHostVisibility(), mAttachInfo.mContentInsets);
                 } catch (RemoteException e) {
                     mAdded = false;
@@ -417,7 +420,10 @@
                     unscheduleTraversals();
                     throw new RuntimeException("Adding window failed", e);
                 }
-                mAttachInfo.mContentInsets.scale(mAppScaleInverted);
+                if (mCompatibilityInfo.mScalingRequired) {
+                    mAttachInfo.mContentInsets.scale(
+                            mCompatibilityInfo.mApplicationInvertedScale);
+                }
                 mPendingContentInsets.set(mAttachInfo.mContentInsets);
                 mPendingVisibleInsets.set(0, 0, 0, 0);
                 if (Config.LOGV) Log.v("ViewRoot", "Added window " + mWindow);
@@ -529,13 +535,13 @@
     public void invalidateChild(View child, Rect dirty) {
         checkThread();
         if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty);
-        if (mCurScrollY != 0 || mAppScale != 1.0f) {
+        if (mCurScrollY != 0 || mCompatibilityInfo.mScalingRequired) {
             mTempRect.set(dirty);
             if (mCurScrollY != 0) {
                mTempRect.offset(0, -mCurScrollY);
             }
-            if (mAppScale != 1.0f) {
-                mTempRect.scale(mAppScale);
+            if (mCompatibilityInfo.mScalingRequired) {
+                mTempRect.scale(mCompatibilityInfo.mApplicationScale);
             }
             dirty = mTempRect;
         }
@@ -615,6 +621,8 @@
         boolean viewVisibilityChanged = mViewVisibility != viewVisibility
                 || mNewSurfaceNeeded;
 
+        float appScale = mCompatibilityInfo.mApplicationScale;
+
         WindowManager.LayoutParams params = null;
         if (mWindowAttributesChanged) {
             mWindowAttributesChanged = false;
@@ -625,9 +633,10 @@
             fullRedrawNeeded = true;
             mLayoutRequested = true;
 
-            Display d = new Display(0);
-            desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted);
-            desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted);
+            DisplayMetrics packageMetrics = 
+                mView.getContext().getResources().getDisplayMetrics();
+            desiredWindowWidth = packageMetrics.widthPixels;
+            desiredWindowHeight = packageMetrics.heightPixels;
 
             // For the very first time, tell the view hierarchy that it
             // is attached to the window.  Note that at this point the surface
@@ -696,9 +705,10 @@
                         || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                     windowResizesToFitContent = true;
 
-                    Display d = new Display(0);
-                    desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted);
-                    desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted);
+                    DisplayMetrics packageMetrics = 
+                        mView.getContext().getResources().getDisplayMetrics();
+                    desiredWindowWidth = packageMetrics.widthPixels;
+                    desiredWindowHeight = packageMetrics.heightPixels;
                 }
             }
 
@@ -878,7 +888,7 @@
             mHeight = frame.height();
 
             if (initialized) {
-                mGlCanvas.setViewport((int) (mWidth * mAppScale), (int) (mHeight * mAppScale));
+                mGlCanvas.setViewport((int) (mWidth * appScale), (int) (mHeight * appScale));
             }
 
             boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
@@ -968,11 +978,7 @@
                         mTmpLocation[1] + host.mBottom - host.mTop);
 
                 host.gatherTransparentRegion(mTransparentRegion);
-
-                // TODO: scale the region, like:
-                // Region uses native methods. We probabl should have ScalableRegion class.
-
-                // Region does not have equals method ?
+                mTransparentRegion.scale(appScale);                
                 if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
                     mPreviousTransparentRegion.set(mTransparentRegion);
                     // reconfigure window manager
@@ -983,7 +989,6 @@
                 }
             }
 
-
             if (DBG) {
                 System.out.println("======================================");
                 System.out.println("performTraversals -- after setFrame");
@@ -1003,10 +1008,11 @@
             givenContent.left = givenContent.top = givenContent.right
                     = givenContent.bottom = givenVisible.left = givenVisible.top
                     = givenVisible.right = givenVisible.bottom = 0;
-            insets.contentInsets.scale(mAppScale);
-            insets.visibleInsets.scale(mAppScale);
-
             attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
+            if (mCompatibilityInfo.mScalingRequired) {
+                insets.contentInsets.scale(appScale);
+                insets.visibleInsets.scale(appScale);
+            }
             if (insetsPending || !mLastGivenInsets.equals(insets)) {
                 mLastGivenInsets.set(insets);
                 try {
@@ -1154,6 +1160,8 @@
             mCurScrollY = yoff;
             fullRedrawNeeded = true;
         }
+        float appScale = mCompatibilityInfo.mApplicationScale;
+        boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
 
         Rect dirty = mDirty;
         if (mUseGL) {
@@ -1169,12 +1177,11 @@
                     mAttachInfo.mIgnoreDirtyState = true;
                     mView.mPrivateFlags |= View.DRAWN;
 
-                    float scale = mAppScale;
                     int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
                     try {
                         canvas.translate(0, -yoff);
-                        if (scale != 1.0f) {
-                            canvas.scale(scale, scale);
+                        if (scalingRequired) {
+                            canvas.scale(appScale, appScale);
                         }
                         mView.draw(canvas);
                         if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
@@ -1206,8 +1213,8 @@
         }
 
         if (fullRedrawNeeded) {
-            mAttachInfo.mIgnoreDirtyState = true;            
-            dirty.union(0, 0, (int) (mWidth * mAppScale), (int) (mHeight * mAppScale));
+            mAttachInfo.mIgnoreDirtyState = true;
+            dirty.union(0, 0, (int) (mWidth * appScale), (int) (mHeight * appScale));
         }
 
         if (DEBUG_ORIENTATION || DEBUG_DRAW) {
@@ -1215,7 +1222,8 @@
                     + mWindowAttributes.getTitle()
                     + ": dirty={" + dirty.left + "," + dirty.top
                     + "," + dirty.right + "," + dirty.bottom + "} surface="
-                    + surface + " surface.isValid()=" + surface.isValid());
+                    + surface + " surface.isValid()=" + surface.isValid() + ", appScale:" +
+                    appScale + ", width=" + mWidth + ", height=" + mHeight);
         }
 
         Canvas canvas;
@@ -1272,18 +1280,16 @@
                 mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
                 mView.mPrivateFlags |= View.DRAWN;
 
-                float scale = mAppScale;
                 if (DEBUG_DRAW) {
                     Context cxt = mView.getContext();
                     Log.i(TAG, "Drawing: package:" + cxt.getPackageName() +
-                            ", appScale=" + mAppScale);
+                            ", metrics=" + mView.getContext().getResources().getDisplayMetrics());
                 }
-                int saveCount =  canvas.save(Canvas.MATRIX_SAVE_FLAG);
+                int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
                 try {
                     canvas.translate(0, -yoff);
-                    if (scale != 1.0f) {
-                        // re-scale this
-                        canvas.scale(scale, scale);
+                    if (scalingRequired) {
+                        canvas.scale(appScale, appScale);
                     }
                     mView.draw(canvas);
                 } finally {
@@ -1586,8 +1592,8 @@
             } else {
                 didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
             }
-            if (event != null) {
-                event.scale(mAppScaleInverted);
+            if (event != null && mCompatibilityInfo.mScalingRequired) {
+                event.scale(mCompatibilityInfo.mApplicationInvertedScale);
             }
 
             try {
@@ -1709,8 +1715,9 @@
                         if (mGlWanted && !mUseGL) {
                             initializeGL();
                             if (mGlCanvas != null) {
-                                mGlCanvas.setViewport((int) (mWidth * mAppScale),
-                                        (int) (mHeight * mAppScale));
+                                float appScale = mCompatibilityInfo.mApplicationScale;
+                                mGlCanvas.setViewport(
+                                        (int) (mWidth * appScale), (int) (mHeight * appScale));
                             }
                         }
                     }
@@ -1914,8 +1921,8 @@
         } else {
             didFinish = false;
         }
-        if (event != null) {
-            event.scale(mAppScaleInverted);
+        if (event != null && mCompatibilityInfo.mScalingRequired) {
+            event.scale(mCompatibilityInfo.mApplicationInvertedScale);
         }
 
         if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
@@ -2345,27 +2352,59 @@
 
     private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
             boolean insetsPending) throws RemoteException {
-
         boolean restore = false;
-        if (params != null && mAppScale != 1.0f) {
+        float appScale = mCompatibilityInfo.mApplicationScale;
+        boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
+        
+        if (params != null && !mCompatibilityInfo.mExpandable) {
+            adjustWindowAttributesForCompatibleMode(params);
+        }
+        if (params != null && scalingRequired) {
             restore = true;
-            params.scale(mAppScale, mWindowLayoutParamsBackup);
+            params.scale(appScale, mWindowLayoutParamsBackup);
         }
         int relayoutResult = sWindowSession.relayout(
                 mWindow, params,
-                (int) (mView.mMeasuredWidth * mAppScale),
-                (int) (mView.mMeasuredHeight * mAppScale),
+                (int) (mView.mMeasuredWidth * appScale),
+                (int) (mView.mMeasuredHeight * appScale),
                 viewVisibility, insetsPending, mWinFrame,
                 mPendingContentInsets, mPendingVisibleInsets, mSurface);
         if (restore) {
             params.restore(mWindowLayoutParamsBackup);
         }
-
-        mPendingContentInsets.scale(mAppScaleInverted);
-        mPendingVisibleInsets.scale(mAppScaleInverted);
-        mWinFrame.scale(mAppScaleInverted);
+        if (scalingRequired) {
+            float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
+            mPendingContentInsets.scale(invertedScale);
+            mPendingVisibleInsets.scale(invertedScale);
+            mWinFrame.scale(invertedScale);
+        }
         return relayoutResult;
     }
+    
+    /**
+     * Adjust the window's layout parameter for compatibility mode. It replaces FILL_PARENT
+     * with the default window size, and centers if the window wanted to fill
+     * horizontally.
+     * 
+     * @param attrs the window's layout params to adjust
+     */
+    private void adjustWindowAttributesForCompatibleMode(WindowManager.LayoutParams attrs) {
+        // fix app windows only
+        if (attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+            DisplayMetrics metrics = mView.getContext().getResources().getDisplayMetrics();
+            // TODO: improve gravity logic
+            if (attrs.width == ViewGroup.LayoutParams.FILL_PARENT) {
+                attrs.width = metrics.widthPixels;
+                attrs.gravity |= Gravity.CENTER_HORIZONTAL;
+            }
+            if (attrs.height == ViewGroup.LayoutParams.FILL_PARENT) {
+                attrs.height = metrics.heightPixels;
+            }
+            if (DEBUG_LAYOUT) {
+                Log.d(TAG, "Attributes fixed for compatibility : " + attrs);
+            }
+        }
+    }
 
     /**
      * {@inheritDoc}
@@ -2470,11 +2509,16 @@
                 + " visibleInsets=" + visibleInsets.toShortString()
                 + " reportDraw=" + reportDraw);
         Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED);
-
-        coveredInsets.scale(mAppScaleInverted);
-        visibleInsets.scale(mAppScaleInverted);
-        msg.arg1 = (int) (w * mAppScaleInverted);
-        msg.arg2 = (int) (h * mAppScaleInverted);
+        if (mCompatibilityInfo.mScalingRequired) {
+            float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
+            coveredInsets.scale(invertedScale);
+            visibleInsets.scale(invertedScale);
+            msg.arg1 = (int) (w * invertedScale);
+            msg.arg2 = (int) (h * invertedScale);
+        } else {
+            msg.arg1 = w;
+            msg.arg2 = h;
+        }
         msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };
         sendMessage(msg);
     }
diff --git a/core/java/android/webkit/TextDialog.java b/core/java/android/webkit/TextDialog.java
index 9de97c9..99de56d 100644
--- a/core/java/android/webkit/TextDialog.java
+++ b/core/java/android/webkit/TextDialog.java
@@ -538,7 +538,8 @@
      * removing the password input type.
      */
     public void setSingleLine(boolean single) {
-        int inputType = EditorInfo.TYPE_CLASS_TEXT;
+        int inputType = EditorInfo.TYPE_CLASS_TEXT
+                | EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
         if (!single) {
             inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
                     | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ec02143..f62487f 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -472,7 +472,6 @@
     private ViewTreeObserver.OnGlobalLayoutListener mGesturesLayoutListener;
     private boolean mGlobalLayoutListenerAddedGestures;
     private boolean mInstallGesturesOverlay;
-    private boolean mPreviousGesturing;
 
     private boolean mGlobalLayoutListenerAddedFilter;
 
@@ -737,8 +736,6 @@
             mGesturesOverlay.removeAllOnGestureListeners();
             mGesturesOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);
             mGesturesOverlay.addOnGesturePerformedListener(new GesturesProcessor());
-
-            mPreviousGesturing = false;
         }
     }
 
@@ -753,25 +750,10 @@
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
         if (mGestures != GESTURES_NONE) {
-            if (ev.getAction() != MotionEvent.ACTION_DOWN || mFastScroller == null ||
-                    !mFastScroller.isPointInside(ev.getX(), ev.getY())) {
-
-                if (mGesturesPopup.isShowing()) {
-                    mGesturesOverlay.dispatchTouchEvent(ev);
-
-                    final boolean isGesturing = mGesturesOverlay.isGesturing();
-
-                    if (!isGesturing) {
-                        mPreviousGesturing = isGesturing;
-                        return super.dispatchTouchEvent(ev);
-                    } else if (!mPreviousGesturing){
-                        mPreviousGesturing = isGesturing;
-                        final MotionEvent event = MotionEvent.obtain(ev);
-                        event.setAction(MotionEvent.ACTION_CANCEL);
-                        super.dispatchTouchEvent(event);
-                        return true;
-                    }
-                }
+            if ((ev.getAction() != MotionEvent.ACTION_DOWN || mFastScroller == null ||
+                    !mFastScroller.isPointInside(ev.getX(), ev.getY())) &&
+                    mGesturesPopup.isShowing()) {
+                mGesturesOverlay.dispatchTouchEvent(ev);
             }
         }
 
@@ -1056,11 +1038,12 @@
     public Parcelable onSaveInstanceState() {
         /*
          * This doesn't really make sense as the place to dismiss the
-         * popup, but there don't seem to be any other useful hooks
+         * popups, but there don't seem to be any other useful hooks
          * that happen early enough to keep from getting complaints
          * about having leaked the window.
          */
         dismissPopup();
+        dismissGesturesPopup();
 
         Parcelable superState = super.onSaveInstanceState();
 
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 99cf6f8c..a195ac7 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1852,18 +1852,25 @@
     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
         boolean populated = super.dispatchPopulateAccessibilityEvent(event);
 
+        // If the item count is less than 15 then subtract disabled items from the count and
+        // position. Otherwise ignore disabled items.
         if (!populated) {
             int itemCount = 0;
             int currentItemIndex = getSelectedItemPosition();
 
             ListAdapter adapter = getAdapter();
             if (adapter != null) {
-                for (int i = 0, count = adapter.getCount(); i < count; i++) {
-                    if (adapter.isEnabled(i)) {
-                        itemCount++;
-                    } else if (i <= currentItemIndex) {
-                        currentItemIndex--;
+                final int count = adapter.getCount();
+                if (count < 15) {
+                    for (int i = 0; i < count; i++) {
+                        if (adapter.isEnabled(i)) {
+                            itemCount++;
+                        } else if (i <= currentItemIndex) {
+                            currentItemIndex--;
+                        }
                     }
+                } else {
+                    itemCount = count;
                 }
             }
 
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index ef240e0..84cf2c8 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -37,19 +37,19 @@
  * A Layout where the positions of the children can be described in relation to each other or to the
  * parent. For the sake of efficiency, the relations between views are evaluated in one pass, so if
  * view Y is dependent on the position of view X, make sure the view X comes first in the layout.
- * 
+ *
  * <p>
  * Note that you cannot have a circular dependency between the size of the RelativeLayout and the
  * position of its children. For example, you cannot have a RelativeLayout whose height is set to
  * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT WRAP_CONTENT} and a child set to
  * {@link #ALIGN_PARENT_BOTTOM}.
  * </p>
- * 
+ *
  * <p>
  * Also see {@link android.widget.RelativeLayout.LayoutParams RelativeLayout.LayoutParams} for
  * layout attributes
  * </p>
- * 
+ *
  * @attr ref android.R.styleable#RelativeLayout_gravity
  * @attr ref android.R.styleable#RelativeLayout_ignoreGravity
  */
@@ -327,7 +327,7 @@
         }
 
         if (widthMode != MeasureSpec.EXACTLY) {
-            // Width already has left padding in it since it was calculated by looking at 
+            // Width already has left padding in it since it was calculated by looking at
             // the right of each child view
             width += mPaddingRight;
 
@@ -339,7 +339,7 @@
             width = resolveSize(width, widthMeasureSpec);
         }
         if (heightMode != MeasureSpec.EXACTLY) {
-            // Height already has top padding in it since it was calculated by looking at 
+            // Height already has top padding in it since it was calculated by looking at
             // the bottom of each child view
             height += mPaddingBottom;
 
@@ -881,7 +881,7 @@
             @ViewDebug.IntToString(from = RIGHT_OF,            to = "rightOf")
         }, mapping = {
             @ViewDebug.IntToString(from = TRUE, to = "true"),
-            @ViewDebug.IntToString(from = 0,    to = "FALSE/NO_ID")
+            @ViewDebug.IntToString(from = 0,    to = "false/NO_ID")
         })
         private int[] mRules = new int[VERB_COUNT];
 
diff --git a/core/java/com/android/internal/backup/AdbTransport.java b/core/java/com/android/internal/backup/AdbTransport.java
new file mode 100644
index 0000000..acb3273
--- /dev/null
+++ b/core/java/com/android/internal/backup/AdbTransport.java
@@ -0,0 +1,28 @@
+package com.android.internal.backup;
+
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+
+/**
+ * Backup transport for full backup over adb.  This transport pipes everything to
+ * a file in a known location in /cache, which 'adb backup' then pulls to the desktop
+ * (deleting it afterwards).
+ */
+
+public class AdbTransport extends IBackupTransport.Stub {
+
+    public int startSession() throws RemoteException {
+        return 0;
+    }
+
+    public int endSession() throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public int performBackup(String packageName, ParcelFileDescriptor data)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+}
diff --git a/core/java/com/android/internal/backup/GoogleTransport.java b/core/java/com/android/internal/backup/GoogleTransport.java
new file mode 100644
index 0000000..85ab21e
--- /dev/null
+++ b/core/java/com/android/internal/backup/GoogleTransport.java
@@ -0,0 +1,28 @@
+package com.android.internal.backup;
+
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+
+/**
+ * Backup transport for saving data to Google cloud storage.
+ */
+
+public class GoogleTransport extends IBackupTransport.Stub {
+
+    public int endSession() throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public int performBackup(String packageName, ParcelFileDescriptor data)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public int startSession() throws RemoteException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+}
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index ce39768..2b44fe7 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.backup;
 
+import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 
 /** {@hide} */
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 51f3b02..99a381c 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -53,7 +53,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS' 
 
     // Current on-disk Parcel version
-    private static final int VERSION = 37;
+    private static final int VERSION = 38;
 
     private final File mFile;
     private final File mBackupFile;
@@ -1342,11 +1342,13 @@
         public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
             return mPackageStats;
         }
-        
+
+        @Override
         public int getUid() {
             return mUid;
         }
-        
+
+        @Override
         public long getTcpBytesReceived(int which) {
             if (which == STATS_LAST) {
                 return mLoadedTcpBytesReceived;
@@ -1365,7 +1367,8 @@
             return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
                     ? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0);
         }
-        
+
+        @Override
         public long getTcpBytesSent(int which) {
             if (which == STATS_LAST) {
                 return mLoadedTcpBytesSent;
@@ -1754,7 +1757,8 @@
             public Timer getSensorTime() {
                 return mTimer;
             }
-            
+
+            @Override
             public int getHandle() {
                 return mHandle;
             }
@@ -1780,6 +1784,11 @@
             int mStarts;
 
             /**
+             * Amount of time the process was running in the foreground.
+             */
+            long mForegroundTime;
+
+            /**
              * The amount of user time loaded from a previous save.
              */
             long mLoadedUserTime;
@@ -1795,6 +1804,11 @@
             int mLoadedStarts;
 
             /**
+             * The amount of foreground time loaded from a previous save.
+             */
+            long mLoadedForegroundTime;
+
+            /**
              * The amount of user time loaded from the previous run.
              */
             long mLastUserTime;
@@ -1810,6 +1824,11 @@
             int mLastStarts;
 
             /**
+             * The amount of foreground time loaded from the previous run
+             */
+            long mLastForegroundTime;
+
+            /**
              * The amount of user time when last unplugged.
              */
             long mUnpluggedUserTime;
@@ -1824,6 +1843,11 @@
              */
             int mUnpluggedStarts;
 
+            /**
+             * The amount of foreground time since unplugged.
+             */
+            long mUnpluggedForegroundTime;
+
             Proc() {
                 mUnpluggables.add(this);
             }
@@ -1832,6 +1856,7 @@
                 mUnpluggedUserTime = mUserTime;
                 mUnpluggedSystemTime = mSystemTime;
                 mUnpluggedStarts = mStarts;
+                mUnpluggedForegroundTime = mForegroundTime;
             }
 
             public void plug(long batteryUptime, long batteryRealtime) {
@@ -1843,30 +1868,38 @@
                 
                 out.writeLong(mUserTime);
                 out.writeLong(mSystemTime);
+                out.writeLong(mForegroundTime);
                 out.writeInt(mStarts);
                 out.writeLong(mLoadedUserTime);
                 out.writeLong(mLoadedSystemTime);
+                out.writeLong(mLoadedForegroundTime);
                 out.writeInt(mLoadedStarts);
                 out.writeLong(mLastUserTime);
                 out.writeLong(mLastSystemTime);
+                out.writeLong(mLastForegroundTime);
                 out.writeInt(mLastStarts);
                 out.writeLong(mUnpluggedUserTime);
                 out.writeLong(mUnpluggedSystemTime);
+                out.writeLong(mUnpluggedForegroundTime);
                 out.writeInt(mUnpluggedStarts);
             }
 
             void readFromParcelLocked(Parcel in) {
                 mUserTime = in.readLong();
                 mSystemTime = in.readLong();
+                mForegroundTime = in.readLong();
                 mStarts = in.readInt();
                 mLoadedUserTime = in.readLong();
                 mLoadedSystemTime = in.readLong();
+                mLoadedForegroundTime = in.readLong();
                 mLoadedStarts = in.readInt();
                 mLastUserTime = in.readLong();
                 mLastSystemTime = in.readLong();
+                mLastForegroundTime = in.readLong();
                 mLastStarts = in.readInt();
                 mUnpluggedUserTime = in.readLong();
                 mUnpluggedSystemTime = in.readLong();
+                mUnpluggedForegroundTime = in.readLong();
                 mUnpluggedStarts = in.readInt();
             }
 
@@ -1879,6 +1912,10 @@
                 mSystemTime += stime;
             }
 
+            public void addForegroundTimeLocked(long ttime) {
+                mForegroundTime += ttime;
+            }
+
             public void incStartsLocked() {
                 mStarts++;
             }
@@ -1916,6 +1953,22 @@
             }
 
             @Override
+            public long getForegroundTime(int which) {
+                long val;
+                if (which == STATS_LAST) {
+                    val = mLastForegroundTime;
+                } else {
+                    val = mForegroundTime;
+                    if (which == STATS_CURRENT) {
+                        val -= mLoadedForegroundTime;
+                    } else if (which == STATS_UNPLUGGED) {
+                        val -= mUnpluggedForegroundTime;
+                    }
+                }
+                return val;
+            }
+
+            @Override
             public int getStarts(int which) {
                 int val;
                 if (which == STATS_LAST) {
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 1fd15d6..137707f 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -311,7 +311,7 @@
                                    int sampleSize) {
     SkPixelRef* pr;
     // only use ashmem for large images, since mmaps come at a price
-    if (bitmap->getSize() >= 32 * 65536) {
+    if (bitmap->getSize() >= 32 * 1024) {
         pr = new SkImageRef_ashmem(stream, bitmap->config(), sampleSize);
     } else {
         pr = new SkImageRef_GlobalPool(stream, bitmap->config(), sampleSize);
@@ -520,7 +520,10 @@
     */
     AutoFDSeek as(descriptor);
 
-    return doDecode(env, stream, padding, bitmapFactoryOptions, true);
+    /* Allow purgeable iff we own the FD, i.e., in the puregeable and
+       shareable case.
+    */
+    return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD);
 }
 
 /*  make a deep copy of the asset, and return it as a stream, or NULL if there
diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp
index 8fce2a2..aab1233 100644
--- a/core/jni/android_backup_BackupDataOutput.cpp
+++ b/core/jni/android_backup_BackupDataOutput.cpp
@@ -20,7 +20,7 @@
 #include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 
-#include <utils/backup_helpers.h>
+#include <utils/BackupHelpers.h>
 
 namespace android
 {
diff --git a/core/jni/android_backup_FileBackupHelper.cpp b/core/jni/android_backup_FileBackupHelper.cpp
index a05d812..a46f37b 100644
--- a/core/jni/android_backup_FileBackupHelper.cpp
+++ b/core/jni/android_backup_FileBackupHelper.cpp
@@ -20,7 +20,7 @@
 #include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 
-#include <utils/backup_helpers.h>
+#include <utils/BackupHelpers.h>
 
 namespace android
 {
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index eb94812..9b9c2e4 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -125,4 +125,14 @@
         <item><xliff:g id="id">sync_failing</xliff:g></item>
         <item><xliff:g id="id">ime</xliff:g></item>
     </string-array>
+
+    <!-- Do not translate. Each string points to the component name of an ACTION_WEB_SEARCH
+         handling activity. On startup if there were no preferred ACTION_WEB_SEARCH handlers,
+         the first component from this list which is found to be installed is set as the
+         preferred activity. -->
+    <string-array name="default_web_search_providers">
+        <item>com.google.android.providers.genie/.GenieLauncher</item>
+        <item>com.android.googlesearch/.GoogleSearch</item>
+        <item>com.android.websearch/.Search.1</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 817a566..0a2d208 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -810,12 +810,19 @@
     <!-- 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 #AndroidManifestApplication application} tag. -->
-    <declare-styleable name="AndroidManifestSupportsDensity" parent="AndroidManifestApplication">
+         {@link #AndroidManifest manifest} tag. -->
+    <declare-styleable name="AndroidManifestSupportsDensity" parent="AndroidManifest">
         <!-- Required value of the density in dip (device independent pixel). -->
         <attr name="density" format="integer" />
     </declare-styleable>
 
+    <!-- The <code>expandable</code> specifies if this package supports screen metrics
+         other than 320x480 dip.
+         <p>This appears as a child tag of the
+         {@link #AndroidManifest manifest} tag. -->
+    <declare-styleable name="AndroidManifestExpandable" parent="AndroidManifest">
+    </declare-styleable>
+
     <!-- The <code>provider</code> tag declares a
          {@link android.content.ContentProvider} class that is available
          as part of the package's application components, supplying structured
diff --git a/core/res/res/xml/power_profile_default.xml b/core/res/res/xml/power_profile_default.xml
index d265b46..ceecb1a 100644
--- a/core/res/res/xml/power_profile_default.xml
+++ b/core/res/res/xml/power_profile_default.xml
@@ -22,7 +22,7 @@
   <item name="screen.on">30</item>
   <item name="bluetooth.active">103</item>
   <item name="bluetooth.on">5</item>
-  <item name="screen.full">144</item>
+  <item name="screen.full">114</item>
   <item name="wifi.on">23</item>
   <item name="wifi.active">200</item>
   <item name="wifi.scan">200</item>
@@ -33,4 +33,5 @@
   <item name="dsp.video">100</item>
   <item name="radio.on">3</item>
   <item name="radio.active">175</item>
+  <item name="gps.on">120</item>
 </device>
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 141cc68..e5a9aab 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -125,8 +125,6 @@
          * false, then this field is ignored. If inPurgeable is true, then this
          * field determines whether the bitmap can share a reference to the
          * input data (inputstream, array, etc.) or if it must make a deep copy.
-         *
-         * @hide pending API council approval
          */
         public boolean inInputShareable;
 
diff --git a/include/utils/backup_helpers.h b/include/utils/BackupHelpers.h
similarity index 100%
rename from include/utils/backup_helpers.h
rename to include/utils/BackupHelpers.h
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 5a1a89b..9bdd64a 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -117,8 +117,8 @@
 	IPermissionController.cpp \
 	IServiceManager.cpp \
 	Unicode.cpp \
-    backup_data.cpp \
-	backup_helper_file.cpp
+    BackupData.cpp \
+	BackupHelpers.cpp
 
 ifeq ($(TARGET_SIMULATOR),true)
 LOCAL_SRC_FILES += $(hostSources)
diff --git a/libs/utils/backup_data.cpp b/libs/utils/BackupData.cpp
similarity index 99%
rename from libs/utils/backup_data.cpp
rename to libs/utils/BackupData.cpp
index 95c05b7..120f23d 100644
--- a/libs/utils/backup_data.cpp
+++ b/libs/utils/BackupData.cpp
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "backup_data"
 
-#include <utils/backup_helpers.h>
+#include <utils/BackupHelpers.h>
 #include <utils/ByteOrder.h>
 
 #include <stdio.h>
diff --git a/libs/utils/backup_helper_file.cpp b/libs/utils/BackupHelpers.cpp
similarity index 99%
rename from libs/utils/backup_helper_file.cpp
rename to libs/utils/BackupHelpers.cpp
index 7ec2ce8..7f423a8 100644
--- a/libs/utils/backup_helper_file.cpp
+++ b/libs/utils/BackupHelpers.cpp
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "file_backup_helper"
 
-#include <utils/backup_helpers.h>
+#include <utils/BackupHelpers.h>
 
 #include <utils/KeyedVector.h>
 #include <utils/ByteOrder.h>
@@ -350,10 +350,11 @@
             FileState& g = newSnapshot.editValueAt(m);
 
             int fd = open(realFilename.string(), O_RDONLY);
-            if (fd != -1) {
+            if (fd < 0) {
                 // We can't open the file.  Don't report it as a delete either.  Let the
                 // server keep the old version.  Maybe they'll be able to deal with it
                 // on restore.
+                LOGP("Unable to open file %s - skipping", realFilename.string());
             } else {
                 g.crc32 = compute_crc32(fd);
 
diff --git a/libs/utils/characterData.h b/libs/utils/CharacterData.h
similarity index 100%
rename from libs/utils/characterData.h
rename to libs/utils/CharacterData.h
diff --git a/libs/utils/Unicode.cpp b/libs/utils/Unicode.cpp
index 33f535f..f92703e 100644
--- a/libs/utils/Unicode.cpp
+++ b/libs/utils/Unicode.cpp
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#include "utils/AndroidUnicode.h"
-#include "characterData.h"
+#include <utils/AndroidUnicode.h>
+#include "CharacterData.h"
 
 #define LOG_TAG "Unicode"
-#include "utils/Log.h"
+#include <utils/Log.h>
 
 // ICU headers for using macros
 #include <unicode/utf16.h>
diff --git a/libs/utils/ZipEntry.cpp b/libs/utils/ZipEntry.cpp
index fbc9e67..96f9fc4 100644
--- a/libs/utils/ZipEntry.cpp
+++ b/libs/utils/ZipEntry.cpp
@@ -20,8 +20,8 @@
 
 #define LOG_TAG "zip"
 
-#include "utils/ZipEntry.h"
-#include "utils/Log.h"
+#include <utils/ZipEntry.h>
+#include <utils/Log.h>
 
 #include <stdio.h>
 #include <string.h>
diff --git a/libs/utils/ZipFile.cpp b/libs/utils/ZipFile.cpp
index 89aa874..6f27d17 100644
--- a/libs/utils/ZipFile.cpp
+++ b/libs/utils/ZipFile.cpp
@@ -20,9 +20,9 @@
 
 #define LOG_TAG "zip"
 
-#include "utils/ZipFile.h"
-#include "utils/ZipUtils.h"
-#include "utils/Log.h"
+#include <utils/ZipFile.h>
+#include <utils/ZipUtils.h>
+#include <utils/Log.h>
 
 #include <zlib.h>
 #define DEF_MEM_LEVEL 8                // normally in zutil.h?
diff --git a/libs/utils/ZipFileCRO.cpp b/libs/utils/ZipFileCRO.cpp
index d312daf..45f6c8b 100644
--- a/libs/utils/ZipFileCRO.cpp
+++ b/libs/utils/ZipFileCRO.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include "utils/ZipFileCRO.h"
-#include "utils/ZipFileRO.h"
+#include <utils/ZipFileCRO.h>
+#include <utils/ZipFileRO.h>
 
 using namespace android;
 
diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp
index ae8c719..6c701dd 100644
--- a/libs/utils/ZipFileRO.cpp
+++ b/libs/utils/ZipFileRO.cpp
@@ -19,9 +19,9 @@
 //
 #define LOG_TAG "zipro"
 //#define LOG_NDEBUG 0
-#include "utils/ZipFileRO.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
+#include <utils/ZipFileRO.h>
+#include <utils/Log.h>
+#include <utils/misc.h>
 
 #include <zlib.h>
 
diff --git a/libs/utils/ZipUtils.cpp b/libs/utils/ZipUtils.cpp
index bfbacfe..5df94cb 100644
--- a/libs/utils/ZipUtils.cpp
+++ b/libs/utils/ZipUtils.cpp
@@ -20,9 +20,9 @@
 
 #define LOG_TAG "ziputil"
 
-#include "utils/ZipUtils.h"
-#include "utils/ZipFileRO.h"
-#include "utils/Log.h"
+#include <utils/ZipUtils.h>
+#include <utils/ZipFileRO.h>
+#include <utils/Log.h>
 
 #include <stdlib.h>
 #include <string.h>
diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp
index 8fa7566..3e9c6a5 100644
--- a/opengl/libagl/array.cpp
+++ b/opengl/libagl/array.cpp
@@ -951,6 +951,8 @@
     v->index = first;
     first &= vertex_cache_t::INDEX_MASK;
     const GLubyte* vp = c->arrays.vertex.element(first);
+    v->obj.z = 0;
+    v->obj.w = 0x10000;
     c->arrays.vertex.fetch(c, v->obj.v, vp);
     c->arrays.mvp_transform(&c->transforms.mvp, &v->clip, &v->obj);
     c->arrays.perspective(c, v);
@@ -966,6 +968,8 @@
     do {
         v->flags = 0;
         v->index = first++;
+        v->obj.z = 0;
+        v->obj.w = 0x10000;
         c->arrays.vertex.fetch(c, v->obj.v, vp);
         c->arrays.mvp_transform(mvp, &v->clip, &v->obj);
         c->arrays.perspective(c, v);
diff --git a/opengl/libagl/light.cpp b/opengl/libagl/light.cpp
index 25c41d0..8ae32cc0f 100644
--- a/opengl/libagl/light.cpp
+++ b/opengl/libagl/light.cpp
@@ -38,13 +38,14 @@
 static void lightVertexMaterial(ogles_context_t* c, vertex_t* v);
 
 static inline void vscale3(GLfixed* d, const GLfixed* m, GLfixed s);
-static inline void vsub3w(GLfixed* d, const GLfixed* a, const GLfixed* b);
 
 static __attribute__((noinline))
 void vnorm3(GLfixed* d, const GLfixed* a);
 
 static inline void vsa3(GLfixed* d,
     const GLfixed* m, GLfixed s, const GLfixed* a);
+static inline void vss3(GLfixed* d,
+    const GLfixed* m, GLfixed s, const GLfixed* a);
 static inline void vmla3(GLfixed* d,
     const GLfixed* m0, const GLfixed* m1, const GLfixed* a);
 static inline void vmul3(GLfixed* d,
@@ -151,18 +152,10 @@
 }
 
 static inline
-void vsub3w(GLfixed* d, const GLfixed* a, const GLfixed* b) {
-    const GLfixed wa = a[3];
-    const GLfixed wb = b[3];
-    if (ggl_likely(wa == wb)) {
-        d[0] = a[0] - b[0];
-        d[1] = a[1] - b[1];
-        d[2] = a[2] - b[2];
-    } else {
-        d[0] = gglMulSubx(a[0], wb, gglMulx(b[0], wa));
-        d[1] = gglMulSubx(a[1], wb, gglMulx(b[1], wa));
-        d[2] = gglMulSubx(a[2], wb, gglMulx(b[2], wa));
-    }
+void vss3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) {
+    d[0] = gglMulSubx(m[0], s, a[0]);
+    d[1] = gglMulSubx(m[1], s, a[1]);
+    d[2] = gglMulSubx(m[2], s, a[2]);
 }
 
 static inline
@@ -227,7 +220,7 @@
         const int i = 31 - gglClz(en);
         en &= ~(1<<i);
         light_t& l = c->lighting.lights[i];
-        c->transforms.mvui.point3(&c->transforms.mvui,
+        c->transforms.mvui.point4(&c->transforms.mvui,
                 &l.objPosition, &l.position);
         vnorm3(l.normalizedObjPosition.v, l.objPosition.v);
     }
@@ -318,6 +311,11 @@
         vmul3(l.implicitAmbient.v,  material.ambient.v,  l.ambient.v);
         vmul3(l.implicitDiffuse.v,  material.diffuse.v,  l.diffuse.v);
         vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
+        // this is just a flag to tell if we have a specular component
+        l.implicitSpecular.v[3] =
+                l.implicitSpecular.r |
+                l.implicitSpecular.g |
+                l.implicitSpecular.b;
     }
     // emission and ambient for the whole scene
     vmla3(  c->lighting.implicitSceneEmissionAndAmbient.v,
@@ -343,7 +341,11 @@
         vec4_t n;
         c->arrays.normal.fetch(c, n.v,
             c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK));
-        if (c->transforms.rescaleNormals == GL_NORMALIZE)
+
+        // TODO: right now we handle GL_RESCALE_NORMALS as if ti were
+        // GL_NORMALIZE. We could optimize this by  scaling mvui 
+        // appropriately instead.
+        if (c->transforms.rescaleNormals)
             vnorm3(n.v, n.v);
 
         const material_t& material = c->lighting.front;
@@ -360,7 +362,8 @@
 
             // compute vertex-to-light vector
             if (ggl_unlikely(l.position.w)) {
-                vsub3w(d.v, l.objPosition.v, v->obj.v);
+                // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex
+                vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v);
                 sqDist = dot3(d.v, d.v);
                 vscale3(d.v, d.v, gglSqrtRecipx(sqDist));
             } else {
diff --git a/opengl/libagl/matrix.cpp b/opengl/libagl/matrix.cpp
index f175cda..0b68dc0 100644
--- a/opengl/libagl/matrix.cpp
+++ b/opengl/libagl/matrix.cpp
@@ -55,7 +55,7 @@
 static void point2__generic(transform_t const*, vec4_t* c, vec4_t const* o);
 static void point3__generic(transform_t const*, vec4_t* c, vec4_t const* o);
 static void point4__generic(transform_t const*, vec4_t* c, vec4_t const* o);
-static void normal__generic(transform_t const*, vec4_t* c, vec4_t const* o);
+static void point4__mvui(transform_t const*, vec4_t* c, vec4_t const* o);
 
 // ----------------------------------------------------------------------------
 #if 0
@@ -209,7 +209,8 @@
 {
     flags = 0;
     ops = OP_ALL;
-    point3 = normal__generic;
+    point3 = point4__mvui;
+    point4 = point4__mvui;
 }
 
 void transform_t::dump(const char* what)
@@ -596,66 +597,19 @@
 
 void transform_state_t::update_mvui()
 {
+    GLfloat r[16];
     const GLfloat* const mv = modelview.top().elements();
-
-    /*
-    When transforming normals, we can use the upper 3x3 matrix, see:
-    http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node26.html
-    */
     
-    // Also note that:
-    //      l(obj) =  tr(M).l(eye) for infinite light
-    //      l(obj) = inv(M).l(eye) for local light
-
-    const uint32_t ops = modelview.top_ops() & ~OP_TRANSLATE;
-    if (ggl_likely((!(ops & ~OP_ROTATE)) ||
-        (rescaleNormals && modelview.isRigidBody()))) {
-        // if the modelview matrix is a rigid body transformation
-        // (translation, rotation, uniform scaling), then we can bypass
-        // the inverse by transposing the matrix.
-        GLfloat rescale = 1.0f;
-        if (rescaleNormals == GL_RESCALE_NORMAL) {
-            if (!(ops & ~OP_UNIFORM_SCALE)) {
-                rescale = reciprocalf(mv[I(0,0)]);
-            } else {
-                rescale = rsqrtf(
-                        sqrf(mv[I(2,0)]) + sqrf(mv[I(2,1)]) + sqrf(mv[I(2,2)]));
-            }
-        }
-        GLfixed* const x = mvui.matrix.m;
-        for (int i=0 ; i<3 ; i++) {
-            x[I(i,0)] = gglFloatToFixed(mv[I(0,i)] * rescale);
-            x[I(i,1)] = gglFloatToFixed(mv[I(1,i)] * rescale);
-            x[I(i,2)] = gglFloatToFixed(mv[I(2,i)] * rescale);
-        }
-        mvui.picker();
-        return;
-    }
-
-    GLfloat r[3][3];
-    r[0][0] = det22(mv[I(1,1)], mv[I(2,1)], mv[I(1,2)], mv[I(2,2)]);
-    r[0][1] =ndet22(mv[I(0,1)], mv[I(2,1)], mv[I(0,2)], mv[I(2,2)]);
-    r[0][2] = det22(mv[I(0,1)], mv[I(1,1)], mv[I(0,2)], mv[I(1,2)]);
-    r[1][0] =ndet22(mv[I(1,0)], mv[I(2,0)], mv[I(1,2)], mv[I(2,2)]);
-    r[1][1] = det22(mv[I(0,0)], mv[I(2,0)], mv[I(0,2)], mv[I(2,2)]);
-    r[1][2] =ndet22(mv[I(0,0)], mv[I(1,0)], mv[I(0,2)], mv[I(1,2)]);
-    r[2][0] = det22(mv[I(1,0)], mv[I(2,0)], mv[I(1,1)], mv[I(2,1)]);
-    r[2][1] =ndet22(mv[I(0,0)], mv[I(2,0)], mv[I(0,1)], mv[I(2,1)]);
-    r[2][2] = det22(mv[I(0,0)], mv[I(1,0)], mv[I(0,1)], mv[I(1,1)]);        
-
-    GLfloat rdet;
-    if (rescaleNormals == GL_RESCALE_NORMAL) {
-        rdet = rsqrtf(sqrf(r[0][2]) + sqrf(r[1][2]) + sqrf(r[2][2]));
-    } else {
-        rdet = reciprocalf( 
-            r[0][0]*mv[I(0,0)] + r[0][1]*mv[I(1,0)] + r[0][2]*mv[I(2,0)]);
-    }
+    // TODO: we need a faster invert, especially for when the modelview
+    // is a rigid-body matrix
+    invert(r, mv);
 
     GLfixed* const x = mvui.matrix.m;
-    for (int i=0 ; i<3 ; i++) {
-        x[I(i,0)] = gglFloatToFixed(r[i][0] * rdet);
-        x[I(i,1)] = gglFloatToFixed(r[i][1] * rdet);
-        x[I(i,2)] = gglFloatToFixed(r[i][2] * rdet);
+    for (int i=0 ; i<4 ; i++) {
+        x[I(i,0)] = gglFloatToFixed(r[I(i,0)]);
+        x[I(i,1)] = gglFloatToFixed(r[I(i,1)]);
+        x[I(i,2)] = gglFloatToFixed(r[I(i,2)]);
+        x[I(i,4)] = gglFloatToFixed(r[I(i,3)]);
     }
     mvui.picker();
 }
@@ -783,14 +737,19 @@
     lhs->w = mla4(rx, m[ 3], ry, m[ 7], rz, m[11], rw, m[15]);
 }
 
-void normal__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) {
+void point4__mvui(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) {
+    // this used for transforming light positions back to object space.
+    // Lights have 3 components positions, so w is always 1.
+    // however, it is used as a switch for directional lights, so we need
+    // to preserve it.
     const GLfixed* const m = mx->matrix.m;
     const GLfixed rx = rhs->x;
     const GLfixed ry = rhs->y;
     const GLfixed rz = rhs->z;
-    lhs->x = mla3(rx, m[ 0], ry, m[ 4], rz, m[ 8]); 
-    lhs->y = mla3(rx, m[ 1], ry, m[ 5], rz, m[ 9]);
-    lhs->z = mla3(rx, m[ 2], ry, m[ 6], rz, m[10]);
+    lhs->x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); 
+    lhs->y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]);
+    lhs->z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]);
+    lhs->w = rhs->w;
 }
 
 
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 82ed1e3..5770a77 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -26,6 +26,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -34,11 +35,17 @@
 import android.os.IBinder;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.SparseArray;
 
 import android.backup.IBackupManager;
+import android.backup.BackupManager;
+
+import com.android.internal.backup.AdbTransport;
+import com.android.internal.backup.GoogleTransport;
+import com.android.internal.backup.IBackupTransport;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -59,6 +66,7 @@
     //private static final long COLLECTION_INTERVAL = 3 * 60 * 1000;
 
     private static final int MSG_RUN_BACKUP = 1;
+    private static final int MSG_RUN_FULL_BACKUP = 2;
     
     private Context mContext;
     private PackageManager mPackageManager;
@@ -89,6 +97,16 @@
     private ArrayList<BackupRequest> mBackupQueue;
     private final Object mQueueLock = new Object();
 
+    // The thread performing the sequence of queued backups binds to each app's agent
+    // in succession.  Bind notifications are asynchronously delivered through the
+    // Activity Manager; use this lock object to signal when a requested binding has
+    // completed.
+    private final Object mAgentConnectLock = new Object();
+    private IBackupAgent mConnectedAgent;
+    private volatile boolean mConnecting;
+
+    private int mTransportId;
+
     private File mStateDir;
     private File mDataDir;
     
@@ -101,6 +119,7 @@
         mStateDir = new File(Environment.getDataDirectory(), "backup");
         mStateDir.mkdirs();
         mDataDir = Environment.getDownloadCacheDirectory();
+        mTransportId = BackupManager.TRANSPORT_GOOGLE;
         
         // Build our mapping of uid to backup client services
         synchronized (mBackupParticipants) {
@@ -130,6 +149,8 @@
                 return;
             }
 
+            // !!! TODO: this is buggy right now; we wind up with duplicate participant entries
+            // after using 'adb install -r' of a participating app
             String action = intent.getAction();
             if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
                 synchronized (mBackupParticipants) {
@@ -166,7 +187,7 @@
                 // snapshot the pending-backup set and work on that
                 synchronized (mQueueLock) {
                     if (mBackupQueue == null) {
-                        mBackupQueue = new ArrayList();
+                        mBackupQueue = new ArrayList<BackupRequest>();
                         for (BackupRequest b: mPendingBackups.values()) {
                             mBackupQueue.add(b);
                         }
@@ -176,68 +197,24 @@
                     // WARNING: If we crash after this line, anything in mPendingBackups will
                     // be lost.  FIX THIS.
                 }
-                startOneAgent();
+                (new PerformBackupThread(mTransportId, mBackupQueue)).run();
+                break;
+
+            case MSG_RUN_FULL_BACKUP:
                 break;
             }
         }
     }
 
-    void startOneAgent() {
-        // Loop until we find someone to start or the queue empties out.
-        while (true) {
-            BackupRequest request;
-            synchronized (mQueueLock) {
-                int queueSize = mBackupQueue.size();
-                Log.d(TAG, "mBackupQueue.size=" + queueSize);
-                if (queueSize == 0) {
-                    mBackupQueue = null;
-                    // if there are pending backups, start those after a short delay
-                    if (mPendingBackups.size() > 0) {
-                        mBackupHandler.sendEmptyMessageDelayed(MSG_RUN_BACKUP, COLLECTION_INTERVAL);
-                    }
-                    return;
-                }
-                request = mBackupQueue.get(0);
-                // Take it off the queue when we're done.
-            }
-            
-            Log.d(TAG, "starting agent for " + request);
-            // !!! TODO: need to handle the restore case?
-            int mode = (request.fullBackup)
-                    ? IApplicationThread.BACKUP_MODE_FULL
-                    : IApplicationThread.BACKUP_MODE_INCREMENTAL;
-            try {
-                if (mActivityManager.bindBackupAgent(request.appInfo, mode)) {
-                    Log.d(TAG, "awaiting agent for " + request);
-                    // success
-                    return;
-                }
-            } catch (RemoteException e) {
-                // can't happen; activity manager is local
-            } catch (SecurityException ex) {
-                // Try for the next one.
-                Log.d(TAG, "error in bind", ex);
-            }
-        }
-    }
-
-    void processOneBackup(String packageName, IBackupAgent bs) {
+    void processOneBackup(BackupRequest request, IBackupAgent agent, IBackupTransport transport) {
+        final String packageName = request.appInfo.packageName;
         Log.d(TAG, "processOneBackup doBackup() on " + packageName);
 
-        BackupRequest request;
-        synchronized (mQueueLock) {
-            if (mBackupQueue == null) {
-                Log.d(TAG, "mBackupQueue is null.  WHY?");
-            }
-            request = mBackupQueue.get(0);
-        }
-
         try {
-            // !!! TODO right now these naming schemes limit applications to
-            // one backup service per package
-            File savedStateName = new File(mStateDir, request.appInfo.packageName);
-            File backupDataName = new File(mDataDir, request.appInfo.packageName + ".data");
-            File newStateName = new File(mStateDir, request.appInfo.packageName + ".new");
+            // !!! TODO: get the state file dir from the transport
+            File savedStateName = new File(mStateDir, packageName);
+            File backupDataName = new File(mDataDir, packageName + ".data");
+            File newStateName = new File(mStateDir, packageName + ".new");
             
             // In a full backup, we pass a null ParcelFileDescriptor as
             // the saved-state "file"
@@ -259,9 +236,10 @@
                             ParcelFileDescriptor.MODE_CREATE);
 
             // Run the target's backup pass
+            boolean success = false;
             try {
-                // TODO: Make this oneway
-                bs.doBackup(savedState, backupData, newState);
+                agent.doBackup(savedState, backupData, newState);
+                success = true;
             } finally {
                 if (savedState != null) {
                     savedState.close();
@@ -270,43 +248,35 @@
                 newState.close();
             }
 
-            // !!! TODO: Now propagate the newly-backed-up data to the transport
-            
-            // !!! TODO: After successful transport, delete the now-stale data
-            // and juggle the files so that next time the new state is passed
-            //backupDataName.delete();
-            newStateName.renameTo(savedStateName);
-            
+            // Now propagate the newly-backed-up data to the transport
+            if (success) {
+                if (DEBUG) Log.v(TAG, "doBackup() success; calling transport");
+                backupData =
+                    ParcelFileDescriptor.open(backupDataName, ParcelFileDescriptor.MODE_READ_ONLY);
+                int error = transport.performBackup(packageName, backupData);
+
+                // !!! TODO: After successful transport, delete the now-stale data
+                // and juggle the files so that next time the new state is passed
+                //backupDataName.delete();
+                newStateName.renameTo(savedStateName);
+            }
         } catch (FileNotFoundException fnf) {
             Log.d(TAG, "File not found on backup: ");
             fnf.printStackTrace();
         } catch (RemoteException e) {
-            Log.d(TAG, "Remote target " + packageName + " threw during backup:");
+            Log.d(TAG, "Remote target " + request.appInfo.packageName + " threw during backup:");
             e.printStackTrace();
         } catch (Exception e) {
             Log.w(TAG, "Final exception guard in backup: ");
             e.printStackTrace();
         }
-        synchronized (mQueueLock) {
-            mBackupQueue.remove(0);
-        }
-
-        if (request != null) {
-            try {
-                mActivityManager.unbindBackupAgent(request.appInfo);
-            } catch (RemoteException e) {
-                // can't happen
-            }
-        }
-
-        // start the next one
-        startOneAgent();
     }
 
     // Add the backup agents in the given package to our set of known backup participants.
     // If 'packageName' is null, adds all backup agents in the whole system.
     void addPackageParticipantsLocked(String packageName) {
         // Look for apps that define the android:backupAgent attribute
+        if (DEBUG) Log.v(TAG, "addPackageParticipantsLocked: " + packageName);
         List<ApplicationInfo> targetApps = allAgentApps();
         addPackageParticipantsLockedInner(packageName, targetApps);
     }
@@ -336,6 +306,7 @@
     // Remove the given package's backup services from our known active set.  If
     // 'packageName' is null, *all* backup services will be removed.
     void removePackageParticipantsLocked(String packageName) {
+        if (DEBUG) Log.v(TAG, "removePackageParticipantsLocked: " + packageName);
         List<ApplicationInfo> allApps = null;
         if (packageName != null) {
             allApps = new ArrayList<ApplicationInfo>();
@@ -354,6 +325,13 @@
 
     private void removePackageParticipantsLockedInner(String packageName,
             List<ApplicationInfo> agents) {
+        if (DEBUG) {
+            Log.v(TAG, "removePackageParticipantsLockedInner (" + packageName
+                    + ") removing " + agents.size() + " entries");
+            for (ApplicationInfo a : agents) {
+                Log.v(TAG, "    - " + a);
+            }
+        }
         for (ApplicationInfo app : agents) {
             if (packageName == null || app.packageName.equals(packageName)) {
                 int uid = app.uid;
@@ -361,8 +339,7 @@
                 if (set != null) {
                     set.remove(app);
                     if (set.size() == 0) {
-                        mBackupParticipants.put(uid, null);
-                    }
+                        mBackupParticipants.delete(uid);                    }
                 }
             }
         }
@@ -390,6 +367,7 @@
             Log.e(TAG, "updatePackageParticipants called with null package name");
             return;
         }
+        if (DEBUG) Log.v(TAG, "updatePackageParticipantsLocked: " + packageName);
 
         // brute force but small code size
         List<ApplicationInfo> allApps = allAgentApps();
@@ -397,6 +375,128 @@
         addPackageParticipantsLockedInner(packageName, allApps);
     }
 
+    // ----- Back up a set of applications via a worker thread -----
+
+    class PerformBackupThread extends Thread {
+        private static final String TAG = "PerformBackupThread";
+        int mTransport;
+        ArrayList<BackupRequest> mQueue;
+
+        public PerformBackupThread(int transportId, ArrayList<BackupRequest> queue) {
+            mTransport = transportId;
+            mQueue = queue;
+        }
+
+        @Override
+        public void run() {
+            /*
+             * 1. start up the current transport
+             * 2. for each item in the queue:
+             *      2a. bind the agent [wait for async attach]
+             *      2b. set up the files and call doBackup()
+             *      2c. unbind the agent
+             * 3. tear down the transport
+             * 4. done!
+             */
+            if (DEBUG) Log.v(TAG, "Beginning backup of " + mQueue.size() + " targets");
+
+            // stand up the current transport
+            IBackupTransport transport = null;
+            switch (mTransport) {
+            case BackupManager.TRANSPORT_ADB:
+                if (DEBUG) Log.v(TAG, "Initializing adb transport");
+                transport = new AdbTransport();
+                break;
+
+            case BackupManager.TRANSPORT_GOOGLE:
+                if (DEBUG) Log.v(TAG, "Initializing Google transport");
+                //!!! TODO: stand up the google backup transport here
+                transport = new GoogleTransport();
+                break;
+
+            default:
+                Log.e(TAG, "Perform backup with unknown transport " + mTransport);
+                // !!! TODO: re-enqueue the backup queue for later?
+                return;
+            }
+
+            try {
+                transport.startSession();
+            } catch (Exception e) {
+                Log.e(TAG, "Error starting backup session");
+                e.printStackTrace();
+                // !!! TODO: re-enqueue the backup queue for later?
+                return;
+            }
+
+            // The transport is up and running; now run all the backups in our queue
+            doQueuedBackups(transport);
+
+            // Finally, tear down the transport
+            try {
+                transport.endSession();
+            } catch (Exception e) {
+                Log.e(TAG, "Error ending transport");
+                e.printStackTrace();
+            }
+        }
+
+        private void doQueuedBackups(IBackupTransport transport) {
+            for (BackupRequest request : mQueue) {
+                Log.d(TAG, "starting agent for " + request);
+                // !!! TODO: need to handle the restore case?
+
+                IBackupAgent agent = null;
+                int mode = (request.fullBackup)
+                        ? IApplicationThread.BACKUP_MODE_FULL
+                        : IApplicationThread.BACKUP_MODE_INCREMENTAL;
+                try {
+                    synchronized(mAgentConnectLock) {
+                        mConnecting = true;
+                        mConnectedAgent = null;
+                        if (mActivityManager.bindBackupAgent(request.appInfo, mode)) {
+                            Log.d(TAG, "awaiting agent for " + request);
+
+                            // success; wait for the agent to arrive
+                            while (mConnecting && mConnectedAgent == null) {
+                                try {
+                                    mAgentConnectLock.wait(10000);
+                                } catch (InterruptedException e) {
+                                    // just retry
+                                    continue;
+                                }
+                            }
+
+                            // if we timed out with no connect, abort and move on
+                            if (mConnecting == true) {
+                                Log.w(TAG, "Timeout waiting for agent " + request);
+                                continue;
+                            }
+                            agent = mConnectedAgent;
+                        }
+                    }
+                } catch (RemoteException e) {
+                    // can't happen; activity manager is local
+                } catch (SecurityException ex) {
+                    // Try for the next one.
+                    Log.d(TAG, "error in bind", ex);
+                }
+
+                // successful bind? run the backup for this agent
+                if (agent != null) {
+                    processOneBackup(request, agent, transport);
+                }
+
+                // send the unbind even on timeout, just in case
+                try {
+                    mActivityManager.unbindBackupAgent(request.appInfo);
+                } catch (RemoteException e) {
+                    // can't happen
+                }
+            }
+        }
+    }
+
     // ----- IBackupManager binder interface -----
     
     public void dataChanged(String packageName) throws RemoteException {
@@ -432,45 +532,75 @@
                 // Schedule a backup pass in a few minutes.  As backup-eligible data
                 // keeps changing, continue to defer the backup pass until things
                 // settle down, to avoid extra overhead.
+                mBackupHandler.removeMessages(MSG_RUN_BACKUP);
                 mBackupHandler.sendEmptyMessageDelayed(MSG_RUN_BACKUP, COLLECTION_INTERVAL);
             }
         }
     }
 
-    // Schedule a backup pass for a given package, even if the caller is not part of
-    // that uid or package itself.
+    // Schedule a backup pass for a given package.  This method will schedule a
+    // full backup even for apps that do not declare an android:backupAgent, so
+    // use with care.
     public void scheduleFullBackup(String packageName) throws RemoteException {
-        // !!! TODO: protect with a signature-or-system permission?
+        mContext.enforceCallingPermission("android.permission.BACKUP", "scheduleFullBackup");
+
+        if (DEBUG) Log.v(TAG, "Scheduling immediate full backup for " + packageName);
         synchronized (mQueueLock) {
-            int numKeys = mBackupParticipants.size();
-            for (int index = 0; index < numKeys; index++) {
-                int uid = mBackupParticipants.keyAt(index);
-                HashSet<ApplicationInfo> servicesAtUid = mBackupParticipants.get(uid);
-                for (ApplicationInfo app: servicesAtUid) {
-                    if (app.packageName.equals(packageName)) {
-                        mPendingBackups.put(app, new BackupRequest(app, true));
-                    }
-                }
+            try {
+                ApplicationInfo app = mPackageManager.getApplicationInfo(packageName, 0);
+                mPendingBackups.put(app, new BackupRequest(app, true));
+                mBackupHandler.sendEmptyMessage(MSG_RUN_FULL_BACKUP);
+            } catch (NameNotFoundException e) {
+                Log.w(TAG, "Could not find app for " + packageName + " to schedule full backup");
             }
         }
     }
 
-    // Callback: a requested backup agent has been instantiated
+    // Select which transport to use for the next backup operation
+    public int selectBackupTransport(int transportId) {
+        mContext.enforceCallingPermission("android.permission.BACKUP", "selectBackupTransport");
+
+        int prevTransport = mTransportId;
+        mTransportId = transportId;
+        return prevTransport;
+    }
+
+    // Callback: a requested backup agent has been instantiated.  This should only
+    // be called from the Activity Manager.
     public void agentConnected(String packageName, IBinder agentBinder) {
-        Log.d(TAG, "agentConnected pkg=" + packageName + " agent=" + agentBinder);
-        IBackupAgent bs = IBackupAgent.Stub.asInterface(agentBinder);
-        processOneBackup(packageName, bs);
+        synchronized(mAgentConnectLock) {
+            if (Binder.getCallingUid() == Process.SYSTEM_UID) {
+                Log.d(TAG, "agentConnected pkg=" + packageName + " agent=" + agentBinder);
+                IBackupAgent agent = IBackupAgent.Stub.asInterface(agentBinder);
+                mConnectedAgent = agent;
+                mConnecting = false;
+            } else {
+                Log.w(TAG, "Non-system process uid=" + Binder.getCallingUid()
+                        + " claiming agent connected");
+            }
+            mAgentConnectLock.notifyAll();
+        }
     }
 
     // Callback: a backup agent has failed to come up, or has unexpectedly quit.
     // If the agent failed to come up in the first place, the agentBinder argument
-    // will be null.
+    // will be null.  This should only be called from the Activity Manager.
     public void agentDisconnected(String packageName) {
         // TODO: handle backup being interrupted
+        synchronized(mAgentConnectLock) {
+            if (Binder.getCallingUid() == Process.SYSTEM_UID) {
+                mConnectedAgent = null;
+                mConnecting = false;
+            } else {
+                Log.w(TAG, "Non-system process uid=" + Binder.getCallingUid()
+                        + " claiming agent disconnected");
+            }
+            mAgentConnectLock.notifyAll();
+        }
     }
-    
 
-    
+
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         synchronized (mQueueLock) {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 8da40ac..6a2e62f 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4147,6 +4147,7 @@
             return false;
         }
         synchronized (mPackages) {
+            grantPermissionsLP(newPkg, true);
             mSettings.writeLP();
         }
         return true;
diff --git a/services/java/com/android/server/ProcessStats.java b/services/java/com/android/server/ProcessStats.java
index 55adabb..58f8980 100644
--- a/services/java/com/android/server/ProcessStats.java
+++ b/services/java/com/android/server/ProcessStats.java
@@ -54,7 +54,10 @@
         PROC_SPACE_TERM|PROC_OUT_LONG                   // 14: stime
     };
 
+    /** Stores user time and system time in 100ths of a second. */
     private final long[] mProcessStatsData = new long[2];
+    /** Stores user time and system time in 100ths of a second. */
+    private final long[] mSinglePidStatsData = new long[2];
 
     private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] {
         PROC_SPACE_TERM,
@@ -418,7 +421,18 @@
         
         return pids;
     }
-    
+
+    public long getCpuTimeForPid(int pid) {
+        final String statFile = "/proc/" + pid + "/stat";
+        final long[] statsData = mSinglePidStatsData;
+        if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
+                null, statsData, null)) {
+            long time = statsData[0] + statsData[1];
+            return time;
+        }
+        return 0;
+    }
+
     final public int getLastUserTime() {
         return mRelUserTime;
     }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3b26cb7..736c0da 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -62,6 +62,7 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.net.Uri;
+import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
@@ -182,7 +183,7 @@
 
     // 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;
+            | PackageManager.GET_SUPPORTS_DENSITIES | PackageManager.GET_EXPANDABLE;
     
     private static final String SYSTEM_SECURE = "ro.secure";
 
@@ -1438,7 +1439,7 @@
         synchronized (mProcessStatsThread) {
             final long now = SystemClock.uptimeMillis();
             boolean haveNewCpuStats = false;
-            
+
             if (MONITOR_CPU_USAGE &&
                     mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
                 mLastCpuTime = now;
@@ -2063,6 +2064,25 @@
         if (prev != null) {
             prev.resumeKeyDispatchingLocked();
         }
+
+        if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
+            long diff = 0;
+            synchronized (mProcessStatsThread) {
+                diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
+            }
+            if (diff > 0) {
+                BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
+                synchronized (bsi) {
+                    BatteryStatsImpl.Uid.Proc ps =
+                            bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
+                            prev.info.packageName);
+                    if (ps != null) {
+                        ps.addForegroundTimeLocked(diff);
+                    }
+                }
+            }
+        }
+        prev.cpuTimeAtResume = 0; // reset it
     }
 
     /**
@@ -2095,6 +2115,17 @@
         next.resumeKeyDispatchingLocked();
         ensureActivitiesVisibleLocked(null, 0);
         mWindowManager.executeAppTransition();
+
+        // Mark the point when the activity is resuming
+        // TODO: To be more accurate, the mark should be before the onCreate,
+        //       not after the onResume. But for subsequent starts, onResume is fine.
+        if (next.app != null) {
+            synchronized (mProcessStatsThread) {
+                next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
+            }
+        } else {
+            next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
+        }
     }
 
     /**
@@ -10346,6 +10377,7 @@
                 return;
             }
 
+            long oldIdent = Binder.clearCallingIdentity();
             try {
                 IBackupManager bm = IBackupManager.Stub.asInterface(
                         ServiceManager.getService(Context.BACKUP_SERVICE));
@@ -10355,6 +10387,8 @@
             } catch (Exception e) {
                 Log.w(TAG, "Exception trying to deliver BackupAgent binding: ");
                 e.printStackTrace();
+            } finally {
+                Binder.restoreCallingIdentity(oldIdent);
             }
         }
     }
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index 1789687..944ea02 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -66,6 +66,7 @@
     int theme;              // resource identifier of activity's theme.
     TaskRecord task;        // the task this is in.
     long startTime;         // when we starting launching this activity
+    long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
     Configuration configuration; // configuration activity was last running in
     HistoryRecord resultTo; // who started this entry, so will get our reply
     final String resultWho; // additional identifier for use by resultTo.
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 77755ce..af79404 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -93,6 +93,7 @@
     protected static final int EVENT_NV_READY = 31;
     protected static final int EVENT_PS_RESTRICT_ENABLED = 32;
     protected static final int EVENT_PS_RESTRICT_DISABLED = 33;
+    public static final int EVENT_CLEAN_UP_CONNECTION = 34;
 
     //***** Constants
     protected static final int RECONNECT_DELAY_INITIAL_MILLIS = 5 * 1000;
@@ -149,7 +150,7 @@
 
     /** Intent sent when the reconnect alarm fires. */
     protected PendingIntent mReconnectIntent = null;
-    
+
     /** CID of active data connection */
     protected int cidActive;
 
@@ -226,6 +227,7 @@
     protected abstract void onDisconnectDone(AsyncResult ar);
     protected abstract void onVoiceCallStarted();
     protected abstract void onVoiceCallEnded();
+    protected abstract void onCleanUpConnection(boolean tearDown, String reason);
 
   //***** Overridden from Handler
     public void handleMessage (Message msg) {
@@ -272,6 +274,11 @@
                 onVoiceCallEnded();
                 break;
 
+            case EVENT_CLEAN_UP_CONNECTION:
+                boolean tearDown = (msg.arg1 == 0) ? false : true;
+                onCleanUpConnection(tearDown, (String)msg.obj);
+                break;
+
             default:
                 Log.e("DATA", "Unidentified event = " + msg.what);
                 break;
@@ -279,12 +286,6 @@
     }
 
     /**
-     * Simply tear down data connections due to radio off 
-     * and don't setup again.
-     */
-    public abstract void cleanConnectionBeforeRadioOff();
-
-    /**
      * Report the current state of data connectivity (enabled or disabled)
      * @return {@code false} if data connectivity has been explicitly disabled,
      * {@code true} otherwise.
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 260f662..a6b0480 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -229,7 +229,7 @@
     /**
      * Get the current DataState. No change notification exists at this
      * interface -- use
-     * {@link com.android.internal.telephony.PhoneStateIntentReceiver PhoneStateIntentReceiver}
+     * {@link com.android.telephony.PhoneStateListener PhoneStateListener}
      * instead.
      */
     DataState getDataConnectionState();
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 7ba9951..0ebe507 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -38,6 +38,7 @@
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_INECM_MODE;
 
 import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.DataConnection;
@@ -525,8 +526,20 @@
 
     public void
     getNeighboringCids(Message response) {
-        // WINK:TODO: implement after Cupcake merge
-        mCM.getNeighboringCids(response); // workaround.
+        /*
+         * This is currently not implemented.  At least as of June
+         * 2009, there is no neighbor cell information available for
+         * CDMA because some party is resisting making this
+         * information readily available.  Consequently, calling this
+         * function can have no useful effect.  This situation may
+         * (and hopefully will) change in the future.
+         */
+        if (response != null) {
+            CommandException ce = new CommandException(
+                    CommandException.Error.REQUEST_NOT_SUPPORTED);
+            AsyncResult.forMessage(response).exception = ce;
+            response.sendToTarget();
+        }
     }
 
     public DataState getDataConnectionState() {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index b92e9e4..900480f 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -263,14 +263,6 @@
     }
 
     /**
-     * Simply tear down data connections due to radio off
-     * and don't setup again.
-     */
-    public void cleanConnectionBeforeRadioOff() {
-        cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
-    }
-
-    /**
      * The data connection is expected to be setup while device
      *  1. has ruim card or non-volatile data store
      *  2. registered to data connection service
@@ -821,6 +813,13 @@
         }
     }
 
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onCleanUpConnection(boolean tearDown, String reason) {
+        cleanUpConnection(tearDown, reason);
+    }
+
     private boolean tryAgain(FailCause cause) {
         return (cause != FailCause.RADIO_NOT_AVAILABLE)
             && (cause != FailCause.RADIO_OFF)
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index a9c810d..12ceeaf 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -449,7 +449,10 @@
                         (dcTracker.getAnyDataEnabled() ? 1 : 0) );
                 EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val);
             }
-            dcTracker.cleanConnectionBeforeRadioOff();
+            Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
+            msg.arg1 = 1; // tearDown is true
+            msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF;
+            sendMessage(msg);
 
             // Poll data state up to 15 times, with a 100ms delay
             // totaling 1.5 sec. Normal data disable action will finish in 100ms.
@@ -679,7 +682,7 @@
                         newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
                 } else {
                     // System is acquired, prl match, no nam match  or mRoamingIndicator > 2
-                    newSS.setCdmaRoamingIndicator(mRoamingIndicator);                    
+                    newSS.setCdmaRoamingIndicator(mRoamingIndicator);
                 }
             } else {
                 if (mRegistrationState == 5) {
@@ -688,8 +691,8 @@
                 } else {
                     // Use the default indicator
                 }
-            }            
-            
+            }
+
             newSS.setCdmaDefaultRoamingIndicator(mDefaultRoamingIndicator);
 
             // NOTE: Some operator may require to override the mCdmaRoaming (set by the modem)
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 6e4a495..3f43502 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -28,10 +28,9 @@
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.NetworkInfo;
-import android.net.wifi.WifiManager;
 import android.net.Uri;
+import android.net.wifi.WifiManager;
 import android.os.AsyncResult;
-import android.os.Handler;
 import android.os.INetStatService;
 import android.os.Message;
 import android.os.RemoteException;
@@ -42,7 +41,6 @@
 import android.provider.Checkin;
 import android.provider.Settings;
 import android.provider.Telephony;
-import android.provider.Settings.SettingNotFoundException;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.telephony.gsm.GsmCellLocation;
@@ -52,11 +50,10 @@
 
 import com.android.internal.telephony.DataCallState;
 import com.android.internal.telephony.DataConnection;
-import com.android.internal.telephony.DataConnection.FailCause;
 import com.android.internal.telephony.DataConnectionTracker;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.TelephonyEventLog;
+import com.android.internal.telephony.DataConnection.FailCause;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -177,9 +174,12 @@
 
                 String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
                 if (state == State.FAILED) {
-                    cleanUpConnection(false, reason);
+                    Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
+                    msg.arg1 = 0; // tearDown is false
+                    msg.obj = (String) reason;
+                    sendMessage(msg);
                 }
-                trySetupData(reason);
+                sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
             } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                 final android.net.NetworkInfo networkInfo = (NetworkInfo)
                         intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
@@ -260,7 +260,7 @@
         ((GSMPhone) phone).mSST.unregisterForRoamingOff(this);
         ((GSMPhone) phone).mSST.unregisterForPsRestrictedEnabled(this);
         ((GSMPhone) phone).mSST.unregisterForPsRestrictedDisabled(this);
-        
+
         phone.getContext().unregisterReceiver(this.mIntentReceiver);
         phone.getContext().getContentResolver().unregisterContentObserver(this.apnObserver);
 
@@ -362,7 +362,7 @@
      * The APN of the specified type is no longer needed. Ensure that if
      * use of the default APN has not been explicitly disabled, we are connected
      * to the default APN.
-     * @param type the APN type. The only valid values are currently 
+     * @param type the APN type. The only valid values are currently
      * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
      * @return
      */
@@ -410,7 +410,7 @@
         if (((GSMPhone) phone).mSIMRecords.getRecordsLoaded() &&
                 ((GSMPhone) phone).mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
                 (!roaming || getDataOnRoamingEnabled()) &&
-            !mIsWifiConnected && 
+            !mIsWifiConnected &&
             !mIsPsRestricted ) {
             return (state == State.CONNECTED);
         }
@@ -494,14 +494,6 @@
             return true;
         }
     }
-    
-    /**
-     * Simply tear down data connections due to radio off 
-     * and don't setup again.
-     */
-    public void cleanConnectionBeforeRadioOff() {
-        cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
-    }
 
     /**
      * Report the current state of data connectivity (enabled or disabled) for
@@ -566,7 +558,7 @@
         if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
 
         Log.d(LOG_TAG, "[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
-        
+
         if (phone.getSimulatedRadioControl() != null) {
             // Assume data is connected on the simulator
             // FIXME  this can be improved
@@ -664,7 +656,7 @@
          * IDLE before the code below runs. If we didn't check
          * for that, future calls to trySetupData would fail,
          * and we would never get out of the DISCONNECTING state.
-         */ 
+         */
         if (!tearDown) {
             setState(State.IDLE);
             phone.notifyDataConnection(reason);
@@ -1061,7 +1053,7 @@
             }
 
             int watchdogTrigger = Settings.Gservices.getInt(mResolver,
-                    Settings.Gservices.PDP_WATCHDOG_TRIGGER_PACKET_COUNT, 
+                    Settings.Gservices.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
                     NUMBER_SENT_PACKETS_OF_HANG);
 
             if (sentSinceLastRecv >= watchdogTrigger) {
@@ -1084,7 +1076,7 @@
 
                     // Slow down the poll interval to let things happen
                     netStatPollPeriod = Settings.Gservices.getInt(mResolver,
-                            Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS, 
+                            Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
                             POLL_NETSTAT_SLOW_MILLIS);
                 } else {
                     if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
@@ -1117,7 +1109,7 @@
             }
         }
     };
-    
+
     private void runPingTest () {
         int status = -1;
         try {
@@ -1166,19 +1158,19 @@
     /**
      * Return true if data connection need to be setup after disconnected due to
      * reason.
-     * 
+     *
      * @param reason the reason why data is disconnected
-     * @return true if try setup data connection is need for this reason 
+     * @return true if try setup data connection is need for this reason
      */
     private boolean retryAfterDisconnected(String reason) {
         boolean retry = true;
-        
+
         if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ||
-             Phone.REASON_DATA_DISABLED.equals(reason) ) { 
+             Phone.REASON_DATA_DISABLED.equals(reason) ) {
             retry = false;
         }
         return retry;
-    }   
+    }
 
     private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
         if (state == State.FAILED) {
@@ -1331,7 +1323,7 @@
             cause = (PdpConnection.FailCause) (ar.result);
             if(DBG) log("PDP setup failed " + cause);
                     // Log this failure to the Event Logs.
-            if (cause == PdpConnection.FailCause.BAD_APN || 
+            if (cause == PdpConnection.FailCause.BAD_APN ||
                     cause == PdpConnection.FailCause.BAD_PAP_SECRET ||
                     cause == PdpConnection.FailCause.BARRED ||
                     cause == PdpConnection.FailCause.RADIO_ERROR_RETRY ||
@@ -1343,7 +1335,7 @@
                 if (loc != null) cid = loc.getCid();
 
                 EventLog.List val = new EventLog.List(
-                        cause.ordinal(), cid, 
+                        cause.ordinal(), cid,
                         TelephonyManager.getDefault().getNetworkType());
                 EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_PDP_SETUP_FAIL, val);
             }
@@ -1416,6 +1408,10 @@
         }
     }
 
+    protected void onCleanUpConnection(boolean tearDown, String reason) {
+        cleanUpConnection(tearDown, reason);
+    }
+
     private boolean tryNextApn(FailCause cause) {
         return (cause != FailCause.RADIO_NOT_AVAILABLE)
                 && (cause != FailCause.RADIO_OFF)
@@ -1576,7 +1572,7 @@
         ContentResolver resolver = phone.getContext().getContentResolver();
         resolver.delete(PREFERAPN_URI, null, null);
 
-        if (pos >= 0) {            
+        if (pos >= 0) {
             ContentValues values = new ContentValues();
             values.put(APN_ID, pos);
             resolver.insert(PREFERAPN_URI, values);
@@ -1589,7 +1585,7 @@
         }
 
         Cursor cursor = phone.getContext().getContentResolver().query(
-                PREFERAPN_URI, new String[] { "_id", "name", "apn" }, 
+                PREFERAPN_URI, new String[] { "_id", "name", "apn" },
                 null, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
 
         if (cursor != null) {
@@ -1673,9 +1669,9 @@
                  * PDP context and notify us with PDP_CONTEXT_CHANGED.
                  * But we should stop the network polling and prevent reset PDP.
                  */
-                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted); 
+                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
                 stopNetStatPoll();
-                mIsPsRestricted = true; 
+                mIsPsRestricted = true;
                 break;
 
             case EVENT_PS_RESTRICT_DISABLED:
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 63b6a5e..066f782 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -16,7 +16,13 @@
 
 package com.android.internal.telephony.gsm;
 
-import com.android.internal.telephony.Phone;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -50,21 +56,11 @@
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.DataConnectionTracker;
 import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyEventLog;
 import com.android.internal.telephony.TelephonyIntents;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
-
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
@@ -541,7 +537,10 @@
                         (dcTracker.getAnyDataEnabled() ? 1 : 0) );
                 EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val);
             }
-            dcTracker.cleanConnectionBeforeRadioOff();
+            Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
+            msg.arg1 = 1; // tearDown is true
+            msg.obj = GSMPhone.REASON_RADIO_TURNED_OFF;
+            sendMessage(msg);
 
             // poll data state up to 15 times, with a 100ms delay
             // totaling 1.5 sec. Normal data disable action will finish in 100ms.
diff --git a/test-runner/android/test/mock/MockContext.java b/test-runner/android/test/mock/MockContext.java
index bd39a14..e733dd1 100644
--- a/test-runner/android/test/mock/MockContext.java
+++ b/test-runner/android/test/mock/MockContext.java
@@ -386,12 +386,4 @@
             throws PackageManager.NameNotFoundException {
         throw new UnsupportedOperationException();
     }
-
-    /**
-     * @hide
-     */
-    @Override
-    public float getApplicationScale() {
-        throw new UnsupportedOperationException();
-    }
 }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java b/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java
index bdf67ba..6b56e6c 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
@@ -306,6 +307,14 @@
                 throws PackageManager.NameNotFoundException {
             return mRealContext.createPackageContext(packageName, flags);
         }
+
+        /**
+         * Message broadcast.  Pass through for now.
+         */
+        @Override
+        public void sendBroadcast(Intent intent) {
+            mRealContext.sendBroadcast(intent);
+        }
     }
 
 /**
@@ -361,7 +370,8 @@
         @Override 
         public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
             assertNotNull(intent);
-            assertEquals(intent.getAction(), Intent.ACTION_SEARCH);
+            assertTrue(intent.getAction().equals(Intent.ACTION_SEARCH)
+                    || intent.getAction().equals(Intent.ACTION_WEB_SEARCH));
             switch (mSearchablesMode) {
             case SEARCHABLES_PASSTHROUGH:
                 return mRealPackageManager.queryIntentActivities(intent, flags);
@@ -375,7 +385,8 @@
         @Override
         public ResolveInfo resolveActivity(Intent intent, int flags) {
             assertNotNull(intent);
-            assertEquals(intent.getAction(), SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
+            assertTrue(intent.getAction().equals(Intent.ACTION_WEB_SEARCH)
+                    || intent.getAction().equals(SearchManager.INTENT_ACTION_GLOBAL_SEARCH));
             switch (mSearchablesMode) {
             case SEARCHABLES_PASSTHROUGH:
                 return mRealPackageManager.resolveActivity(intent, flags);
@@ -438,6 +449,29 @@
                 throw new UnsupportedOperationException();
             }
         }
+
+        /**
+         * Get the activity information for a particular activity.
+         *
+         * @param name The name of the activity to find.
+         * @param flags Additional option flags.
+         *
+         * @return ActivityInfo Information about the activity, if found, else null.
+         */
+        @Override
+        public ActivityInfo getActivityInfo(ComponentName name, int flags)
+                throws NameNotFoundException {
+            assertNotNull(name);
+            MoreAsserts.assertNotEqual(name, "");
+            switch (mSearchablesMode) {
+            case SEARCHABLES_PASSTHROUGH:
+                return mRealPackageManager.getActivityInfo(name, flags);
+            case SEARCHABLES_MOCK_ZERO:
+                throw new NameNotFoundException();
+            default:
+                throw new UnsupportedOperationException();
+            }
+        }
     }
 }
 
diff --git a/tests/DumpRenderTree/assets/run_reliability_tests.py b/tests/DumpRenderTree/assets/run_reliability_tests.py
index 6aab009..076c508 100755
--- a/tests/DumpRenderTree/assets/run_reliability_tests.py
+++ b/tests/DumpRenderTree/assets/run_reliability_tests.py
@@ -10,8 +10,10 @@
 
 import logging
 import optparse
+import os
 import subprocess
 import sys
+import time
 
 TEST_LIST_FILE = "/sdcard/android/reliability_tests_list.txt"
 TEST_STATUS_FILE = "/sdcard/android/reliability_running_test.txt"
@@ -46,6 +48,20 @@
                    stderr=subprocess.PIPE).communicate()
 
 
+def Bugreport(url, bugreport_dir, adb_cmd):
+  """Pull a bugreport from the device."""
+  bugreport_filename = "%s/reliability_bugreport_%d.txt" % (bugreport_dir,
+                                                            int(time.time()))
+
+  # prepend the report with url
+  handle = open(bugreport_filename, "w")
+  handle.writelines("Bugreport for crash in url - %s\n\n" % url)
+  handle.close()
+
+  cmd = "%s bugreport >> %s" % (adb_cmd, bugreport_filename)
+  os.system(cmd)
+
+
 def main(options, args):
   """Send the url list to device and start testing, restart if crashed."""
 
@@ -80,6 +96,16 @@
   else:
     manual_delay = options.delay
 
+  if not options.bugreport:
+    bugreport_dir = "."
+  else:
+    bugreport_dir = options.bugreport
+  if not os.path.exists(bugreport_dir):
+    os.makedirs(bugreport_dir)
+  if not os.path.isdir(bugreport_dir):
+    logging.error("Cannot create results dir: " + bugreport_dir)
+    sys.exit(1)
+
   adb_cmd = "adb "
   if options.adb_options:
     adb_cmd += options.adb_options + " "
@@ -128,6 +154,7 @@
                                     stdout=subprocess.PIPE).communicate()[0]
     logging.info(crashed_test + " CRASHED")
     crashed_tests.append(crashed_test)
+    Bugreport(crashed_test, bugreport_dir, adb_cmd)
     logging.info("Resuming reliability test runner...")
 
     adb_output = subprocess.Popen(test_cmd, shell=True, stdout=subprocess.PIPE,
@@ -172,9 +199,12 @@
                            help="the list of sites that cause browser to crash")
   option_parser.add_option("-f", "--timeout-file",
                            default="reliability_timedout_sites.txt",
-                           help="the list of sites that timedout during test.")
+                           help="the list of sites that timedout during test")
   option_parser.add_option("-d", "--delay",
                            default=0,
                            help="add a manual delay between pages (in ms)")
+  option_parser.add_option("-b", "--bugreport",
+                           default=".",
+                           help="the directory to store bugreport for crashes")
   opts, arguments = option_parser.parse_args()
   main(opts, arguments)
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
index e63aa95..22c458c 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
@@ -55,6 +55,9 @@
         //read from BufferedReader instead of populating a list in advance,
         //this will avoid excessive memory usage in case of a large list
         while((url = listReader.readLine()) != null) {
+            url = url.trim();
+            if(url.length() == 0)
+                continue;
             start = System.currentTimeMillis();
             Log.v(LOGTAG, "Testing URL: " + url);
             updateTestStatus(url);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
index a374a41..cbec104 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
@@ -215,6 +215,12 @@
         }
         
         @Override
+        public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
+            result.confirm();
+            return true;
+        }
+
+        @Override
         public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
                 JsPromptResult result) {
             result.confirm();
diff --git a/tests/backup/backup_helper_test.cpp b/tests/backup/backup_helper_test.cpp
index 1085909..f087941 100644
--- a/tests/backup/backup_helper_test.cpp
+++ b/tests/backup/backup_helper_test.cpp
@@ -1,4 +1,20 @@
-#include <utils/backup_helpers.h>
+/*
+ * 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.
+ */
+
+#include <utils/BackupHelpers.h>
 
 #include <stdio.h>
 #include <string.h>
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix.java b/tools/layoutlib/bridge/src/android/graphics/Matrix.java
index 3f9a993..18c0e17 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix.java
@@ -24,8 +24,8 @@
  */
 public class Matrix extends _Original_Matrix {
 
-    float mValues[] = new float[9]; 
-    
+    float mValues[] = new float[9];
+
     /**
      * Create an identity matrix
      */
@@ -40,7 +40,7 @@
     public Matrix(Matrix src) {
         set(src);
     }
-    
+
     /**
      * Creates a Matrix object from the float array. The array becomes the internal storage
      * of the object.
@@ -50,14 +50,14 @@
         assert data.length != 9;
         mValues = data;
     }
-    
+
     @Override
     public void finalize() throws Throwable {
         // pass
     }
-    
+
     //---------- Custom Methods
-    
+
     /**
      * Adds the given transformation to the current Matrix
      * <p/>This in effect does this = this*matrix
@@ -65,17 +65,17 @@
      */
     private void addTransform(float[] matrix) {
         float[] tmp = new float[9];
-        
-        // first row 
+
+        // first row
         tmp[0] = matrix[0] * mValues[0] + matrix[1] * mValues[3] + matrix[2] * mValues[6];
         tmp[1] = matrix[0] * mValues[1] + matrix[1] * mValues[4] + matrix[2] * mValues[7];
         tmp[2] = matrix[0] * mValues[2] + matrix[1] * mValues[5] + matrix[2] * mValues[8];
-        
+
         // 2nd row
         tmp[3] = matrix[3] * mValues[0] + matrix[4] * mValues[3] + matrix[5] * mValues[6];
         tmp[4] = matrix[3] * mValues[1] + matrix[4] * mValues[4] + matrix[5] * mValues[7];
         tmp[5] = matrix[3] * mValues[2] + matrix[4] * mValues[5] + matrix[5] * mValues[8];
-        
+
         // 3rd row
         tmp[6] = matrix[6] * mValues[0] + matrix[7] * mValues[3] + matrix[8] * mValues[6];
         tmp[7] = matrix[6] * mValues[1] + matrix[7] * mValues[4] + matrix[8] * mValues[7];
@@ -84,16 +84,16 @@
         // copy the result over to mValues
         mValues = tmp;
     }
-    
+
     public AffineTransform getTransform() {
         return new AffineTransform(mValues[0], mValues[1], mValues[2],
                 mValues[3], mValues[4], mValues[5]);
     }
-    
+
     public boolean hasPerspective() {
         return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
     }
-    
+
     //----------
 
     /**
@@ -109,7 +109,7 @@
                 }
             }
         }
-        
+
         return true;
     }
 
@@ -122,7 +122,7 @@
     public boolean rectStaysRect() {
         return (computeTypeMask() & kRectStaysRect_Mask) != 0;
     }
-    
+
     /**
      * (deep) copy the src matrix into this matrix. If src is null, reset this
      * matrix to the identity matrix.
@@ -151,10 +151,10 @@
                     return false;
                 }
             }
-            
+
             return true;
         }
-        
+
         return false;
     }
 
@@ -179,7 +179,7 @@
         mValues[5] = dy;
         mValues[6] = 0;
         mValues[7] = 0;
-        mValues[7] = 1;
+        mValues[8] = 1;
     }
 
     /**
@@ -200,7 +200,7 @@
         mValues[5] = -py;
         mValues[6] = 0;
         mValues[7] = 0;
-        mValues[7] = 1;
+        mValues[8] = 1;
 
         // scale
         addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 });
@@ -219,7 +219,7 @@
         mValues[5] = 0;
         mValues[6] = 0;
         mValues[7] = 0;
-        mValues[7] = 1;
+        mValues[8] = 1;
     }
 
     /**
@@ -240,13 +240,13 @@
         mValues[5] = -py;
         mValues[6] = 0;
         mValues[7] = 0;
-        mValues[7] = 1;
+        mValues[8] = 1;
 
         // scale
         double rad = Math.toRadians(degrees);
         float cos = (float)Math.cos(rad);
         float sin = (float)Math.sin(rad);
-        addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 }); 
+        addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 });
         // translate back the pivot
         addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
     }
@@ -268,7 +268,7 @@
         mValues[5] = 0;
         mValues[6] = 0;
         mValues[7] = 0;
-        mValues[7] = 1;
+        mValues[8] = 1;
     }
 
     /**
@@ -289,10 +289,10 @@
         mValues[5] = -py;
         mValues[6] = 0;
         mValues[7] = 0;
-        mValues[7] = 1;
+        mValues[8] = 1;
 
         // scale
-        addTransform(new float[] { cosValue, -sinValue, 0, sinValue, cosValue, 0, 0, 0, 1 }); 
+        addTransform(new float[] { cosValue, -sinValue, 0, sinValue, cosValue, 0, 0, 0, 1 });
         // translate back the pivot
         addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
     }
@@ -308,7 +308,7 @@
         mValues[5] = 0;
         mValues[6] = 0;
         mValues[7] = 0;
-        mValues[7] = 1;
+        mValues[8] = 1;
     }
 
     /**
@@ -329,7 +329,7 @@
         mValues[5] = -py;
         mValues[6] = 0;
         mValues[7] = 0;
-        mValues[7] = 1;
+        mValues[8] = 1;
 
         // scale
         addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
@@ -348,7 +348,7 @@
         mValues[5] = 0;
         mValues[6] = 0;
         mValues[7] = 0;
-        mValues[7] = 1;
+        mValues[8] = 1;
     }
 
     /**
@@ -366,10 +366,10 @@
             tmp.addTransform(a.mValues);
             set(tmp);
         }
-        
+
         return true;
     }
-    
+
     @Override
     public boolean setConcat(_Original_Matrix a, _Original_Matrix b) {
         throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
@@ -384,7 +384,7 @@
         // create a matrix that will be multiply by this
         Matrix m = new Matrix(new float[] { 1, 0, dx, 0, 1, dy, 0, 0, 1 });
         m.addTransform(this.mValues);
-        
+
         System.arraycopy(m.mValues, 0, mValues, 0, 9);
         return true;
     }
@@ -399,7 +399,7 @@
         m.setScale(sx, sy, px, py);
         m.addTransform(mValues);
         set(m);
-        
+
         return true;
     }
 
@@ -413,7 +413,7 @@
         m.setScale(sx, sy);
         m.addTransform(mValues);
         set(m);
-        
+
         return true;
     }
 
@@ -427,7 +427,7 @@
         m.setRotate(degrees, px, py);
         m.addTransform(mValues);
         set(m);
-        
+
         return true;
     }
 
@@ -441,7 +441,7 @@
         m.setRotate(degrees);
         m.addTransform(mValues);
         set(m);
-        
+
         return true;
     }
 
@@ -455,7 +455,7 @@
         m.setSkew(kx, ky, px, py);
         m.addTransform(mValues);
         set(m);
-        
+
         return true;
     }
 
@@ -469,7 +469,7 @@
         m.setSkew(kx, ky);
         m.addTransform(mValues);
         set(m);
-        
+
         return true;
     }
 
@@ -481,10 +481,10 @@
         Matrix m = new Matrix(other);
         other.addTransform(mValues);
         set(m);
-        
+
         return true;
     }
-    
+
     @Override
     public boolean preConcat(_Original_Matrix other) {
         throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
@@ -513,7 +513,7 @@
         addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 });
         // translate back the pivot
         addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-        
+
         return true;
     }
 
@@ -540,10 +540,10 @@
         double rad = Math.toRadians(degrees);
         float cos = (float)Math.cos(rad);
         float sin = (float)Math.sin(rad);
-        addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 }); 
+        addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 });
         // translate back the pivot
         addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-        
+
         return true;
     }
 
@@ -557,7 +557,7 @@
         float cos = (float)Math.cos(rad);
         float sin = (float)Math.sin(rad);
         addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 });
-        
+
         return true;
     }
 
@@ -574,7 +574,7 @@
         addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
         // translate back the pivot
         addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-        
+
         return true;
     }
 
@@ -585,7 +585,7 @@
     @Override
     public boolean postSkew(float kx, float ky) {
         addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
-        
+
         return true;
     }
 
@@ -595,7 +595,7 @@
      */
     public boolean postConcat(Matrix other) {
         addTransform(other.mValues);
-        
+
         return true;
     }
 
@@ -603,7 +603,7 @@
     public boolean postConcat(_Original_Matrix other) {
         throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
     }
-    
+
     /** Controlls how the src rect should align into the dst rect for
         setRectToRect().
     */
@@ -634,7 +634,7 @@
          */
         END     (3);
 
-        // the native values must match those in SkMatrix.h 
+        // the native values must match those in SkMatrix.h
         ScaleToFit(int nativeInt) {
             this.nativeInt = nativeInt;
         }
@@ -655,7 +655,7 @@
         if (dst == null || src == null) {
             throw new NullPointerException();
         }
-        
+
         if (src.isEmpty()) {
             reset();
             return false;
@@ -689,7 +689,7 @@
                 } else {
                     diff = dst.height() - src.height() * sy;
                 }
-                
+
                 if (stf == ScaleToFit.CENTER) {
                     diff = diff / 2;
                 }
@@ -712,12 +712,12 @@
         mValues[8] = 1;
         return true;
     }
-    
+
     @Override
     public boolean setRectToRect(RectF src, RectF dst, _Original_Matrix.ScaleToFit stf) {
         throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
     }
-    
+
     /**
      * Set the matrix such that the specified src points would map to the
      * specified dst points. The "points" are represented as an array of floats,
@@ -749,7 +749,7 @@
     public boolean invert(Matrix inverse) {
         throw new UnsupportedOperationException("STUB NEEDED");
     }
-    
+
     @Override
     public boolean invert(_Original_Matrix inverse) {
         throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
@@ -772,7 +772,7 @@
         checkPointArrays(src, srcIndex, dst, dstIndex, pointCount);
         throw new UnsupportedOperationException("STUB NEEDED");
     }
-    
+
     /**
     * Apply this matrix to the array of 2D vectors specified by src, and write
      * the transformed vectors into the array of vectors specified by dst. The
@@ -790,7 +790,7 @@
         checkPointArrays(src, srcIndex, dst, dstIndex, vectorCount);
         throw new UnsupportedOperationException("STUB NEEDED");
     }
-    
+
     /**
      * Apply this matrix to the array of 2D points specified by src, and write
      * the transformed points into the array of points specified by dst. The
@@ -883,7 +883,7 @@
     public float mapRadius(float radius) {
         throw new UnsupportedOperationException("STUB NEEDED");
     }
-    
+
     /** Copy 9 values from the matrix into the array.
     */
     @Override
@@ -907,7 +907,7 @@
         }
         System.arraycopy(values, 0, mValues, 0, mValues.length);
     }
-    
+
     @SuppressWarnings("unused")
     private final static int kIdentity_Mask      = 0;
     private final static int kTranslate_Mask     = 0x01;  //!< set if the matrix has translation
@@ -917,7 +917,7 @@
     private final static int kRectStaysRect_Mask = 0x10;
     @SuppressWarnings("unused")
     private final static int kUnknown_Mask       = 0x80;
-    
+
     @SuppressWarnings("unused")
     private final static int kAllMasks           = kTranslate_Mask |
                                                      kScale_Mask |
@@ -942,43 +942,43 @@
         if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
             mask |= kPerspective_Mask;
         }
-        
+
         if (mValues[2] != 0. || mValues[5] != 0.) {
             mask |= kTranslate_Mask;
         }
-    
+
         float m00 = mValues[0];
         float m01 = mValues[1];
         float m10 = mValues[3];
         float m11 = mValues[4];
-        
+
         if (m01 != 0. || m10 != 0.) {
             mask |= kAffine_Mask;
         }
-    
+
         if (m00 != 1. || m11 != 1.) {
             mask |= kScale_Mask;
         }
-        
+
         if ((mask & kPerspective_Mask) == 0) {
             // map non-zero to 1
             int im00 = m00 != 0 ? 1 : 0;
             int im01 = m01 != 0 ? 1 : 0;
             int im10 = m10 != 0 ? 1 : 0;
             int im11 = m11 != 0 ? 1 : 0;
-            
+
             // record if the (p)rimary and (s)econdary diagonals are all 0 or
             // all non-zero (answer is 0 or 1)
             int dp0 = (im00 | im11) ^ 1;  // true if both are 0
             int dp1 = im00 & im11;        // true if both are 1
             int ds0 = (im01 | im10) ^ 1;  // true if both are 0
             int ds1 = im01 & im10;        // true if both are 1
-            
+
             // return 1 if primary is 1 and secondary is 0 or
             // primary is 0 and secondary is 1
             mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
         }
-    
+
         return mask;
     }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
index f434e14..baa3d53 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
@@ -1145,12 +1145,4 @@
     public Context getApplicationContext() {
         throw new UnsupportedOperationException();
     }
-
-    /**
-     * @hide
-     */
-    @Override
-    public float getApplicationScale() {
-        throw new UnsupportedOperationException();
-    }
 }
diff --git a/tools/localize/Android.mk b/tools/localize/Android.mk
index 186177f5..ab79f8d 100644
--- a/tools/localize/Android.mk
+++ b/tools/localize/Android.mk
@@ -53,4 +53,3 @@
 endif
 
 include $(BUILD_HOST_EXECUTABLE)
-
diff --git a/tools/localize/file_utils.cpp b/tools/localize/file_utils.cpp
index bb82a9c..8792b9e 100644
--- a/tools/localize/file_utils.cpp
+++ b/tools/localize/file_utils.cpp
@@ -3,12 +3,46 @@
 #include <unistd.h>
 #include "file_utils.h"
 #include "Perforce.h"
+#include <utils/String8.h>
 #include <sys/fcntl.h>
 #include <sys/stat.h>
 #include <errno.h>
-#include <host/Directories.h>
 #include "log.h"
 
+using namespace android;
+using namespace std;
+
+static string
+parent_dir(const string& path)
+{
+    return string(String8(path.c_str()).getPathDir().string());
+}
+
+static int
+mkdirs(const char* last)
+{
+    String8 dest;
+    const char* s = last-1;
+    int err;
+    do {
+        s++;
+        if (s > last && (*s == '.' || *s == 0)) {
+            String8 part(last, s-last);
+            dest.appendPath(part);
+#ifdef HAVE_MS_C_RUNTIME
+            err = _mkdir(dest.string());
+#else                    
+            err = mkdir(dest.string(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP);
+#endif                    
+            if (err != 0) {
+                return err;
+            }
+            last = s+1;
+        }
+    } while (*s);
+    return 0;
+}
+
 string
 translated_file_name(const string& file, const string& locale)
 {