Merge "Don't allow connection to profiles in TURNING_OFF state." into froyo
diff --git a/Android.mk b/Android.mk
index 5a4c547..cecc26a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -381,6 +381,8 @@
 		-hdf android.hasSamples 1 \
 		-samplecode $(sample_dir)/ApiDemos \
 		            resources/samples/ApiDemos "API Demos" \
+		-samplecode $(sample_dir)/BackupRestore \
+		            resources/samples/BackupRestore "Backup and Restore" \
 		-samplecode $(sample_dir)/BluetoothChat \
 		            resources/samples/BluetoothChat "Bluetooth Chat" \
 		-samplecode $(sample_dir)/BusinessCard \
diff --git a/api/current.xml b/api/current.xml
index 692cb16..21b75eb 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -71656,7 +71656,7 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
-<method name="setZoomCallback"
+<method name="setZoomChangeListener"
  return="void"
  abstract="false"
  native="false"
@@ -71666,7 +71666,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="cb" type="android.hardware.Camera.ZoomCallback">
+<parameter name="listener" type="android.hardware.Camera.OnZoomChangeListener">
 </parameter>
 </method>
 <method name="startPreview"
@@ -71831,6 +71831,31 @@
 </parameter>
 </method>
 </interface>
+<interface name="Camera.OnZoomChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onZoomChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="zoomValue" type="int">
+</parameter>
+<parameter name="stopped" type="boolean">
+</parameter>
+<parameter name="camera" type="android.hardware.Camera">
+</parameter>
+</method>
+</interface>
 <class name="Camera.Parameters"
  extends="java.lang.Object"
  abstract="false"
@@ -73255,31 +73280,6 @@
 >
 </field>
 </class>
-<interface name="Camera.ZoomCallback"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="onZoomUpdate"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="zoomValue" type="int">
-</parameter>
-<parameter name="stopped" type="boolean">
-</parameter>
-<parameter name="camera" type="android.hardware.Camera">
-</parameter>
-</method>
-</interface>
 <class name="GeomagneticField"
  extends="java.lang.Object"
  abstract="false"
@@ -85230,7 +85230,7 @@
 </parameter>
 <parameter name="mimeTypes" type="java.lang.String[]">
 </parameter>
-<parameter name="callback" type="android.media.MediaScannerConnection.ScanResultListener">
+<parameter name="callback" type="android.media.MediaScannerConnection.OnScanCompletedListener">
 </parameter>
 </method>
 </class>
@@ -85241,7 +85241,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<implements name="android.media.MediaScannerConnection.ScanResultListener">
+<implements name="android.media.MediaScannerConnection.OnScanCompletedListener">
 </implements>
 <method name="onMediaScannerConnected"
  return="void"
@@ -85270,7 +85270,7 @@
 </parameter>
 </method>
 </interface>
-<interface name="MediaScannerConnection.ScanResultListener"
+<interface name="MediaScannerConnection.OnScanCompletedListener"
  abstract="true"
  static="true"
  final="false"
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 5612158..8263e75 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -373,7 +373,7 @@
             }
             RestoreSet[] sets = null;
             int err = mRestore.getAvailableRestoreSets(observer);
-            if (err != 0) {
+            if (err == 0) {
                 observer.waitForCompletion();
                 sets = observer.sets;
                 for (RestoreSet s : sets) {
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 659d70f..9b8b0ac 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -16,6 +16,8 @@
 
 package com.android.commands.pm;
 
+import com.android.internal.content.PackageHelper;
+
 import android.content.ComponentName;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.FeatureInfo;
@@ -33,6 +35,7 @@
 import android.net.Uri;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.provider.Settings;
 
 import java.io.File;
 import java.lang.reflect.Field;
@@ -107,6 +110,16 @@
             return;
         }
 
+        if ("setInstallLocation".equals(op)) {
+            runSetInstallLocation();
+            return;
+        }
+
+        if ("getInstallLocation".equals(op)) {
+            runGetInstallLocation();
+            return;
+        }
+
         try {
             if (args.length == 1) {
                 if (args[0].equalsIgnoreCase("-l")) {
@@ -575,6 +588,51 @@
         return Integer.toString(result);
     }
 
+    private void runSetInstallLocation() {
+        int loc;
+
+        String arg = nextArg();
+        if (arg == null) {
+            System.err.println("Error: no install location specified.");
+            showUsage();
+            return;
+        }
+        try {
+            loc = Integer.parseInt(arg);
+        } catch (NumberFormatException e) {
+            System.err.println("Error: install location has to be a number.");
+            showUsage();
+            return;
+        }
+        try {
+            if (!mPm.setInstallLocation(loc)) {
+                System.err.println("Error: install location has to be a number.");
+                showUsage();
+            }
+        } catch (RemoteException e) {
+            System.err.println(e.toString());
+            System.err.println(PM_NOT_RUNNING_ERR);
+        }
+    }
+
+    private void runGetInstallLocation() {
+        try {
+            int loc = mPm.getInstallLocation();
+            String locStr = "invalid";
+            if (loc == PackageHelper.APP_INSTALL_AUTO) {
+                locStr = "auto";
+            } else if (loc == PackageHelper.APP_INSTALL_INTERNAL) {
+                locStr = "internal";
+            } else if (loc == PackageHelper.APP_INSTALL_EXTERNAL) {
+                locStr = "external";
+            }
+            System.out.println(loc + "[" + locStr + "]");
+        } catch (RemoteException e) {
+            System.err.println(e.toString());
+            System.err.println(PM_NOT_RUNNING_ERR);
+        }
+    }
+
     private void runInstall() {
         int installFlags = 0;
         String installerPackageName = null;
@@ -832,6 +890,7 @@
         System.err.println("       pm uninstall [-k] PACKAGE");
         System.err.println("       pm enable PACKAGE_OR_COMPONENT");
         System.err.println("       pm disable PACKAGE_OR_COMPONENT");
+        System.err.println("       pm setInstallLocation [0/auto] [1/internal] [2/external]");
         System.err.println("");
         System.err.println("The list packages command prints all packages.  Options:");
         System.err.println("  -f: see their associated file.");
@@ -867,10 +926,17 @@
         System.err.println("  -k: keep the data and cache directories around.");
         System.err.println("after the package removal.");
         System.err.println("");
-        System.err.println("The mountsd command simulates mounting/unmounting sdcard.Options:");
-        System.err.println("  -m: true or false.");
-        System.err.println("");
         System.err.println("The enable and disable commands change the enabled state of");
         System.err.println("a given package or component (written as \"package/class\").");
+        System.err.println("");
+        System.err.println("The getInstallLocation command gets the current install location");
+        System.err.println("  0 [auto]: Let system decide the best location");
+        System.err.println("  1 [internal]: Install on internal device storage");
+        System.err.println("  2 [external]: Install on external media");
+        System.err.println("");
+        System.err.println("The setInstallLocation command changes the default install location");
+        System.err.println("  0 [auto]: Let system decide the best location");
+        System.err.println("  1 [internal]: Install on internal device storage");
+        System.err.println("  2 [external]: Install on external media");
     }
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index b07b690..950f34f 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1482,8 +1482,9 @@
         mPackageInfo = packageInfo;
         mResources = mPackageInfo.getResources(mainThread);
 
-        if (container != null && container.getCompatibilityInfo().applicationScale !=
-            mResources.getCompatibilityInfo().applicationScale) {
+        if (mResources != null && container != null
+                && container.getCompatibilityInfo().applicationScale !=
+                        mResources.getCompatibilityInfo().applicationScale) {
             if (DEBUG) {
                 Log.d(TAG, "loaded context has different scaling. Using container's" +
                         " compatiblity info:" + container.getDisplayMetrics());
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 1d6c125..7c2d3a0 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -24,11 +24,24 @@
 import android.os.Message;
 
 /**
- * An abstract {@link Service} that serializes the handling of the Intents passed upon service
- * start and handles them on a handler thread.
+ * IntentService is a base class for {@link Service}s that handle asynchronous
+ * requests (expressed as {@link Intent}s) on demand.  Clients send requests
+ * through {@link android.content.Context#startService(Intent)} calls; the
+ * service is started as needed, handles each Intent in turn using a worker
+ * thread, and stops itself when it runs out of work.
  *
- * <p>To use this class extend it and implement {@link #onHandleIntent}. The {@link Service} will
- * automatically be stopped when the last enqueued {@link Intent} is handled.
+ * <p>This "work queue processor" pattern is commonly used to offload tasks
+ * from an application's main thread.  The IntentService class exists to
+ * simplify this pattern and take care of the mechanics.  To use it, extend
+ * IntentService and implement {@link #onHandleIntent(Intent)}.  IntentService
+ * will receive the Intents, launch a worker thread, and stop the service as
+ * appropriate.
+ *
+ * <p>All requests are handled on a single worker thread -- they may take as
+ * long as necessary (and will not block the application's main loop), but
+ * only one request will be processed at a time.
+ *
+ * @see android.os.AsyncTask
  */
 public abstract class IntentService extends Service {
     private volatile Looper mServiceLooper;
@@ -48,26 +61,42 @@
         }
     }
 
+    /**
+     * Creates an IntentService.  Invoked by your subclass's constructor.
+     *
+     * @param name Used to name the worker thread, important only for debugging.
+     */
     public IntentService(String name) {
         super();
         mName = name;
     }
 
     /**
-     * Control redelivery of intents.  If called with true,
+     * Sets intent redelivery preferences.  Usually called from the constructor
+     * with your preferred semantics.
+     *
+     * <p>If enabled is true,
      * {@link #onStartCommand(Intent, int, int)} will return
-     * {@link Service#START_REDELIVER_INTENT} instead of
-     * {@link Service#START_NOT_STICKY}, so that if this service's process
-     * is killed while it is executing the Intent in
-     * {@link #onHandleIntent(Intent)}, then when later restarted the same Intent
-     * will be re-delivered to it, to retry its execution.
+     * {@link Service#START_REDELIVER_INTENT}, so if this process dies before
+     * {@link #onHandleIntent(Intent)} returns, the process will be restarted
+     * and the intent redelivered.  If multiple Intents have been sent, only
+     * the most recent one is guaranteed to be redelivered.
+     *
+     * <p>If enabled is false (the default),
+     * {@link #onStartCommand(Intent, int, int)} will return
+     * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent
+     * dies along with it.
      */
     public void setIntentRedelivery(boolean enabled) {
         mRedelivery = enabled;
     }
-    
+
     @Override
     public void onCreate() {
+        // TODO: It would be nice to have an option to hold a partial wakelock
+        // during processing, and to have a static startService(Context, Intent)
+        // method that would launch the service & hand off a wakelock.
+
         super.onCreate();
         HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
         thread.start();
@@ -89,7 +118,7 @@
         onStart(intent, startId);
         return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
     }
-    
+
     @Override
     public void onDestroy() {
         mServiceLooper.quit();
@@ -101,9 +130,14 @@
     }
 
     /**
-     * Invoked on the Handler thread with the {@link Intent} that is passed to {@link #onStart}.
-     * Note that this will be invoked from a different thread than the one that handles the
-     * {@link #onStart} call.
+     * This method is invoked on the worker thread with a request to process.
+     * Only one Intent is processed at a time, but the processing happens on a
+     * worker thread that runs independently from other application logic.
+     * So, if this code takes a long time, it will hold up other requests to
+     * the same IntentService, but it will not hold up anything else.
+     *
+     * @param intent The value passed to {@link
+     *               android.content.Context#startService(Intent)}.
      */
     protected abstract void onHandleIntent(Intent intent);
 }
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 9d217ec..7625c04 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -123,6 +123,9 @@
     // that modifies the contents of the text field. But if the user then edits
     // the suggestion, the resulting string is saved.
     private String mUserQuery;
+    // The query passed in when opening the SearchDialog.  Used in the browser
+    // case to determine whether the user has edited the query.
+    private String mInitialQuery;
     
     // A weak map of drawables we've gotten from other packages, so we don't load them
     // more than once.
@@ -253,6 +256,7 @@
             return false;
         }
 
+        mInitialQuery = initialQuery == null ? "" : initialQuery;
         // finally, load the user's initial text (which may trigger suggestions)
         setUserQuery(initialQuery);
         if (selectInitialQuery) {
@@ -329,6 +333,7 @@
         mAppSearchData = null;
         mSearchable = null;
         mUserQuery = null;
+        mInitialQuery = null;
     }
 
     /**
@@ -687,13 +692,16 @@
             if (mSearchable == null) {
                 return;
             }
-            updateWidgetState();
             if (!mSearchAutoComplete.isPerformingCompletion()) {
                 // The user changed the query, remember it.
                 mUserQuery = s == null ? "" : s.toString();
             }
+            updateWidgetState();
             // Always want to show the microphone if the context is voice.
+            // Also show the microphone if this is a browser search and the
+            // query matches the initial query.
             updateVoiceButton(mSearchAutoComplete.isEmpty()
+                    || (isBrowserSearch() && mInitialQuery.equals(mUserQuery))
                     || (mAppSearchData != null && mAppSearchData.getBoolean(
                     SearchManager.CONTEXT_IS_VOICE)));
         }
@@ -724,8 +732,9 @@
         // enable the button if we have one or more non-space characters
         boolean enabled = !mSearchAutoComplete.isEmpty();
         if (isBrowserSearch()) {
-            // In the browser, we hide the search button when there is no text
-            if (enabled) {
+            // In the browser, we hide the search button when there is no text,
+            // or if the text matches the initial query.
+            if (enabled && !mInitialQuery.equals(mUserQuery)) {
                 mSearchAutoComplete.setBackgroundResource(
                         com.android.internal.R.drawable.textfield_search);
                 mGoButton.setVisibility(View.VISIBLE);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ee87290..3a2aa55 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -25,7 +25,6 @@
 import android.database.sqlite.SQLiteDatabase.CursorFactory;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
-import android.media.MediaScannerConnection.ScanResultListener;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -444,7 +443,7 @@
      * are not automatically scanned by the media scanner, you can explicitly
      * add them to the media database with
      * {@link android.media.MediaScannerConnection#scanFile(Context, String[], String[],
-     *      ScanResultListener) MediaScannerConnection.scanFile}.
+     *      OnScanCompletedListener) MediaScannerConnection.scanFile}.
      * Note that this is not the same as
      * {@link android.os.Environment#getExternalStoragePublicDirectory
      * Environment.getExternalStoragePublicDirectory()}, which provides
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 984c070..98a4993 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -330,11 +330,11 @@
 
     @Override public void handleMessage(Message msg) {
         if (msg.what == MSG_WRITE_STATUS) {
-            synchronized (mAccounts) {
+            synchronized (mAuthorities) {
                 writeStatusLocked();
             }
         } else if (msg.what == MSG_WRITE_STATISTICS) {
-            synchronized (mAccounts) {
+            synchronized (mAuthorities) {
                 writeStatisticsLocked();
             }
         }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index f90ef63..9939478 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -316,4 +316,7 @@
     void movePackage(String packageName, IPackageMoveObserver observer, int flags);
     
     boolean addPermissionAsync(in PermissionInfo info);
+
+    boolean setInstallLocation(int loc);
+    int getInstallLocation();
 }
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index abebdeb9..2495619 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -78,7 +78,7 @@
     private PreviewCallback mPreviewCallback;
     private PictureCallback mPostviewCallback;
     private AutoFocusCallback mAutoFocusCallback;
-    private ZoomCallback mZoomCallback;
+    private OnZoomChangeListener mZoomListener;
     private ErrorCallback mErrorCallback;
     private boolean mOneShot;
     private boolean mWithBuffer;
@@ -96,7 +96,7 @@
         mJpegCallback = null;
         mPreviewCallback = null;
         mPostviewCallback = null;
-        mZoomCallback = null;
+        mZoomListener = null;
 
         Looper looper;
         if ((looper = Looper.myLooper()) != null) {
@@ -270,16 +270,18 @@
     }
 
     /**
-     * Adds a pre-allocated buffer to the callback buffer queue. Applications
-     * can add one or more buffers to the queue. When a preview frame arrives
-     * and there is still available buffer, buffer will be filled and it is
-     * removed from the queue. Then preview callback is invoked with the buffer.
-     * If a frame arrives and there is no buffer left, the frame is discarded.
-     * Applications should add the buffers back when they finish the processing.
+     * Adds a pre-allocated buffer to the preview callback buffer queue.
+     * Applications can add one or more buffers to the queue. When a preview
+     * frame arrives and there is still available buffer, buffer will be filled
+     * and it is removed from the queue. Then preview callback is invoked with
+     * the buffer. If a frame arrives and there is no buffer left, the frame is
+     * discarded. Applications should add the buffers back when they finish the
+     * processing.
      *
-     * Preview width and height can be determined from getPreviewSize, and bitsPerPixel can be
-     * found from {@link android.hardware.Camera.Parameters#getPreviewFormat()}
-     * and {@link android.graphics.ImageFormat#getBitsPerPixel(int)}.
+     * The image format of the callback buffer can be read from {@link
+     * android.hardware.Camera.Parameters#getPreviewFormat()}. bitsPerPixel can
+     * be read from {@link android.graphics.ImageFormat#getBitsPerPixel(int)}.
+     * Preview width and height can be determined from getPreviewSize.
      *
      * Alternatively, a buffer from a previous callback may be passed in or used
      * to determine the size of new preview frame buffers.
@@ -350,8 +352,8 @@
                 return;
 
             case CAMERA_MSG_ZOOM:
-                if (mZoomCallback != null) {
-                    mZoomCallback.onZoomUpdate(msg.arg1, msg.arg2 != 0, mCamera);
+                if (mZoomListener != null) {
+                    mZoomListener.onZoomChange(msg.arg1, msg.arg2 != 0, mCamera);
                 }
                 return;
 
@@ -526,15 +528,15 @@
     }
 
     /**
-     * Zooms to the requested value smoothly. Driver will generate {@link
-     * ZoomCallback} for the zoom value and whether zoom is stopped at the
-     * time. For example, suppose the current zoom is 0 and startSmoothZoom is
-     * called with value 3. Three ZoomCallback will be generated with zoom value
-     * 1, 2, and 3. The applications can call {@link #stopSmoothZoom} to stop
-     * the zoom earlier. The applications should not call startSmoothZoom again
-     * or change the zoom value before zoom stops. If the passing zoom value
-     * equals to the current zoom value, no zoom callback will be generated.
-     * This method is supported if {@link
+     * Zooms to the requested value smoothly. Driver will notify {@link
+     * OnZoomChangeListener} of the zoom value and whether zoom is stopped at
+     * the time. For example, suppose the current zoom is 0 and startSmoothZoom
+     * is called with value 3. Method onZoomChange will be called three times
+     * with zoom value 1, 2, and 3. The applications can call {@link
+     * #stopSmoothZoom} to stop the zoom earlier. The applications should not
+     * call startSmoothZoom again or change the zoom value before zoom stops. If
+     * the passing zoom value equals to the current zoom value, no zoom callback
+     * will be generated. This method is supported if {@link
      * android.hardware.Camera.Parameters#isSmoothZoomSupported} is true.
      *
      * @param value zoom value. The valid range is 0 to {@link
@@ -546,8 +548,8 @@
 
     /**
      * Stops the smooth zoom. The applications should wait for the {@link
-     * ZoomCallback} to know when the zoom is actually stopped. This method is
-     * supported if {@link
+     * OnZoomChangeListener} to know when the zoom is actually stopped. This
+     * method is supported if {@link
      * android.hardware.Camera.Parameters#isSmoothZoomSupported} is true.
      *
      * @throws RuntimeException if the method fails.
@@ -570,35 +572,34 @@
     public native final void setDisplayOrientation(int degrees);
 
     /**
-     * Handles the zoom callback.
-     *
+     * Interface for a callback to be invoked when zoom value changes.
      */
-    public interface ZoomCallback
+    public interface OnZoomChangeListener
     {
         /**
-         * Callback for zoom updates
+         * Called when the zoom value has changed.
          *
          * @param zoomValue the current zoom value. In smooth zoom mode, camera
-         *                  generates this callback for every new zoom value.
+         *                  calls this for every new zoom value.
          * @param stopped whether smooth zoom is stopped. If the value is true,
          *                this is the last zoom update for the application.
          *
          * @param camera  the Camera service object
          * @see #startSmoothZoom(int)
          */
-        void onZoomUpdate(int zoomValue, boolean stopped, Camera camera);
+        void onZoomChange(int zoomValue, boolean stopped, Camera camera);
     };
 
     /**
-     * Registers a callback to be invoked when the zoom value is updated by the
+     * Registers a listener to be notified when the zoom value is updated by the
      * camera driver during smooth zoom.
      *
-     * @param cb the callback to run
+     * @param listener the listener to notify
      * @see #startSmoothZoom(int)
      */
-    public final void setZoomCallback(ZoomCallback cb)
+    public final void setZoomChangeListener(OnZoomChangeListener listener)
     {
-        mZoomCallback = cb;
+        mZoomListener = listener;
     }
 
     // These match the enum in include/ui/Camera.h
@@ -992,7 +993,7 @@
         /**
          * Gets the supported preview sizes.
          *
-         * @return a List of Size object. This method will always return a list
+         * @return a list of Size object. This method will always return a list
          *         with at least one element.
          */
         public List<Size> getSupportedPreviewSizes() {
@@ -1027,7 +1028,7 @@
         /**
          * Gets the supported jpeg thumbnail sizes.
          *
-         * @return a List of Size object. This method will always return a list
+         * @return a list of Size object. This method will always return a list
          *         with at least two elements. Size 0,0 (no thumbnail) is always
          *         supported.
          */
@@ -1098,8 +1099,8 @@
         /**
          * Gets the supported preview frame rates.
          *
-         * @return a List of Integer objects (preview frame rates). null if
-         *         preview frame rate setting is not supported.
+         * @return a list of supported preview frame rates. null if preview
+         *         frame rate setting is not supported.
          */
         public List<Integer> getSupportedPreviewFrameRates() {
             String str = get(KEY_PREVIEW_FRAME_RATE + SUPPORTED_VALUES_SUFFIX);
@@ -1130,11 +1131,11 @@
         }
 
         /**
-         * Returns the image format for preview pictures got from
+         * Returns the image format for preview frames got from
          * {@link PreviewCallback}.
          *
-         * @return the {@link android.graphics.ImageFormat} int representing
-         *         the preview picture format.
+         * @return the preview format.
+         * @see android.graphics.ImageFormat
          */
         public int getPreviewFormat() {
             return pixelFormatForCameraFormat(get(KEY_PREVIEW_FORMAT));
@@ -1143,8 +1144,9 @@
         /**
          * Gets the supported preview formats.
          *
-         * @return a List of Integer objects. This method will always return a
-         *         list with at least one element.
+         * @return a list of supported preview formats. This method will always
+         *         return a list with at least one element.
+         * @see android.graphics.ImageFormat
          */
         public List<Integer> getSupportedPreviewFormats() {
             String str = get(KEY_PREVIEW_FORMAT + SUPPORTED_VALUES_SUFFIX);
@@ -1182,8 +1184,8 @@
         /**
          * Gets the supported picture sizes.
          *
-         * @return a List of Size objects. This method will always return a list
-         *         with at least one element.
+         * @return a list of supported picture sizes. This method will always
+         *         return a list with at least one element.
          */
         public List<Size> getSupportedPictureSizes() {
             String str = get(KEY_PICTURE_SIZE + SUPPORTED_VALUES_SUFFIX);
@@ -1212,7 +1214,8 @@
         /**
          * Returns the image format for pictures.
          *
-         * @return the ImageFormat int representing the picture format
+         * @return the picture format
+         * @see android.graphics.ImageFormat
          */
         public int getPictureFormat() {
             return pixelFormatForCameraFormat(get(KEY_PICTURE_FORMAT));
@@ -1221,8 +1224,9 @@
         /**
          * Gets the supported picture formats.
          *
-         * @return a List of Integer objects (values are ImageFormat.XXX). This
-         *         method will always return a list with at least one element.
+         * @return supported picture formats. This method will always return a
+         *         list with at least one element.
+         * @see android.graphics.ImageFormat
          */
         public List<Integer> getSupportedPictureFormats() {
             String str = get(KEY_PICTURE_FORMAT + SUPPORTED_VALUES_SUFFIX);
@@ -1361,8 +1365,17 @@
         /**
          * Gets the current white balance setting.
          *
-         * @return one of WHITE_BALANCE_XXX string constant. null if white
-         *         balance setting is not supported.
+         * @return current white balance. null if white balance setting is not
+         *         supported.
+         * @see #WHITE_BALANCE_AUTO
+         * @see #WHITE_BALANCE_INCANDESCENT
+         * @see #WHITE_BALANCE_FLUORESCENT
+         * @see #WHITE_BALANCE_WARM_FLUORESCENT
+         * @see #WHITE_BALANCE_DAYLIGHT
+         * @see #WHITE_BALANCE_CLOUDY_DAYLIGHT
+         * @see #WHITE_BALANCE_TWILIGHT
+         * @see #WHITE_BALANCE_SHADE
+         *
          */
         public String getWhiteBalance() {
             return get(KEY_WHITE_BALANCE);
@@ -1371,7 +1384,8 @@
         /**
          * Sets the white balance.
          *
-         * @param value WHITE_BALANCE_XXX string constant.
+         * @param value new white balance.
+         * @see #getWhiteBalance()
          */
         public void setWhiteBalance(String value) {
             set(KEY_WHITE_BALANCE, value);
@@ -1380,8 +1394,9 @@
         /**
          * Gets the supported white balance.
          *
-         * @return a List of WHITE_BALANCE_XXX string constants. null if white
-         *         balance setting is not supported.
+         * @return a list of supported white balance. null if white balance
+         *         setting is not supported.
+         * @see #getWhiteBalance()
          */
         public List<String> getSupportedWhiteBalance() {
             String str = get(KEY_WHITE_BALANCE + SUPPORTED_VALUES_SUFFIX);
@@ -1391,8 +1406,17 @@
         /**
          * Gets the current color effect setting.
          *
-         * @return one of EFFECT_XXX string constant. null if color effect
+         * @return current color effect. null if color effect
          *         setting is not supported.
+         * @see #EFFECT_NONE
+         * @see #EFFECT_MONO
+         * @see #EFFECT_NEGATIVE
+         * @see #EFFECT_SOLARIZE
+         * @see #EFFECT_SEPIA
+         * @see #EFFECT_POSTERIZE
+         * @see #EFFECT_WHITEBOARD
+         * @see #EFFECT_BLACKBOARD
+         * @see #EFFECT_AQUA
          */
         public String getColorEffect() {
             return get(KEY_EFFECT);
@@ -1401,7 +1425,8 @@
         /**
          * Sets the current color effect setting.
          *
-         * @param value EFFECT_XXX string constants.
+         * @param value new color effect.
+         * @see #getColorEffect()
          */
         public void setColorEffect(String value) {
             set(KEY_EFFECT, value);
@@ -1410,8 +1435,9 @@
         /**
          * Gets the supported color effects.
          *
-         * @return a List of EFFECT_XXX string constants. null if color effect
+         * @return a list of supported color effects. null if color effect
          *         setting is not supported.
+         * @see #getColorEffect()
          */
         public List<String> getSupportedColorEffects() {
             String str = get(KEY_EFFECT + SUPPORTED_VALUES_SUFFIX);
@@ -1422,8 +1448,12 @@
         /**
          * Gets the current antibanding setting.
          *
-         * @return one of ANTIBANDING_XXX string constant. null if antibanding
-         *         setting is not supported.
+         * @return current antibanding. null if antibanding setting is not
+         *         supported.
+         * @see #ANTIBANDING_AUTO
+         * @see #ANTIBANDING_50HZ
+         * @see #ANTIBANDING_60HZ
+         * @see #ANTIBANDING_OFF
          */
         public String getAntibanding() {
             return get(KEY_ANTIBANDING);
@@ -1432,7 +1462,8 @@
         /**
          * Sets the antibanding.
          *
-         * @param antibanding ANTIBANDING_XXX string constant.
+         * @param antibanding new antibanding value.
+         * @see #getAntibanding()
          */
         public void setAntibanding(String antibanding) {
             set(KEY_ANTIBANDING, antibanding);
@@ -1441,8 +1472,9 @@
         /**
          * Gets the supported antibanding values.
          *
-         * @return a List of ANTIBANDING_XXX string constants. null if
-         *         antibanding setting is not supported.
+         * @return a list of supported antibanding values. null if antibanding
+         *         setting is not supported.
+         * @see #getAntibanding()
          */
         public List<String> getSupportedAntibanding() {
             String str = get(KEY_ANTIBANDING + SUPPORTED_VALUES_SUFFIX);
@@ -1454,6 +1486,21 @@
          *
          * @return one of SCENE_MODE_XXX string constant. null if scene mode
          *         setting is not supported.
+         * @see #SCENE_MODE_AUTO
+         * @see #SCENE_MODE_ACTION
+         * @see #SCENE_MODE_PORTRAIT
+         * @see #SCENE_MODE_LANDSCAPE
+         * @see #SCENE_MODE_NIGHT
+         * @see #SCENE_MODE_NIGHT_PORTRAIT
+         * @see #SCENE_MODE_THEATRE
+         * @see #SCENE_MODE_BEACH
+         * @see #SCENE_MODE_SNOW
+         * @see #SCENE_MODE_SUNSET
+         * @see #SCENE_MODE_STEADYPHOTO
+         * @see #SCENE_MODE_FIREWORKS
+         * @see #SCENE_MODE_SPORTS
+         * @see #SCENE_MODE_PARTY
+         * @see #SCENE_MODE_CANDLELIGHT
          */
         public String getSceneMode() {
             return get(KEY_SCENE_MODE);
@@ -1466,7 +1513,8 @@
          * applications should call getParameters to know if some parameters are
          * changed.
          *
-         * @param value SCENE_MODE_XXX string constants.
+         * @param value scene mode.
+         * @see #getSceneMode()
          */
         public void setSceneMode(String value) {
             set(KEY_SCENE_MODE, value);
@@ -1475,8 +1523,9 @@
         /**
          * Gets the supported scene modes.
          *
-         * @return a List of SCENE_MODE_XXX string constant. null if scene mode
-         *         setting is not supported.
+         * @return a list of supported scene modes. null if scene mode setting
+         *         is not supported.
+         * @see #getSceneMode()
          */
         public List<String> getSupportedSceneModes() {
             String str = get(KEY_SCENE_MODE + SUPPORTED_VALUES_SUFFIX);
@@ -1486,8 +1535,13 @@
         /**
          * Gets the current flash mode setting.
          *
-         * @return one of FLASH_MODE_XXX string constant. null if flash mode
-         *         setting is not supported.
+         * @return current flash mode. null if flash mode setting is not
+         *         supported.
+         * @see #FLASH_MODE_OFF
+         * @see #FLASH_MODE_AUTO
+         * @see #FLASH_MODE_ON
+         * @see #FLASH_MODE_RED_EYE
+         * @see #FLASH_MODE_TORCH
          */
         public String getFlashMode() {
             return get(KEY_FLASH_MODE);
@@ -1496,7 +1550,8 @@
         /**
          * Sets the flash mode.
          *
-         * @param value FLASH_MODE_XXX string constants.
+         * @param value flash mode.
+         * @see #getFlashMode()
          */
         public void setFlashMode(String value) {
             set(KEY_FLASH_MODE, value);
@@ -1505,8 +1560,9 @@
         /**
          * Gets the supported flash modes.
          *
-         * @return a List of FLASH_MODE_XXX string constants. null if flash mode
-         *         setting is not supported.
+         * @return a list of supported flash modes. null if flash mode setting
+         *         is not supported.
+         * @see #getFlashMode()
          */
         public List<String> getSupportedFlashModes() {
             String str = get(KEY_FLASH_MODE + SUPPORTED_VALUES_SUFFIX);
@@ -1516,11 +1572,15 @@
         /**
          * Gets the current focus mode setting.
          *
-         * @return one of FOCUS_MODE_XXX string constant. If the camera does not
-         *         support auto-focus, this should return {@link
-         *         #FOCUS_MODE_FIXED}. If the focus mode is not FOCUS_MODE_FIXED
-         *         or {@link #FOCUS_MODE_INFINITY}, applications should call
-         *         {@link #autoFocus(AutoFocusCallback)} to start the focus.
+         * @return current focus mode. If the camera does not support
+         *         auto-focus, this should return {@link #FOCUS_MODE_FIXED}. If
+         *         the focus mode is not FOCUS_MODE_FIXED or {@link
+         *         #FOCUS_MODE_INFINITY}, applications should call {@link
+         *         #autoFocus(AutoFocusCallback)} to start the focus.
+         * @see #FOCUS_MODE_AUTO
+         * @see #FOCUS_MODE_INFINITY
+         * @see #FOCUS_MODE_MACRO
+         * @see #FOCUS_MODE_FIXED
          */
         public String getFocusMode() {
             return get(KEY_FOCUS_MODE);
@@ -1529,7 +1589,8 @@
         /**
          * Sets the focus mode.
          *
-         * @param value FOCUS_MODE_XXX string constants.
+         * @param value focus mode.
+         * @see #getFocusMode()
          */
         public void setFocusMode(String value) {
             set(KEY_FOCUS_MODE, value);
@@ -1538,8 +1599,9 @@
         /**
          * Gets the supported focus modes.
          *
-         * @return a List of FOCUS_MODE_XXX string constants. This method will
-         *         always return a list with at least one element.
+         * @return a list of supported focus modes. This method will always
+         *         return a list with at least one element.
+         * @see #getFocusMode()
          */
         public List<String> getSupportedFocusModes() {
             String str = get(KEY_FOCUS_MODE + SUPPORTED_VALUES_SUFFIX);
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index f7e7d39..812391c 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -166,9 +166,11 @@
      * Standard directory in which to place files that have been downloaded by
      * the user.  Note that this is primarily a convention for the top-level
      * public directory, you are free to download files anywhere in your own
-     * private directories.
+     * private directories.  Also note that though the constant here is
+     * named DIRECTORY_DOWNLOADS (plural), the actual file name is non-plural for
+     * backwards compatibility reasons.
      */
-    public static String DIRECTORY_DOWNLOADS = "Downloads";
+    public static String DIRECTORY_DOWNLOADS = "Download";
     
     /**
      * The traditional location for pictures and videos when mounting the
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 7f16b4c..212c5fb 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -193,7 +193,7 @@
     /**
      * Configures bandwidth throttling on an interface
      */
-    void setInterfaceThrottle(String iface, int maxKbits, int rxKbps, int txKbps);
+    void setInterfaceThrottle(String iface, int rxKbps, int txKbps);
 
     /**
      * Returns the currently configured RX throttle values
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b8e5747..c07ac31 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1611,21 +1611,6 @@
         public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";
 
         /**
-         * Let user pick default install location.
-         * @hide
-         */
-        public static final String SET_INSTALL_LOCATION = "set_install_location";
-
-        /**
-         * Default install location value.
-         * 0 = auto, let system decide
-         * 1 = internal
-         * 2 = sdcard
-         * @hide
-         */
-        public static final String DEFAULT_INSTALL_LOCATION = "default_install_location";
-
-        /**
          * Show pointer location on screen?
          * 0 = no
          * 1 = yes
@@ -3295,6 +3280,21 @@
          * @hide
          */
         public static final String UI_NIGHT_MODE = "ui_night_mode";
+
+        /**
+         * Let user pick default install location.
+         * @hide
+         */
+        public static final String SET_INSTALL_LOCATION = "set_install_location";
+
+        /**
+         * Default install location value.
+         * 0 = auto, let system decide
+         * 1 = internal
+         * 2 = sdcard
+         * @hide
+         */
+        public static final String DEFAULT_INSTALL_LOCATION = "default_install_location";
         
         /**
          * @hide
diff --git a/core/java/android/text/method/PasswordTransformationMethod.java b/core/java/android/text/method/PasswordTransformationMethod.java
index fad4f64..b769b76 100644
--- a/core/java/android/text/method/PasswordTransformationMethod.java
+++ b/core/java/android/text/method/PasswordTransformationMethod.java
@@ -51,6 +51,8 @@
                 sp.removeSpan(vr[i]);
             }
 
+            removeVisibleSpans(sp);
+
             sp.setSpan(new ViewReference(view), 0, 0,
                        Spannable.SPAN_POINT_POINT);
         }
@@ -100,10 +102,7 @@
             int pref = TextKeyListener.getInstance().getPrefs(v.getContext());
             if ((pref & TextKeyListener.SHOW_PASSWORD) != 0) {
                 if (count > 0) {
-                    Visible[] old = sp.getSpans(0, sp.length(), Visible.class);
-                    for (int i = 0; i < old.length; i++) {
-                        sp.removeSpan(old[i]);
-                    }
+                    removeVisibleSpans(sp);
 
                     if (count == 1) {
                         sp.setSpan(new Visible(sp, this), start, start + count,
@@ -125,14 +124,18 @@
             if (sourceText instanceof Spannable) {
                 Spannable sp = (Spannable) sourceText;
 
-                Visible[] old = sp.getSpans(0, sp.length(), Visible.class);
-                for (int i = 0; i < old.length; i++) {
-                    sp.removeSpan(old[i]);
-                }
+                removeVisibleSpans(sp);
             }
         }
     }
 
+    private static void removeVisibleSpans(Spannable sp) {
+        Visible[] old = sp.getSpans(0, sp.length(), Visible.class);
+        for (int i = 0; i < old.length; i++) {
+            sp.removeSpan(old[i]);
+        }
+    }
+
     private static class PasswordCharSequence
     implements CharSequence, GetChars
     {
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index ed83bca..e56a6fe 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -766,7 +766,7 @@
                 // make sure touch mode code executes by setting cached value
                 // to opposite of the added touch mode.
                 mAttachInfo.mInTouchMode = !mAddedTouchMode;
-                ensureTouchModeLocally(mAddedTouchMode);
+                ensureTouchModeLocally(mAddedTouchMode, false);
             } else {
                 if (!mAttachInfo.mContentInsets.equals(mPendingContentInsets)) {
                     mAttachInfo.mContentInsets.set(mPendingContentInsets);
@@ -852,7 +852,11 @@
         }
 
         boolean windowShouldResize = mLayoutRequested && windowResizesToFitContent
-            && (mWidth != host.mMeasuredWidth || mHeight != host.mMeasuredHeight);
+            && ((mWidth != host.mMeasuredWidth || mHeight != host.mMeasuredHeight)
+                || (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT &&
+                        frame.width() < desiredWindowWidth && frame.width() != mWidth)
+                || (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT &&
+                        frame.height() < desiredWindowHeight && frame.height() != mHeight));
 
         final boolean computesInternalInsets =
                 attachInfo.mTreeObserver.hasComputeInternalInsetsListeners();
@@ -979,7 +983,7 @@
             }
 
             boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
-                    (relayoutResult&WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE) != 0);
+                    (relayoutResult&WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE) != 0, true);
             if (focusChangedDueToTouchMode || mWidth != host.mMeasuredWidth
                     || mHeight != host.mMeasuredHeight || contentInsetsChanged) {
                 childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
@@ -1039,6 +1043,13 @@
                 startTime = SystemClock.elapsedRealtime();
             }
             host.layout(0, 0, host.mMeasuredWidth, host.mMeasuredHeight);
+            if (mFirst) {
+                if (mAddedTouchMode) {
+                    enterTouchMode();
+                } else {
+                    leaveTouchMode();
+                }
+            }
 
             if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
                 if (!host.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_LAYOUT)) {
@@ -1888,7 +1899,7 @@
                 mAttachInfo.mHasWindowFocus = hasWindowFocus;
                 if (hasWindowFocus) {
                     boolean inTouchMode = msg.arg2 != 0;
-                    ensureTouchModeLocally(inTouchMode);
+                    ensureTouchModeLocally(inTouchMode, true);
 
                     if (mGlWanted) {
                         checkEglErrors();
@@ -1998,16 +2009,17 @@
         }
 
         // handle the change
-        return ensureTouchModeLocally(inTouchMode);
+        return ensureTouchModeLocally(inTouchMode, true);
     }
 
     /**
      * Ensure that the touch mode for this window is set, and if it is changing,
      * take the appropriate action.
      * @param inTouchMode Whether we want to be in touch mode.
+     * @param dispatchFocus
      * @return True if the touch mode changed and focus changed was changed as a result
      */
-    private boolean ensureTouchModeLocally(boolean inTouchMode) {
+    private boolean ensureTouchModeLocally(boolean inTouchMode, boolean dispatchFocus) {
         if (DBG) Log.d("touchmode", "ensureTouchModeLocally(" + inTouchMode + "), current "
                 + "touch mode is " + mAttachInfo.mInTouchMode);
 
@@ -2016,7 +2028,7 @@
         mAttachInfo.mInTouchMode = inTouchMode;
         mAttachInfo.mTreeObserver.dispatchOnTouchModeChanged(inTouchMode);
 
-        return (inTouchMode) ? enterTouchMode() : leaveTouchMode();
+        return dispatchFocus && (inTouchMode) ? enterTouchMode() : leaveTouchMode();
     }
 
     private boolean enterTouchMode() {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 88d0c25..0aa1fde 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -405,8 +405,16 @@
                     name = "FLAG_LAYOUT_IN_SCREEN"),
             @ViewDebug.FlagToString(mask = FLAG_DITHER, equals = FLAG_DITHER,
                     name = "FLAG_DITHER"),
+            @ViewDebug.FlagToString(mask = FLAG_TURN_SCREEN_ON, equals = FLAG_TURN_SCREEN_ON,
+                    name = "FLAG_TURN_SCREEN_ON"),
             @ViewDebug.FlagToString(mask = FLAG_KEEP_SCREEN_ON, equals = FLAG_KEEP_SCREEN_ON,
                     name = "FLAG_KEEP_SCREEN_ON"),
+            @ViewDebug.FlagToString(mask = FLAG_SHOW_WHEN_LOCKED, equals = FLAG_SHOW_WHEN_LOCKED,
+                    name = "FLAG_SHOW_WHEN_LOCKED"),
+            @ViewDebug.FlagToString(mask = FLAG_ALLOW_LOCK_WHILE_SCREEN_ON, equals = FLAG_ALLOW_LOCK_WHILE_SCREEN_ON,
+                    name = "FLAG_ALLOW_LOCK_WHILE_SCREEN_ON"),
+            @ViewDebug.FlagToString(mask = FLAG_DISMISS_KEYGUARD, equals = FLAG_DISMISS_KEYGUARD,
+                    name = "FLAG_DISMISS_KEYGUARD"),
             @ViewDebug.FlagToString(mask = FLAG_FULLSCREEN, equals = FLAG_FULLSCREEN,
                     name = "FLAG_FULLSCREEN"),
             @ViewDebug.FlagToString(mask = FLAG_FORCE_NOT_FULLSCREEN,
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index 42e1539..eee8025 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -129,9 +129,10 @@
                     // is invoked.
                     mTimer.cancel();
                     mTimer = null;
-                    mCurrentProxy.playbackEnded();
+                    if (mVideoView.isPlaying()) {
+                        mVideoView.stopPlayback();
+                    }
                     mCurrentProxy = null;
-                    mVideoView.stopPlayback();
                     mLayout.removeView(mVideoView);
                     mVideoView = null;
                     if (mProgressView != null) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 5cfbe73..0526362 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -6153,7 +6153,7 @@
                 case UPDATE_ZOOM_RANGE: {
                     WebViewCore.RestoreState restoreState
                             = (WebViewCore.RestoreState) msg.obj;
-                    // mScrollX contains the new contentWidth
+                    // mScrollX contains the new minPrefWidth
                     updateZoomRange(restoreState, getViewWidth(),
                             restoreState.mScrollX, false);
                     break;
@@ -6176,7 +6176,7 @@
                     boolean hasRestoreState = restoreState != null;
                     if (hasRestoreState) {
                         updateZoomRange(restoreState, viewSize.x,
-                                draw.mWidthHeight.x, true);
+                                draw.mMinPrefWidth, true);
                         if (!mDrawHistory) {
                             mInZoomOverview = false;
 
@@ -6238,12 +6238,10 @@
                         // sMaxViewportWidth so that if the page doesn't behave
                         // well, the WebView won't go insane. limit the lower
                         // bound to match the default scale for mobile sites.
-                        // we choose the content width to be mZoomOverviewWidth.
-                        // this works for most of the sites. But some sites may
-                        // cause the page layout wider than it needs.
                         mZoomOverviewWidth = Math.min(sMaxViewportWidth, Math
-                                .max((int) (viewWidth / mDefaultScale),
-                                        draw.mWidthHeight.x));
+                                .max((int) (viewWidth / mDefaultScale), Math
+                                        .max(draw.mMinPrefWidth,
+                                                draw.mViewPoint.x)));
                     }
                     if (!mMinZoomScaleFixed) {
                         mMinZoomScale = (float) viewWidth / mZoomOverviewWidth;
@@ -6893,13 +6891,12 @@
                 new InvokeListBox(array, enabledArray, selectedArray));
     }
 
-    // viewWidth/contentWidth/updateZoomOverview are only used for mobile sites
     private void updateZoomRange(WebViewCore.RestoreState restoreState,
-            int viewWidth, int contentWidth, boolean updateZoomOverview) {
+            int viewWidth, int minPrefWidth, boolean updateZoomOverview) {
         if (restoreState.mMinScale == 0) {
             if (restoreState.mMobileSite) {
-                if (contentWidth > Math.max(0, viewWidth)) {
-                    mMinZoomScale = (float) viewWidth / contentWidth;
+                if (minPrefWidth > Math.max(0, viewWidth)) {
+                    mMinZoomScale = (float) viewWidth / minPrefWidth;
                     mMinZoomScaleFixed = false;
                     if (updateZoomOverview) {
                         WebSettings settings = getSettings();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 445e7ff..625e7ba 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1705,6 +1705,7 @@
         Region mInvalRegion;
         Point mViewPoint;
         Point mWidthHeight;
+        int mMinPrefWidth;
         RestoreState mRestoreState; // only non-null if it is for the first
                                     // picture set after the first layout
         boolean mFocusSizeChanged;
@@ -1724,6 +1725,13 @@
             // layout.
             draw.mFocusSizeChanged = nativeFocusBoundsChanged();
             draw.mViewPoint = new Point(mCurrentViewWidth, mCurrentViewHeight);
+            if (mSettings.getUseWideViewPort()) {
+                draw.mMinPrefWidth = Math.max(
+                        mViewportWidth == -1 ? WebView.DEFAULT_VIEWPORT_WIDTH
+                                : (mViewportWidth == 0 ? mCurrentViewWidth
+                                        : mViewportWidth),
+                        nativeGetContentMinPrefWidth());
+            }
             if (mRestoreState != null) {
                 draw.mRestoreState = mRestoreState;
                 mRestoreState = null;
@@ -1752,9 +1760,9 @@
 
     final DrawFilter mZoomFilter =
                     new PaintFlagsDrawFilter(ZOOM_BITS, Paint.LINEAR_TEXT_FLAG);
-    final DrawFilter mScrollFilter = null;
-    // If we need to trade more speed for less quality on slower devices
-    // use this: new PaintFlagsDrawFilter(SCROLL_BITS, 0);
+    // If we need to trade better quality for speed, set mScrollFilter to null
+    final DrawFilter mScrollFilter =
+                new PaintFlagsDrawFilter(SCROLL_BITS, 0);
 
     /* package */ void drawContentPicture(Canvas canvas, int color,
                                           boolean animatingZoom,
@@ -2077,7 +2085,7 @@
             restoreState.mDefaultScale = adjust;
             // as mViewportWidth is not 0, it is not mobile site.
             restoreState.mMobileSite = false;
-            // for non-mobile site, we don't need contentWidth, set it as 0
+            // for non-mobile site, we don't need minPrefWidth, set it as 0
             restoreState.mScrollX = 0;
             Message.obtain(mWebView.mPrivateHandler,
                     WebView.UPDATE_ZOOM_RANGE, restoreState).sendToTarget();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 4aae05e..48e7f79 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2856,13 +2856,13 @@
 
         final int firstPosition = mFirstPosition;
 
-        if (firstPosition == 0 && firstTop >= listPadding.top && deltaY > 0) {
+        if (firstPosition == 0 && firstTop >= listPadding.top && deltaY >= 0) {
             // Don't need to move views down if the top of the first position
             // is already visible
             return true;
         }
 
-        if (firstPosition + childCount == mItemCount && lastBottom <= end && deltaY < 0) {
+        if (firstPosition + childCount == mItemCount && lastBottom <= end && deltaY <= 0) {
             // Don't need to move views up if the bottom of the last position
             // is already visible
             return true;
diff --git a/core/java/com/android/internal/widget/ContactHeaderWidget.java b/core/java/com/android/internal/widget/ContactHeaderWidget.java
index 333257e..f421466 100644
--- a/core/java/com/android/internal/widget/ContactHeaderWidget.java
+++ b/core/java/com/android/internal/widget/ContactHeaderWidget.java
@@ -489,7 +489,7 @@
             resetAsyncQueryHandler();
         }
 
-        mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, contactUri, ContactQuery.COLUMNS,
+        mQueryHandler.startQuery(TOKEN_CONTACT_INFO, contactUri, contactUri, ContactQuery.COLUMNS,
                 null, null, null);
     }
 
diff --git a/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png
index 41ad27d..6b4f66d 100644
--- a/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png
index ee77526..d29c6c3 100644
--- a/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png
Binary files differ
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index a4b2357..945d283 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -152,5 +152,19 @@
         android:layout_marginBottom="80dip"
         />
 
+    <!-- emergency call button shown when sim is PUKd and tab_selector is
+         hidden -->
+    <Button
+        android:id="@+id/emergencyCallButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:drawableLeft="@drawable/ic_emergency"
+        android:layout_centerInParent="true"
+        android:layout_alignParentBottom="true"
+        android:layout_marginBottom="80dip"
+        style="@style/Widget.Button.Transparent"
+        android:drawablePadding="8dip"
+        />
+
 </RelativeLayout>
 
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index e1c9772..6b76004e 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -153,4 +153,16 @@
         android:layout_marginRight="80dip"
         />
 
+    <!-- emergency call button shown when sim is PUKd and tab_selector is
+         hidden -->
+    <Button
+        android:id="@+id/emergencyCallButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:drawableLeft="@drawable/ic_emergency"
+        style="@style/Widget.Button.Transparent"
+        android:drawablePadding="8dip"
+        android:layout_marginRight="80dip"
+        />
+
 </LinearLayout>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 959a9db..3585bf1 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -527,6 +527,9 @@
         <!-- The screen layout has changed.  This might be caused by a
              different display being activated. -->
         <flag name="screenLayout" value="0x0100" />
+        <!-- The global user interface mode has changed.  For example,
+             going in or out of car mode, night mode changing, etc. -->
+        <flag name="uiMode" value="0x0200" />
         <!-- The font scaling factor has changed, that is the user has
              selected a new global font size. -->
         <flag name="fontScale" value="0x40000000" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index bf7425f..48d1ad7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1612,8 +1612,8 @@
     <string name="factorytest_reboot">Reboot</string>
 
     <!-- Do not translate.  WebView User Agent string -->
-    <string name="web_user_agent"><xliff:g id="x">Mozilla/5.0 (Linux; U; Android %s)
-        AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17</xliff:g></string>
+    <string name="web_user_agent" translatable="false"><xliff:g id="x">Mozilla/5.0 (Linux; U; Android %s)
+        AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1</xliff:g></string>
 
     <!-- Title for a JavaScript dialog. "The page at <url of current page> says:" -->
     <string name="js_dialog_title">The page at \'<xliff:g id="title">%s</xliff:g>\' says:</string>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index 7641afe..ae3daad 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -470,10 +470,7 @@
         }
 
         // Prepare for state validation
-        NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
-        cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE,
-                networkInfo.getState(),NetworkState.DO_NOTHING,State.DISCONNECTED);
-        networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
         assertEquals(State.DISCONNECTED, networkInfo.getState());
         cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_WIFI,
                 networkInfo.getState(), NetworkState.TO_CONNECTION, State.CONNECTED);
@@ -482,7 +479,9 @@
         cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
 
         waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
-            STATE_TRANSITION_LONG_TIMEOUT);
+                            STATE_TRANSITION_LONG_TIMEOUT);
+        waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.DISCONNECTED,
+                            STATE_TRANSITION_LONG_TIMEOUT);
 
         // validate the state transition
         if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_WIFI)) {
@@ -491,12 +490,6 @@
                     cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_WIFI));
             assertTrue(false);
         }
-        if (!cmActivity.validateNetworkStates(ConnectivityManager.TYPE_MOBILE)) {
-            Log.v(LOG_TAG, "Mobile state transition validation failed.");
-            Log.v(LOG_TAG, "reason: " +
-                    cmActivity.getTransitionFailureReason(ConnectivityManager.TYPE_MOBILE));
-            assertTrue(false);
-        }
     }
 
     // Test case 8: test wifi state change while connecting/disconnecting to/from an AP
diff --git a/core/tests/coretests/apks/Android.mk b/core/tests/coretests/apks/Android.mk
new file mode 100644
index 0000000..4670e21
--- /dev/null
+++ b/core/tests/coretests/apks/Android.mk
@@ -0,0 +1,5 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# build sub packages
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/coretests/apks/install_loc_auto/Android.mk b/core/tests/coretests/apks/install_loc_auto/Android.mk
new file mode 100644
index 0000000..2deb978
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_auto/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := FrameworkCoreTests_install_loc_auto
+
+include $(BUILD_PACKAGE)
+
diff --git a/core/tests/coretests/apks/install_loc_auto/AndroidManifest.xml b/core/tests/coretests/apks/install_loc_auto/AndroidManifest.xml
new file mode 100644
index 0000000..5a903e2
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_auto/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        android:installLocation="auto"
+        package="com.android.frameworks.coretests.install_loc">
+
+    <application android:hasCode="false">
+    </application>
+</manifest>
diff --git a/core/tests/coretests/apks/install_loc_auto/res/values/strings.xml b/core/tests/coretests/apks/install_loc_auto/res/values/strings.xml
new file mode 100644
index 0000000..3b8b3b1
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_auto/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="dummy">dummy</string>
+</resources>
diff --git a/core/tests/coretests/apks/install_loc_internal/Android.mk b/core/tests/coretests/apks/install_loc_internal/Android.mk
new file mode 100644
index 0000000..784bf0a
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_internal/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := FrameworkCoreTests_install_loc_internal
+
+include $(BUILD_PACKAGE)
+
diff --git a/core/tests/coretests/apks/install_loc_internal/AndroidManifest.xml b/core/tests/coretests/apks/install_loc_internal/AndroidManifest.xml
new file mode 100644
index 0000000..2568f37
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_internal/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        android:installLocation="internalOnly"
+        package="com.android.frameworks.coretests.install_loc">
+
+    <application android:hasCode="false">
+    </application>
+</manifest>
diff --git a/core/tests/coretests/apks/install_loc_internal/res/values/strings.xml b/core/tests/coretests/apks/install_loc_internal/res/values/strings.xml
new file mode 100644
index 0000000..3b8b3b1
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_internal/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="dummy">dummy</string>
+</resources>
diff --git a/core/tests/coretests/apks/install_loc_sdcard/Android.mk b/core/tests/coretests/apks/install_loc_sdcard/Android.mk
new file mode 100644
index 0000000..4eea322
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_sdcard/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := FrameworkCoreTests_install_loc_sdcard
+
+include $(BUILD_PACKAGE)
+
diff --git a/core/tests/coretests/apks/install_loc_sdcard/AndroidManifest.xml b/core/tests/coretests/apks/install_loc_sdcard/AndroidManifest.xml
new file mode 100644
index 0000000..647f4e5
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_sdcard/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        android:installLocation="preferExternal"
+        package="com.android.frameworks.coretests.install_loc">
+
+    <application android:hasCode="false">
+    </application>
+</manifest>
diff --git a/core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml b/core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml
new file mode 100644
index 0000000..3b8b3b1
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="dummy">dummy</string>
+</resources>
diff --git a/core/tests/coretests/apks/install_loc_unspecified/Android.mk b/core/tests/coretests/apks/install_loc_unspecified/Android.mk
new file mode 100644
index 0000000..206c99f
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_unspecified/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := FrameworkCoreTests_install_loc_unspecified
+
+include $(BUILD_PACKAGE)
+
diff --git a/core/tests/coretests/apks/install_loc_unspecified/AndroidManifest.xml b/core/tests/coretests/apks/install_loc_unspecified/AndroidManifest.xml
new file mode 100644
index 0000000..07b1eb3
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_unspecified/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.coretests.install_loc">
+
+    <application android:hasCode="false">
+    </application>
+</manifest>
diff --git a/core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml b/core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml
new file mode 100644
index 0000000..3b8b3b1
--- /dev/null
+++ b/core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="dummy">dummy</string>
+</resources>
diff --git a/core/tests/coretests/res/raw/install b/core/tests/coretests/res/raw/install
index 2ee1f3c..06981f4 100644
--- a/core/tests/coretests/res/raw/install
+++ b/core/tests/coretests/res/raw/install
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_app1_cert1 b/core/tests/coretests/res/raw/install_app1_cert1
index 67eb2de..f880c0b 100644
--- a/core/tests/coretests/res/raw/install_app1_cert1
+++ b/core/tests/coretests/res/raw/install_app1_cert1
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_app1_cert1_cert2 b/core/tests/coretests/res/raw/install_app1_cert1_cert2
index dbafdc5..ed89fbb 100644
--- a/core/tests/coretests/res/raw/install_app1_cert1_cert2
+++ b/core/tests/coretests/res/raw/install_app1_cert1_cert2
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_app1_cert2 b/core/tests/coretests/res/raw/install_app1_cert2
index e26c2eb..5551c7e 100644
--- a/core/tests/coretests/res/raw/install_app1_cert2
+++ b/core/tests/coretests/res/raw/install_app1_cert2
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_app1_cert3 b/core/tests/coretests/res/raw/install_app1_cert3
index fa10be7..0d1a4dc 100644
--- a/core/tests/coretests/res/raw/install_app1_cert3
+++ b/core/tests/coretests/res/raw/install_app1_cert3
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_app1_cert3_cert4 b/core/tests/coretests/res/raw/install_app1_cert3_cert4
index c2f6c81..29ff3b6 100644
--- a/core/tests/coretests/res/raw/install_app1_cert3_cert4
+++ b/core/tests/coretests/res/raw/install_app1_cert3_cert4
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_app1_unsigned b/core/tests/coretests/res/raw/install_app1_unsigned
index 18be5f8..01b39e2 100644
--- a/core/tests/coretests/res/raw/install_app1_unsigned
+++ b/core/tests/coretests/res/raw/install_app1_unsigned
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_app2_cert1 b/core/tests/coretests/res/raw/install_app2_cert1
index b345732..12bfc6f 100644
--- a/core/tests/coretests/res/raw/install_app2_cert1
+++ b/core/tests/coretests/res/raw/install_app2_cert1
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_app2_cert1_cert2 b/core/tests/coretests/res/raw/install_app2_cert1_cert2
index 1faa257..39095ba 100644
--- a/core/tests/coretests/res/raw/install_app2_cert1_cert2
+++ b/core/tests/coretests/res/raw/install_app2_cert1_cert2
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_app2_cert2 b/core/tests/coretests/res/raw/install_app2_cert2
index c3d5979..f6d965b 100644
--- a/core/tests/coretests/res/raw/install_app2_cert2
+++ b/core/tests/coretests/res/raw/install_app2_cert2
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_app2_cert3 b/core/tests/coretests/res/raw/install_app2_cert3
index ac0d9da..3d8b6f1 100644
--- a/core/tests/coretests/res/raw/install_app2_cert3
+++ b/core/tests/coretests/res/raw/install_app2_cert3
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_app2_unsigned b/core/tests/coretests/res/raw/install_app2_unsigned
index 8d24e88..b69d9fe 100644
--- a/core/tests/coretests/res/raw/install_app2_unsigned
+++ b/core/tests/coretests/res/raw/install_app2_unsigned
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_decl_perm b/core/tests/coretests/res/raw/install_decl_perm
index 6f22321..af05d81 100644
--- a/core/tests/coretests/res/raw/install_decl_perm
+++ b/core/tests/coretests/res/raw/install_decl_perm
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_loc_auto b/core/tests/coretests/res/raw/install_loc_auto
index d5d2739..63bf35c 100644
--- a/core/tests/coretests/res/raw/install_loc_auto
+++ b/core/tests/coretests/res/raw/install_loc_auto
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_loc_internal b/core/tests/coretests/res/raw/install_loc_internal
index eb6279a..5178803 100644
--- a/core/tests/coretests/res/raw/install_loc_internal
+++ b/core/tests/coretests/res/raw/install_loc_internal
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_loc_sdcard b/core/tests/coretests/res/raw/install_loc_sdcard
index c774989..013a414 100644
--- a/core/tests/coretests/res/raw/install_loc_sdcard
+++ b/core/tests/coretests/res/raw/install_loc_sdcard
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_loc_unspecified b/core/tests/coretests/res/raw/install_loc_unspecified
index ab226c6..06981f4 100644
--- a/core/tests/coretests/res/raw/install_loc_unspecified
+++ b/core/tests/coretests/res/raw/install_loc_unspecified
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_shared1_cert1 b/core/tests/coretests/res/raw/install_shared1_cert1
index d702dab..714f9ff 100644
--- a/core/tests/coretests/res/raw/install_shared1_cert1
+++ b/core/tests/coretests/res/raw/install_shared1_cert1
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_shared1_cert12 b/core/tests/coretests/res/raw/install_shared1_cert12
deleted file mode 100644
index b580b60..0000000
--- a/core/tests/coretests/res/raw/install_shared1_cert12
+++ /dev/null
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_shared1_cert1_cert2 b/core/tests/coretests/res/raw/install_shared1_cert1_cert2
index b580b60..83725e0 100644
--- a/core/tests/coretests/res/raw/install_shared1_cert1_cert2
+++ b/core/tests/coretests/res/raw/install_shared1_cert1_cert2
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_shared1_cert2 b/core/tests/coretests/res/raw/install_shared1_cert2
index a2de801..6a3157e 100644
--- a/core/tests/coretests/res/raw/install_shared1_cert2
+++ b/core/tests/coretests/res/raw/install_shared1_cert2
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_shared1_unsigned b/core/tests/coretests/res/raw/install_shared1_unsigned
index 35680be..2a2e5f5 100644
--- a/core/tests/coretests/res/raw/install_shared1_unsigned
+++ b/core/tests/coretests/res/raw/install_shared1_unsigned
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_shared2_cert1 b/core/tests/coretests/res/raw/install_shared2_cert1
index 9064de7..7006edc 100644
--- a/core/tests/coretests/res/raw/install_shared2_cert1
+++ b/core/tests/coretests/res/raw/install_shared2_cert1
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_shared2_cert12 b/core/tests/coretests/res/raw/install_shared2_cert12
deleted file mode 100644
index 26a250d..0000000
--- a/core/tests/coretests/res/raw/install_shared2_cert12
+++ /dev/null
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_shared2_cert1_cert2 b/core/tests/coretests/res/raw/install_shared2_cert1_cert2
index 26a250d..b7b084c 100644
--- a/core/tests/coretests/res/raw/install_shared2_cert1_cert2
+++ b/core/tests/coretests/res/raw/install_shared2_cert1_cert2
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_shared2_cert2 b/core/tests/coretests/res/raw/install_shared2_cert2
index 7981308..0f04388 100644
--- a/core/tests/coretests/res/raw/install_shared2_cert2
+++ b/core/tests/coretests/res/raw/install_shared2_cert2
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_shared2_unsigned b/core/tests/coretests/res/raw/install_shared2_unsigned
index ad909fd..2794282 100644
--- a/core/tests/coretests/res/raw/install_shared2_unsigned
+++ b/core/tests/coretests/res/raw/install_shared2_unsigned
Binary files differ
diff --git a/core/tests/coretests/res/raw/install_use_perm_good b/core/tests/coretests/res/raw/install_use_perm_good
index d5216f8..a7eb32f 100644
--- a/core/tests/coretests/res/raw/install_use_perm_good
+++ b/core/tests/coretests/res/raw/install_use_perm_good
Binary files differ
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index c699c10..7fa64ca 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageMoveObserver;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
@@ -327,14 +328,14 @@
         boolean checkSd = false;
         int setLoc = 0;
         try {
-            setLoc = Settings.System.getInt(mContext.getContentResolver(), Settings.System.SET_INSTALL_LOCATION);
+            setLoc = Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.SET_INSTALL_LOCATION);
         } catch (SettingNotFoundException e) {
             failStr(e);
         }
         if (setLoc == 1) {
             int userPref = APP_INSTALL_AUTO;
             try {
-                userPref = Settings.System.getInt(mContext.getContentResolver(), Settings.System.DEFAULT_INSTALL_LOCATION);
+                userPref = Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.DEFAULT_INSTALL_LOCATION);
             } catch (SettingNotFoundException e) {
                 failStr(e);
             }
@@ -1218,8 +1219,15 @@
     private class PackageMoveObserver extends IPackageMoveObserver.Stub {
         public int returnCode;
         private boolean doneFlag = false;
-
+        public String packageName;
+        public PackageMoveObserver(String pkgName) {
+            packageName = pkgName;
+        }
         public void packageMoved(String packageName, int returnCode) {
+            Log.i("DEBUG_MOVE::", "pkg = " + packageName + ", " + "ret = " + returnCode);
+            if (!packageName.equals(this.packageName)) {
+                return;
+            }
             synchronized(this) {
                 this.returnCode = returnCode;
                 doneFlag = true;
@@ -1234,7 +1242,7 @@
 
     public boolean invokeMovePackage(String pkgName, int flags,
             GenericReceiver receiver) throws Exception {
-        PackageMoveObserver observer = new PackageMoveObserver();
+        PackageMoveObserver observer = new PackageMoveObserver(pkgName);
         final boolean received = false;
         mContext.registerReceiver(receiver, receiver.filter);
         try {
@@ -1269,13 +1277,33 @@
             mContext.unregisterReceiver(receiver);
         }
     }
+    private boolean invokeMovePackageFail(String pkgName, int flags, int errCode) throws Exception {
+        PackageMoveObserver observer = new PackageMoveObserver(pkgName);
+        try {
+            // Wait on observer
+            synchronized(observer) {
+                getPm().movePackage(pkgName, observer, flags);
+                long waitTime = 0;
+                while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                    observer.wait(WAIT_TIME_INCR);
+                    waitTime += WAIT_TIME_INCR;
+                }
+                if(!observer.isDone()) {
+                    throw new Exception("Timed out waiting for pkgmove callback");
+                }
+                assertEquals(errCode, observer.returnCode);
+            }
+        } finally {
+        }
+        return true;
+    }
 
     private int getInstallLoc() {
         boolean userSetting = false;
         int origDefaultLoc = PackageInfo.INSTALL_LOCATION_AUTO;
         try {
-            userSetting = Settings.System.getInt(mContext.getContentResolver(), Settings.System.SET_INSTALL_LOCATION) != 0;
-            origDefaultLoc = Settings.System.getInt(mContext.getContentResolver(), Settings.System.DEFAULT_INSTALL_LOCATION);
+            userSetting = Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.SET_INSTALL_LOCATION) != 0;
+            origDefaultLoc = Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.DEFAULT_INSTALL_LOCATION);
         } catch (SettingNotFoundException e1) {
         }
         return origDefaultLoc;
@@ -1283,33 +1311,39 @@
 
     private void setInstallLoc(int loc) {
         Settings.System.putInt(mContext.getContentResolver(),
-                Settings.System.DEFAULT_INSTALL_LOCATION, loc);
+                Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
     }
     /*
+     * Tests for moving apps between internal and external storage
+     */
+    /*
      * Utility function that reads a apk bundled as a raw resource
      * copies it into own data directory and invokes
      * PackageManager api to install first and then replace it
      * again.
      */
-    public void moveFromRawResource(int installFlags, int moveFlags,
-            int expRetCode) {
+    
+    private void moveFromRawResource(String outFileName,
+            int rawResId, int installFlags, int moveFlags, boolean cleanUp,
+            boolean fail, int result) {
         int origDefaultLoc = getInstallLoc();
-        setInstallLoc(PackageHelper.APP_INSTALL_AUTO);
-        // Install first
-        InstallParams ip = sampleInstallFromRawResource(installFlags, false);
-        ApplicationInfo oldAppInfo = null;
+        InstallParams ip = null;
         try {
-            oldAppInfo = getPm().getApplicationInfo(ip.pkg.packageName, 0);
-        } catch (NameNotFoundException e) {
-            failStr("Pkg hasnt been installed correctly");
-        }
-
-        // Create receiver based on expRetCode
-        MoveReceiver receiver = new MoveReceiver(ip.pkg.packageName);
-        try {
-            boolean retCode = invokeMovePackage(ip.pkg.packageName, moveFlags,
-                    receiver);
-            if (expRetCode == PackageManager.MOVE_SUCCEEDED) {
+            setInstallLoc(PackageHelper.APP_INSTALL_AUTO);
+            // Install first
+            ip = installFromRawResource("install.apk", rawResId, installFlags, false,
+                    false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+            ApplicationInfo oldAppInfo = getPm().getApplicationInfo(ip.pkg.packageName, 0);
+            if (fail) {
+                assertTrue(invokeMovePackageFail(ip.pkg.packageName, moveFlags, result));
+                ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0);
+                assertNotNull(info);
+                assertEquals(oldAppInfo.flags, info.flags);
+            } else {
+                // Create receiver based on expRetCode
+                MoveReceiver receiver = new MoveReceiver(ip.pkg.packageName);
+                boolean retCode = invokeMovePackage(ip.pkg.packageName, moveFlags,
+                        receiver);
                 assertTrue(retCode);
                 ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0);
                 assertNotNull(info);
@@ -1318,40 +1352,91 @@
                 } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0){
                     assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
                 }
-            } else {
-                assertFalse(retCode);
-                ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0);
-                assertNotNull(info);
-                assertEquals(oldAppInfo.flags, info.flags);
             }
+        } catch (NameNotFoundException e) {
+            failStr("Pkg hasnt been installed correctly");
         } catch (Exception e) {
             failStr("Failed with exception : " + e);
         } finally {
-            cleanUpInstall(ip);
+            if (ip != null) {
+                cleanUpInstall(ip);
+            }
             // Restore default install location
             setInstallLoc(origDefaultLoc);
         }
     }
+    private void sampleMoveFromRawResource(int installFlags, int moveFlags, boolean fail,
+            int result) {
+        moveFromRawResource("install.apk",
+                R.raw.install, installFlags, moveFlags, true,
+                fail, result);
+    }
 
     public void testMoveAppInternalToExternal() {
-        moveFromRawResource(0, PackageManager.MOVE_EXTERNAL_MEDIA,
-                PackageManager.MOVE_SUCCEEDED);
+        int installFlags = PackageManager.INSTALL_INTERNAL;
+        int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA;
+        boolean fail = false;
+        int result = PackageManager.MOVE_SUCCEEDED;
+        sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
     }
 
     public void testMoveAppInternalToInternal() {
-        moveFromRawResource(0, PackageManager.MOVE_INTERNAL,
-                PackageManager.MOVE_FAILED_INVALID_LOCATION);
+        int installFlags = PackageManager.INSTALL_INTERNAL;
+        int moveFlags = PackageManager.MOVE_INTERNAL;
+        boolean fail = true;
+        int result = PackageManager.MOVE_FAILED_INVALID_LOCATION;
+        sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
     }
 
     public void testMoveAppExternalToExternal() {
-        moveFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.MOVE_EXTERNAL_MEDIA,
-                PackageManager.MOVE_FAILED_INVALID_LOCATION);
+        int installFlags = PackageManager.INSTALL_EXTERNAL;
+        int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA;
+        boolean fail = true;
+        int result = PackageManager.MOVE_FAILED_INVALID_LOCATION;
+        sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
     }
     public void testMoveAppExternalToInternal() {
-        moveFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.MOVE_INTERNAL,
-                PackageManager.MOVE_SUCCEEDED);
+        int installFlags = PackageManager.INSTALL_EXTERNAL;
+        int moveFlags = PackageManager.MOVE_INTERNAL;
+        boolean fail = false;
+        int result = PackageManager.MOVE_SUCCEEDED;
+        sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
     }
-
+    public void testMoveAppForwardLocked() {
+        int installFlags = PackageManager.INSTALL_FORWARD_LOCK;
+        int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA;
+        boolean fail = true;
+        int result = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
+        sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
+    }
+    public void testMoveAppFailInternalToExternalDelete() {
+        int installFlags = 0;
+        int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA;
+        boolean fail = true;
+        final int result = PackageManager.MOVE_FAILED_DOESNT_EXIST;
+        
+        int rawResId = R.raw.install;
+        int origDefaultLoc = getInstallLoc();
+        InstallParams ip = null;
+        try {
+            PackageManager pm = getPm();
+            setInstallLoc(PackageHelper.APP_INSTALL_AUTO);
+            // Install first
+            ip = installFromRawResource("install.apk", R.raw.install, installFlags, false,
+                    false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+            // Delete the package now retaining data.
+            pm.deletePackage(ip.pkg.packageName, null, PackageManager.DONT_DELETE_DATA);
+            assertTrue(invokeMovePackageFail(ip.pkg.packageName, moveFlags, result));
+        } catch (Exception e) {
+            failStr(e);
+        } finally {
+            if (ip != null) {
+                cleanUpInstall(ip);
+            }
+            // Restore default install location
+            setInstallLoc(origDefaultLoc);
+        }
+    }
     /*
      * Test that an install error code is returned when media is unmounted
      * and package installed on sdcard via package manager flag.
@@ -1799,7 +1884,7 @@
                rFlags,
                true,
                false, -1,
-               PackageInfo.INSTALL_LOCATION_AUTO);
+               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
    }
    /*
     * The following set of tests check install location for existing
@@ -1878,7 +1963,7 @@
     */
    private boolean getUserSettingSetInstallLocation() {
        try {
-           return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SET_INSTALL_LOCATION) != 0;
+           return Settings.System.getInt(mContext.getContentResolver(), Settings.Secure.SET_INSTALL_LOCATION) != 0;
            
        } catch (SettingNotFoundException e1) {
        }
@@ -1887,7 +1972,7 @@
 
    private void setUserSettingSetInstallLocation(boolean value) {
        Settings.System.putInt(mContext.getContentResolver(),
-               Settings.System.SET_INSTALL_LOCATION, value ? 1 : 0);
+               Settings.Secure.SET_INSTALL_LOCATION, value ? 1 : 0);
    }
    private void setUserX(boolean enable, int userSetting, int iloc) {
        boolean origUserSetting = getUserSettingSetInstallLocation();
diff --git a/docs/html/guide/samples/index.jd b/docs/html/guide/samples/index.jd
index 7923532..2f3ac5e 100644
--- a/docs/html/guide/samples/index.jd
+++ b/docs/html/guide/samples/index.jd
@@ -41,6 +41,10 @@
   <dd>A variety of small applications that demonstrate an extensive collection of
   framework topics.</dd>
 
+ <dt><a href="{@docRoot}resources/samples/BackupRestore/index.html">Backup and Restore</a></dt>
+  <dd>An simple example that illustrates a few different ways for an application to
+  implement support for the Android data backup and restore mechanism.</dd>
+
  <dt><a href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat</a></dt>
   <dd>An application for two-way text messaging over Bluetooth.</dd>
 
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index 41c27c6..de8ca6d 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -8,7 +8,8 @@
           android:<a href="#clear">clearTaskOnLaunch</a>=["true" | "false"]
           android:<a href="#config">configChanges</a>=["mcc", "mnc", "locale",
                                  "touchscreen", "keyboard", "keyboardHidden",
-                                 "navigation", "orientation", "fontScale"]
+                                 "navigation", "orientation", "screenLayout",
+                                 "fontScale", "uiMode"]
           android:<a href="#enabled">enabled</a>=["true" | "false"]
           android:<a href="#exclude">excludeFromRecents</a>=["true" | "false"]
           android:<a href="#exported">exported</a>=["true" | "false"]
@@ -152,13 +153,19 @@
 </p></dd>
 
 <dt><a name="config"></a>{@code android:configChanges}</dt>
-<dd>Lists configuration changes that the activity will handle itself.  When 
-changes that are not listed occur, the activity is shut down and restarted.  
-When a listed change occurs, the activity remains running and its <code>{@link android.app.Activity#onConfigurationChanged onConfigurationChanged()}</code> 
-method is called.
+<dd>Lists configuration changes that the activity will handle itself.  When a configuration
+change occurs at runtime, the activity is shut down and restarted by default, but declaring a
+configuration with this attribute will prevent the activity from being restarted. Instead, the
+activity remains running and its <code>{@link android.app.Activity#onConfigurationChanged
+onConfigurationChanged()}</code> method is called.
+
+<p class="note"><strong>Note:</strong> Using this attribute should be
+avoided and used only as a last-resort. Please read <a
+href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a> for more
+information about how to properly handle a restart due to a configuration change.</p>
 
 <p>
-Any or all of the following strings can be used to set this attribute.  Values are 
+Any or all of the following strings are valid values for this attribute. Multiple values are
 separated by '{@code |}' &mdash; for example, "{@code locale|navigation|orientation}".
 </p>
 
@@ -168,39 +175,48 @@
    <th>Description</th>
 </tr><tr>
    <td>"{@code mcc}"</td>
-   <td>The IMSI mobile country code (MCC) has changed &mdash; 
-       that is, a SIM has been detected and updated the MCC.</td>
+   <td>The IMSI mobile country code (MCC) has changed &mdash;
+       a SIM has been detected and updated the MCC.</td>
 </tr><tr>
    <td>"{@code mnc}"</td>
-   <td>The IMSI mobile network code (MNC) has changed &mdash; 
-       that is, a SIM has been detected and updated the MNC.</td>
+   <td>The IMSI mobile network code (MNC) has changed &mdash;
+       a SIM has been detected and updated the MNC.</td>
 </tr><tr>
    <td>"{@code locale}"</td>
-   <td>The locale has changed &mdash; for example, the user has selected a new 
+   <td>The locale has changed &mdash; the user has selected a new
        language that text should be displayed in.</td>
 </tr><tr>
    <td>"{@code touchscreen}"</td>
    <td>The touchscreen has changed.  (This should never normally happen.)</td>
 </tr><tr>
    <td>"{@code keyboard}"</td>
-   <td>The keyboard type has changed &mdash; for example, the user has 
+   <td>The keyboard type has changed &mdash; for example, the user has
        plugged in an external keyboard.</td>
 </tr><tr>
    <td>"{@code keyboardHidden}"</td>
-   <td>The keyboard accessibility has changed &mdash; for example, the 
-       user has slid the keyboard out to expose it.</td>
+   <td>The keyboard accessibility has changed &mdash; for example, the
+       user has revealed the hardware keyboard.</td>
 </tr><tr>
    <td>"{@code navigation}"</td>
-   <td>The navigation type has changed.  (This should never normally happen.)</td>
+   <td>The navigation type (trackball/dpad) has changed.  (This should never normally happen.)</td>
 </tr><tr>
-   <td>"{@code orientation}"</td> 
-   <td>The screen orientation has changed &mdash; that is, the user has rotated 
+   <td>"{@code orientation}"</td>
+   <td>The screen orientation has changed &mdash; the user has rotated
        the device.</td>
  </tr><tr>
+   <td>"{@code screenLayout}"</td>
+   <td>The screen layout has changed &mdash; this might be caused by a
+             different display being activated.</td>
+ </tr><tr>
   <td>"{@code fontScale}"</td>
-   <td>The font scaling factor has changed &mdash; that is, the user has selected 
+   <td>The font scaling factor has changed &mdash; the user has selected
        a new global font size.</td>
-</tr>
+  </tr><tr>
+  <td>"{@code uiMode}"</td>
+   <td>The user interface mode has changed &mdash; this can be caused when the user places the
+device into a desk/car dock or when the the night mode changes. See {@link
+android.app.UiModeManager}. <em>Introduced in API Level 8</em>.</td>
+  </tr>
 </table>
 
 <p>
diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs
index 5958f71..43ab562 100644
--- a/docs/html/resources/resources_toc.cs
+++ b/docs/html/resources/resources_toc.cs
@@ -188,6 +188,9 @@
           <li><a href="<?cs var:toroot ?>resources/samples/ApiDemos/index.html">
                 <span class="en">API Demos</span>
               </a></li>
+          <li><a href="<?cs var:toroot ?>resources/samples/BackupRestore/index.html">
+                <span class="en">Backup and Restore</span>
+              </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>resources/samples/BluetoothChat/index.html">
                 <span class="en">Bluetooth Chat</span>
               </a></li>
diff --git a/docs/html/resources/samples/index.jd b/docs/html/resources/samples/index.jd
index 044c69de..2718d0c 100644
--- a/docs/html/resources/samples/index.jd
+++ b/docs/html/resources/samples/index.jd
@@ -22,6 +22,10 @@
   <dd>A variety of small applications that demonstrate an extensive collection of
   framework topics.</dd>
 
+ <dt><a href="BackupRestore/index.html">Backup and Restore</a></dt>
+  <dd>An simple example that illustrates a few different ways for an application to
+  implement support for the Android data backup and restore mechanism.</dd>
+
  <dt><a href="BluetoothChat/index.html">Bluetooth Chat</a></dt>
   <dd>An application for two-way text messaging over Bluetooth.</dd>
 
diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h
index b5d1e7a..83be475 100644
--- a/include/media/stagefright/HTTPDataSource.h
+++ b/include/media/stagefright/HTTPDataSource.h
@@ -54,7 +54,7 @@
 
 private:
     enum {
-        kBufferSize = 32 * 1024,
+        kBufferSize = 64 * 1024,
 
         // If we encounter a socket-read error we'll try reconnecting
         // and restarting the read for at most this many times.
diff --git a/media/java/android/media/MediaScannerConnection.java b/media/java/android/media/MediaScannerConnection.java
index 65b67a1..503b5f4 100644
--- a/media/java/android/media/MediaScannerConnection.java
+++ b/media/java/android/media/MediaScannerConnection.java
@@ -30,11 +30,11 @@
 
 
 /**
- * MediaScannerConnection provides a way for applications to pass a 
+ * MediaScannerConnection provides a way for applications to pass a
  * newly created or downloaded media file to the media scanner service.
- * The media scanner service will read metadata from the file and add 
+ * The media scanner service will read metadata from the file and add
  * the file to the media content provider.
- * The MediaScannerConnectionClient provides an interface for the 
+ * The MediaScannerConnectionClient provides an interface for the
  * media scanner service to return the Uri for a newly scanned file
  * to the client of the MediaScannerConnection class.
  */
@@ -46,7 +46,7 @@
     private MediaScannerConnectionClient mClient;
     private IMediaScannerService mService;
     private boolean mConnected; // true if connect() has been called since last disconnect()
-    
+
     private IMediaScannerListener.Stub mListener = new IMediaScannerListener.Stub() {
         public void scanCompleted(String path, Uri uri) {
             MediaScannerConnectionClient client = mClient;
@@ -60,36 +60,36 @@
      * Interface for notifying clients of the result of scanning a
      * requested media file.
      */
-    public interface ScanResultListener {
+    public interface OnScanCompletedListener {
         /**
          * Called to notify the client when the media scanner has finished
          * scanning a file.
          * @param path the path to the file that has been scanned.
-         * @param uri the Uri for the file if the scanning operation succeeded 
-         * and the file was added to the media database, or null if scanning failed. 
-         */    
+         * @param uri the Uri for the file if the scanning operation succeeded
+         * and the file was added to the media database, or null if scanning failed.
+         */
         public void onScanCompleted(String path, Uri uri);
     }
-    
+
     /**
      * An interface for notifying clients of MediaScannerConnection
      * when a connection to the MediaScanner service has been established
      * and when the scanning of a file has completed.
      */
-    public interface MediaScannerConnectionClient extends ScanResultListener {
+    public interface MediaScannerConnectionClient extends OnScanCompletedListener {
         /**
-         * Called to notify the client when a connection to the 
+         * Called to notify the client when a connection to the
          * MediaScanner service has been established.
-         */    
+         */
         public void onMediaScannerConnected();
-        
+
         /**
          * Called to notify the client when the media scanner has finished
          * scanning a file.
          * @param path the path to the file that has been scanned.
-         * @param uri the Uri for the file if the scanning operation succeeded 
-         * and the file was added to the media database, or null if scanning failed. 
-         */    
+         * @param uri the Uri for the file if the scanning operation succeeded
+         * and the file was added to the media database, or null if scanning failed.
+         */
         public void onScanCompleted(String path, Uri uri);
     }
 
@@ -140,7 +140,7 @@
             }
         }
     }
-    
+
     /**
      * Returns whether we are connected to the media scanner service
      * @return true if we are connected, false otherwise
@@ -151,9 +151,9 @@
 
     /**
      * Requests the media scanner to scan a file.
-     * Success or failure of the scanning operation cannot be determined until 
+     * Success or failure of the scanning operation cannot be determined until
      * {@link MediaScannerConnectionClient#onScanCompleted(String, Uri)} is called.
-     * 
+     *
      * @param path the path to the file to be scanned.
      * @param mimeType  an optional mimeType for the file.
      * If mimeType is null, then the mimeType will be inferred from the file extension.
@@ -175,31 +175,31 @@
             }
         }
     }
-    
+
     static class ClientProxy implements MediaScannerConnectionClient {
         final String[] mPaths;
         final String[] mMimeTypes;
-        final ScanResultListener mClient;
+        final OnScanCompletedListener mClient;
         MediaScannerConnection mConnection;
         int mNextPath;
-        
-        ClientProxy(String[] paths, String[] mimeTypes, ScanResultListener client) {
+
+        ClientProxy(String[] paths, String[] mimeTypes, OnScanCompletedListener client) {
             mPaths = paths;
             mMimeTypes = mimeTypes;
             mClient = client;
         }
-        
+
         public void onMediaScannerConnected() {
             scanNextPath();
         }
-        
+
         public void onScanCompleted(String path, Uri uri) {
             if (mClient != null) {
                 mClient.onScanCompleted(path, uri);
             }
             scanNextPath();
         }
-        
+
         void scanNextPath() {
             if (mNextPath >= mPaths.length) {
                 mConnection.disconnect();
@@ -210,7 +210,7 @@
             mNextPath++;
         }
     }
-    
+
     /**
      * Convenience for constructing a {@link MediaScannerConnection}, calling
      * {@link #connect} on it, and calling {@link #scanFile} with the given
@@ -218,7 +218,7 @@
      * established.
      * @param context The caller's Context, required for establishing a connection to
      * the media scanner service.
-     * Success or failure of the scanning operation cannot be determined until 
+     * Success or failure of the scanning operation cannot be determined until
      * {@link MediaScannerConnectionClient#onScanCompleted(String, Uri)} is called.
      * @param paths Array of paths to be scanned.
      * @param mimeTypes Optional array of MIME types for each path.
@@ -229,13 +229,13 @@
      * @see scanFile(String, String)
      */
     public static void scanFile(Context context, String[] paths, String[] mimeTypes,
-            ScanResultListener callback) {
+            OnScanCompletedListener callback) {
         ClientProxy client = new ClientProxy(paths, mimeTypes, callback);
         MediaScannerConnection connection = new MediaScannerConnection(context, client);
         client.mConnection = connection;
         connection.connect();
     }
-     
+
     /**
      * Part of the ServiceConnection interface.  Do not call.
      */
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 27add0a..63dfa67 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -668,7 +668,9 @@
 }
 
 status_t AwesomePlayer::getPosition(int64_t *positionUs) {
-    if (mVideoSource != NULL) {
+    if (mSeeking) {
+        *positionUs = mSeekTimeUs;
+    } else if (mVideoSource != NULL) {
         Mutex::Autolock autoLock(mMiscStateLock);
         *positionUs = mVideoTimeUs;
     } else if (mAudioPlayer != NULL) {
@@ -710,7 +712,6 @@
 
         mWatchForAudioSeekComplete = true;
         mWatchForAudioEOS = true;
-        mSeeking = false;
         mSeekNotificationSent = false;
     }
 }
@@ -1001,6 +1002,8 @@
             notifyListener_l(MEDIA_SEEK_COMPLETE);
             mSeekNotificationSent = true;
         }
+
+        mSeeking = false;
     }
 
     status_t finalStatus;
@@ -1088,7 +1091,7 @@
         }
 
         dataSource = new CachingDataSource(
-                mConnectingDataSource, 32 * 1024, 20);
+                mConnectingDataSource, 64 * 1024, 10);
 
         mConnectingDataSource.clear();
     } else {
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 284e3bc..86e4bfe 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -105,7 +105,7 @@
         if (httpSource->connect() != OK) {
             return NULL;
         }
-        source = new CachingDataSource(httpSource, 32 * 1024, 20);
+        source = new CachingDataSource(httpSource, 64 * 1024, 10);
     } else {
         // Assume it's a filename.
         source = new FileSource(uri);
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index 61ffa8d..48f8e7a 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -35,7 +35,8 @@
 // connected.
 static bool PerformRedirectIfNecessary(
         HTTPStream *http, const String8 &headers,
-        string *host, string *path, int *port) {
+        string *host, string *path, int *port,
+        status_t *result) {
     String8 request;
     request.append("GET ");
     request.append(path->c_str());
@@ -52,6 +53,8 @@
         err = http->receive_header(&http_status);
     }
 
+    *result = err;
+
     if (err != OK) {
         return false;
     }
@@ -181,6 +184,7 @@
          host.c_str(), port, path.c_str());
 
     int numRedirectsRemaining = 5;
+    status_t result;
     do {
         status_t err = mHttp->connect(host.c_str(), port);
 
@@ -194,9 +198,19 @@
 
             return err;
         }
-    } while (PerformRedirectIfNecessary(mHttp, mHeaders, &host, &path, &port)
+    } while (PerformRedirectIfNecessary(
+                mHttp, mHeaders, &host, &path, &port, &result)
              && numRedirectsRemaining-- > 0);
 
+    if (result != OK) {
+        // An error occurred while attempting to follow redirections/connect.
+        Mutex::Autolock autoLock(mStateLock);
+
+        mState = DISCONNECTED;
+
+        return result;
+    }
+
     string value;
     if (mHttp->find_header_value("Content-Length", &value)) {
         char *end;
@@ -282,7 +296,7 @@
 
     char range[128];
     if (offset > 0) {
-        sprintf(range, "Range: bytes=%d-\r\n\r\n", offset);
+        sprintf(range, "Range: bytes=%d-\r\n", offset);
     } else {
         range[0] = '\0';
     }
@@ -313,6 +327,7 @@
     }
 
     if ((http_status / 100) != 2) {
+        LOGE("HTTP request failed, http status = %d", http_status);
         return UNKNOWN_ERROR;
     }
 
@@ -349,6 +364,10 @@
 
         memcpy(data, (const char *)mBuffer + (offset - mBufferOffset), copy);
 
+        if (copy < size) {
+            LOGV("short read (1), returning %d vs. %d requested", copy, size);
+        }
+
         return copy;
     }
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 2346639..6037088 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -535,26 +535,6 @@
                 return err;
             }
         }
-    } else if (!strncasecmp(mMIME, "audio/", 6)) {
-        if ((mQuirks & kSupportsMultipleFramesPerInputBuffer)
-            && !strcmp(mComponentName, "OMX.TI.AAC.decode")) {
-            OMX_PARAM_PORTDEFINITIONTYPE def;
-            InitOMXParams(&def);
-            def.nPortIndex = kPortIndexInput;
-
-            status_t err = mOMX->getParameter(
-                    mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
-            CHECK_EQ(err, OK);
-
-            const size_t kMinBufferSize = 100 * 1024;
-            if (def.nBufferSize < kMinBufferSize) {
-                def.nBufferSize = kMinBufferSize;
-            }
-
-            err = mOMX->setParameter(
-                    mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
-            CHECK_EQ(err, OK);
-        }
     }
 
     if (!strcasecmp(mMIME, MEDIA_MIMETYPE_IMAGE_JPEG)
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java
index 8489a67..728e68d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java
@@ -49,7 +49,6 @@
     private final String TAG = "MediaMimeTest";
     private Context mContext;
     private final String MP3_FILE = "/sdcard/media_api/music/SHORTMP3.mp3";
-    private final String MEDIA_PLAYBACK_NAME = "com.android.music.MediaPlaybackActivityStarter";
 
     public MediaMimeTest() {
         super("com.android.mediaframeworktest", MediaFrameworkTest.class);
@@ -129,7 +128,6 @@
         ResolveInfo ri = resolveMime(mime);
 
         assertNotNull(ri);
-        assertEquals(MEDIA_PLAYBACK_NAME, ri.activityInfo.name.toString());
     }
 
     // Helper method to check that NO activity handles the given mime type.
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 14c8806..57f9ce7 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -339,25 +339,19 @@
                 checkBoth = true;
                 break check_inner;
             }
-            // Check if user option is enabled
-            boolean setInstallLoc = Settings.System.getInt(getApplicationContext()
+            // Pick user preference
+            int installPreference = Settings.System.getInt(getApplicationContext()
                     .getContentResolver(),
-                    Settings.System.SET_INSTALL_LOCATION, 0) != 0;
-            if (setInstallLoc) {
-                // Pick user preference
-                int installPreference = Settings.System.getInt(getApplicationContext()
-                        .getContentResolver(),
-                        Settings.System.DEFAULT_INSTALL_LOCATION,
-                        PackageHelper.APP_INSTALL_AUTO);
-                if (installPreference == PackageHelper.APP_INSTALL_INTERNAL) {
-                    checkInt = true;
-                    checkBoth = true;
-                    break check_inner;
-                } else if (installPreference == PackageHelper.APP_INSTALL_EXTERNAL) {
-                    checkExt = true;
-                    checkBoth = true;
-                    break check_inner;
-                }
+                    Settings.Secure.DEFAULT_INSTALL_LOCATION,
+                    PackageHelper.APP_INSTALL_AUTO);
+            if (installPreference == PackageHelper.APP_INSTALL_INTERNAL) {
+                checkInt = true;
+                checkBoth = true;
+                break check_inner;
+            } else if (installPreference == PackageHelper.APP_INSTALL_EXTERNAL) {
+                checkExt = true;
+                checkBoth = true;
+                break check_inner;
             }
             // Fall back to default policy if nothing else is specified.
             checkInt = true;
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 34302c4..185d72a9 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -56,10 +56,6 @@
     <bool name="def_mount_ums_autostart">false</bool>
     <bool name="def_mount_ums_prompt">true</bool>
     <bool name="def_mount_ums_notify_enabled">true</bool>
-    <!-- Enable User preference for setting install location -->
-    <bool name="set_install_location">true</bool>
-    <!-- Default install location if user preference for setting install location is turned on. -->
-    <integer name="def_install_location">2</integer>
 
     <!-- user interface sound effects -->
     <integer name="def_power_sounds_enabled">1</integer>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index d0e9dd9..0c0bf93 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -39,6 +39,8 @@
 import android.util.Config;
 import android.util.Log;
 import android.util.Xml;
+
+import com.android.internal.content.PackageHelper;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.util.XmlUtils;
 import com.android.internal.widget.LockPatternUtils;
@@ -61,7 +63,7 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 55;
+    private static final int DATABASE_VERSION = 56;
 
     private Context mContext;
 
@@ -608,21 +610,8 @@
 
        if (upgradeVersion == 50) {
            /*
-            * New settings for set install location UI.
+            * Install location no longer initiated here.
             */
-           db.beginTransaction();
-           SQLiteStatement stmt = null;
-           try {
-                stmt = db.compileStatement("INSERT INTO system(name,value)"
-                        + " VALUES(?,?);");
-                loadBooleanSetting(stmt, Settings.System.SET_INSTALL_LOCATION,
-                        R.bool.set_install_location);
-                db.setTransactionSuccessful();
-            } finally {
-                db.endTransaction();
-                if (stmt != null) stmt.close();
-            }
-
            upgradeVersion = 51;
        }
 
@@ -663,21 +652,8 @@
         
         if (upgradeVersion == 53) {
             /*
-             * New settings for set install location UI.
+             * New settings for set install location UI no longer initiated here.
              */
-            db.beginTransaction();
-            SQLiteStatement stmt = null;
-            try {
-                 stmt = db.compileStatement("INSERT INTO system(name,value)"
-                         + " VALUES(?,?);");
-                 loadIntegerSetting(stmt, Settings.System.DEFAULT_INSTALL_LOCATION,
-                         R.integer.def_install_location);
-                 db.setTransactionSuccessful();
-             } finally {
-                 db.endTransaction();
-                 if (stmt != null) stmt.close();
-             }
-
             upgradeVersion = 54;
         }
 
@@ -696,6 +672,28 @@
             upgradeVersion = 55;
         }
 
+        if (upgradeVersion == 55) {
+            /* Move the install location settings. */
+            String[] settingsToMove = {
+                    Secure.SET_INSTALL_LOCATION,
+                    Secure.DEFAULT_INSTALL_LOCATION
+            };
+            moveFromSystemToSecure(db, settingsToMove);
+            db.beginTransaction();
+            SQLiteStatement stmt = null;
+            try {
+                stmt = db.compileStatement("INSERT INTO system(name,value)"
+                        + " VALUES(?,?);");
+                loadSetting(stmt, Secure.SET_INSTALL_LOCATION, 0);
+                loadSetting(stmt, Secure.DEFAULT_INSTALL_LOCATION,
+                        PackageHelper.APP_INSTALL_AUTO);
+                db.setTransactionSuccessful();
+             } finally {
+                 db.endTransaction();
+                 if (stmt != null) stmt.close();
+             }
+            upgradeVersion = 56;
+        }
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
@@ -1021,10 +1019,9 @@
     
             loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
                     R.bool.def_notification_pulse);
-            loadBooleanSetting(stmt, Settings.System.SET_INSTALL_LOCATION,
-                    R.bool.set_install_location);
-            loadIntegerSetting(stmt, Settings.System.DEFAULT_INSTALL_LOCATION,
-                    R.integer.def_install_location);
+            loadSetting(stmt, Settings.Secure.SET_INSTALL_LOCATION, 0);
+            loadSetting(stmt, Settings.Secure.DEFAULT_INSTALL_LOCATION,
+                    PackageHelper.APP_INSTALL_AUTO);
     
             loadUISoundEffectsSettings(stmt);
     
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 6d16aed..552bed4 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -564,11 +564,11 @@
         return getInterfaceCounter(iface, false);
     }
 
-    public void setInterfaceThrottle(String iface, int maxKbps, int rxKbps, int txKbps) {
+    public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
         mConnector.doCommand(String.format(
-                "interface setthrottle %s %d %d %d", iface, maxKbps, rxKbps, txKbps));
+                "interface setthrottle %s %d %d", iface, rxKbps, txKbps));
     }
 
     private int getInterfaceThrottle(String iface, boolean rx) {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index b1bd263..e6663d4 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -31,8 +31,9 @@
 import android.app.IActivityManager;
 import android.app.admin.IDevicePolicyManager;
 import android.app.backup.IBackupManager;
-import android.content.ComponentName;
 import android.content.Context;
+import android.content.ComponentName;
+import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
@@ -83,6 +84,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.provider.Settings;
 import android.security.SystemKeyStore;
 import android.util.*;
 import android.view.Display;
@@ -582,11 +584,11 @@
                             }
                             sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
                                     res.pkg.applicationInfo.packageName,
-                                    extras);
+                                    extras, null);
                             if (update) {
                                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
                                         res.pkg.applicationInfo.packageName,
-                                        extras);
+                                        extras, null);
                             }
                             if (res.removedInfo.args != null) {
                                 // Remove the replaced package's older resources safely now
@@ -954,7 +956,20 @@
                     + ((SystemClock.uptimeMillis()-startTime)/1000f)
                     + " seconds");
 
-            updatePermissionsLP(null, null, true, false);
+            // If the platform SDK has changed since the last time we booted,
+            // we need to re-grant app permission to catch any new ones that
+            // appear.  This is really a hack, and means that apps can in some
+            // cases get permissions that the user didn't initially explicitly
+            // allow...  it would be nice to have some better way to handle
+            // this situation.
+            final boolean regrantPermissions = mSettings.mInternalSdkPlatform
+                    != mSdkVersion;
+            if (regrantPermissions) Slog.i(TAG, "Platform changed from "
+                    + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
+                    + "; regranting permissions for internal storage");
+            mSettings.mInternalSdkPlatform = mSdkVersion;
+            
+            updatePermissionsLP(null, null, true, regrantPermissions);
 
             mSettings.writeLP();
 
@@ -4458,7 +4473,8 @@
         }
     };
 
-    private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
+    private static final void sendPackageBroadcast(String action, String pkg,
+            Bundle extras, IIntentReceiver finishedReceiver) {
         IActivityManager am = ActivityManagerNative.getDefault();
         if (am != null) {
             try {
@@ -4468,9 +4484,8 @@
                     intent.putExtras(extras);
                 }
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-                am.broadcastIntent(
-                    null, intent,
-                            null, null, 0, null, null, null, false, false);
+                am.broadcastIntent(null, intent, null, finishedReceiver,
+                        0, null, null, null, finishedReceiver != null, false);
             } catch (RemoteException ex) {
             }
         }
@@ -4592,12 +4607,14 @@
                 Bundle extras = new Bundle(1);
                 extras.putInt(Intent.EXTRA_UID, removedUid);
                 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
-                sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
+                sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
+                        extras, null);
             }
             if (addedPackage != null) {
                 Bundle extras = new Bundle(1);
                 extras.putInt(Intent.EXTRA_UID, addedUid);
-                sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
+                sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
+                        extras, null);
             }
         }
 
@@ -6039,8 +6056,8 @@
                 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
                 extras.putBoolean(Intent.EXTRA_REPLACING, true);
 
-                sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
-                sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
+                sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, null);
+                sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, null);
             }
         }
         // Force a gc here.
@@ -6071,10 +6088,10 @@
                 extras.putBoolean(Intent.EXTRA_REPLACING, true);
             }
             if (removedPackage != null) {
-                sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
+                sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras, null);
             }
             if (removedUid >= 0) {
-                sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
+                sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null);
             }
         }
     }
@@ -6776,7 +6793,7 @@
         extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
         extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
         extras.putInt(Intent.EXTRA_UID, packageUid);
-        sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED,  packageName, extras);
+        sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED,  packageName, extras, null);
     }
 
     public String getInstallerPackageName(String packageName) {
@@ -7707,6 +7724,12 @@
         final HashMap<String, PackageSetting> mDisabledSysPackages =
             new HashMap<String, PackageSetting>();
 
+        // These are the last platform API version we were using for
+        // the apps installed on internal and external storage.  It is
+        // used to grant newer permissions one time during a system upgrade.
+        int mInternalSdkPlatform;
+        int mExternalSdkPlatform;
+        
         // The user's preferred activities associated with particular intent
         // filters.
         private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
@@ -8291,6 +8314,11 @@
 
                 serializer.startTag(null, "packages");
 
+                serializer.startTag(null, "last-platform-version");
+                serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
+                serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
+                serializer.endTag(null, "last-platform-version");
+                
                 serializer.startTag(null, "permission-trees");
                 for (BasePermission bp : mPermissionTrees.values()) {
                     writePermission(serializer, bp);
@@ -8684,6 +8712,19 @@
                         if (nname != null && oname != null) {
                             mRenamedPackages.put(nname, oname);
                         }
+                    } else if (tagName.equals("last-platform-version")) {
+                        mInternalSdkPlatform = mExternalSdkPlatform = 0;
+                        try {
+                            String internal = parser.getAttributeValue(null, "internal");
+                            if (internal != null) {
+                                mInternalSdkPlatform = Integer.parseInt(internal);
+                            }
+                            String external = parser.getAttributeValue(null, "external");
+                            if (external != null) {
+                                mInternalSdkPlatform = Integer.parseInt(external);
+                            }
+                        } catch (NumberFormatException e) {
+                        }
                     } else {
                         Slog.w(TAG, "Unknown element under <packages>: "
                               + parser.getName());
@@ -9475,7 +9516,7 @@
    }
 
    private void sendResourcesChangedBroadcast(boolean mediaStatus,
-           ArrayList<String> pkgList, int uidArr[]) {
+           ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
        int size = pkgList.size();
        if (size > 0) {
            // Send broadcasts here
@@ -9487,7 +9528,7 @@
            }
            String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
                    : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
-           sendPackageBroadcast(action, null, extras);
+           sendPackageBroadcast(action, null, extras, finishedReceiver);
        }
    }
 
@@ -9553,15 +9594,28 @@
            }
        }
        synchronized (mPackages) {
+           // If the platform SDK has changed since the last time we booted,
+           // we need to re-grant app permission to catch any new ones that
+           // appear.  This is really a hack, and means that apps can in some
+           // cases get permissions that the user didn't initially explicitly
+           // allow...  it would be nice to have some better way to handle
+           // this situation.
+           final boolean regrantPermissions = mSettings.mExternalSdkPlatform
+                   != mSdkVersion;
+           if (regrantPermissions) Slog.i(TAG, "Platform changed from "
+                   + mSettings.mExternalSdkPlatform + " to " + mSdkVersion
+                   + "; regranting permissions for external storage");
+           mSettings.mExternalSdkPlatform = mSdkVersion;
+           
            // Make sure group IDs have been assigned, and any permission
            // changes in other apps are accounted for
-           updatePermissionsLP(null, null, true, false);
+           updatePermissionsLP(null, null, true, regrantPermissions);
            // Persist settings
            mSettings.writeLP();
        }
        // Send a broadcast to let everyone know we are done processing
        if (pkgList.size() > 0) {
-           sendResourcesChangedBroadcast(true, pkgList, uidArr);
+           sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
        }
        if (doGc) {
            Runtime.getRuntime().gc();
@@ -9599,10 +9653,15 @@
        }
        // Send broadcasts
        if (pkgList.size() > 0) {
-           sendResourcesChangedBroadcast(false, pkgList, uidArr);
+           sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
+               public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
+                       boolean ordered, boolean sticky) throws RemoteException {
+                   // Force gc now that everyone is done cleaning up, to release
+                   // references on assets.
+                   Runtime.getRuntime().gc();
+               }
+           });
        }
-       // Force gc
-       Runtime.getRuntime().gc();
        // Just unmount all valid containers.
        for (SdInstallArgs args : keys) {
            synchronized (mInstallLock) {
@@ -9613,9 +9672,6 @@
 
    public void movePackage(final String packageName,
            final IPackageMoveObserver observer, final int flags) {
-       if (packageName == null) {
-           return;
-       }
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.MOVE_PACKAGE, null);
        int returnCode = PackageManager.MOVE_SUCCEEDED;
@@ -9625,30 +9681,31 @@
            PackageParser.Package pkg = mPackages.get(packageName);
            if (pkg == null) {
                returnCode =  PackageManager.MOVE_FAILED_DOESNT_EXIST;
-           }
-           // Disable moving fwd locked apps and system packages
-           if (pkg.applicationInfo != null &&
-                   (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
-               Slog.w(TAG, "Cannot move system application");
-               returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
-           } else if (pkg.applicationInfo != null &&
-                   (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
-               Slog.w(TAG, "Cannot move forward locked app.");
-               returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
            } else {
-               // Find install location first
-               if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 &&
-                       (flags & PackageManager.MOVE_INTERNAL) != 0) {
-                   Slog.w(TAG, "Ambigous flags specified for move location.");
-                   returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
+               // Disable moving fwd locked apps and system packages
+               if (pkg.applicationInfo != null &&
+                       (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                   Slog.w(TAG, "Cannot move system application");
+                   returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
+               } else if (pkg.applicationInfo != null &&
+                       (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
+                   Slog.w(TAG, "Cannot move forward locked app.");
+                   returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
                } else {
-                   newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
-                           PackageManager.INSTALL_EXTERNAL : 0;
-                   currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ?
-                           PackageManager.INSTALL_EXTERNAL : 0;
-                   if (newFlags == currFlags) {
-                       Slog.w(TAG, "No move required. Trying to move to same location");
+                   // Find install location first
+                   if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 &&
+                           (flags & PackageManager.MOVE_INTERNAL) != 0) {
+                       Slog.w(TAG, "Ambigous flags specified for move location.");
                        returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
+                   } else {
+                       newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
+                               PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
+                       currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ?
+                               PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
+                       if (newFlags == currFlags) {
+                           Slog.w(TAG, "No move required. Trying to move to same location");
+                           returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
+                       }
                    }
                }
            }
@@ -9672,67 +9729,87 @@
            public void run() {
                mHandler.removeCallbacks(this);
                int returnCode = currentStatus;
-               boolean moveSucceeded = (returnCode == PackageManager.MOVE_SUCCEEDED);
-               if (moveSucceeded) {
-                   int uid = -1;
+               if (currentStatus == PackageManager.MOVE_SUCCEEDED) {
+                   int uidArr[] = null;
+                   ArrayList<String> pkgList = null;
                    synchronized (mPackages) {
-                       uid = mPackages.get(mp.packageName).applicationInfo.uid;
-                   }
-                   ArrayList<String> pkgList = new ArrayList<String>();
-                   pkgList.add(mp.packageName);
-                   int uidArr[] = new int[] { uid };
-                   // Send resources unavailable broadcast
-                   sendResourcesChangedBroadcast(false, pkgList, uidArr);
-
-                   // Update package code and resource paths
-                   synchronized (mInstallLock) {
-                       synchronized (mPackages) {
-                           PackageParser.Package pkg = mPackages.get(mp.packageName);
-                           if (pkg != null) {
-                               String oldCodePath = pkg.mPath;
-                               String newCodePath = mp.targetArgs.getCodePath();
-                               String newResPath = mp.targetArgs.getResourcePath();
-                               pkg.mPath = newCodePath;
-                               // Move dex files around
-                               if (moveDexFilesLI(pkg)
-                                       != PackageManager.INSTALL_SUCCEEDED) {
-                                   // Moving of dex files failed. Set
-                                   // error code and abort move.
-                                   pkg.mPath = pkg.mScanPath;
-                                   returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
-                                   moveSucceeded = false;
-                               } else {
-                                   pkg.mScanPath = newCodePath;
-                                   pkg.applicationInfo.sourceDir = newCodePath;
-                                   pkg.applicationInfo.publicSourceDir = newResPath;
-                                   PackageSetting ps = (PackageSetting) pkg.mExtras;
-                                   ps.codePath = new File(pkg.applicationInfo.sourceDir);
-                                   ps.codePathString = ps.codePath.getPath();
-                                   ps.resourcePath = new File(pkg.applicationInfo.publicSourceDir);
-                                   ps.resourcePathString = ps.resourcePath.getPath();
-                                   // Set the application info flag correctly.
-                                   if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
-                                       pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
-                                   } else {
-                                       pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
-                                   }
-                                   ps.setFlags(pkg.applicationInfo.flags);
-                                   mAppDirs.remove(oldCodePath);
-                                   mAppDirs.put(newCodePath, pkg);
-                                   // Persist settings
-                                   mSettings.writeLP();
-                               }
-                           }
+                       PackageParser.Package pkg = mPackages.get(mp.packageName);
+                       if (pkg == null ) {
+                           Slog.w(TAG, " Package " + mp.packageName +
+                           " doesn't exist. Aborting move");
+                           returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
+                       } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
+                           Slog.w(TAG, "Package " + mp.packageName + " code path changed from " +
+                                   mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir +
+                           " Aborting move and returning error");
+                           returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
+                       } else {
+                           uidArr = new int[] { pkg.applicationInfo.uid };
+                           pkgList = new ArrayList<String>();
+                           pkgList.add(mp.packageName);
                        }
                    }
-                   // Send resources available broadcast
-                   sendResourcesChangedBroadcast(true, pkgList, uidArr);
+                   if (returnCode == PackageManager.MOVE_SUCCEEDED) {
+                       // Send resources unavailable broadcast
+                       sendResourcesChangedBroadcast(false, pkgList, uidArr, null);
+                       // Update package code and resource paths
+                       synchronized (mInstallLock) {
+                           synchronized (mPackages) {
+                               PackageParser.Package pkg = mPackages.get(mp.packageName);
+                               // Recheck for package again.
+                               if (pkg == null ) {
+                                   Slog.w(TAG, " Package " + mp.packageName +
+                                   " doesn't exist. Aborting move");
+                                   returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
+                               } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
+                                   Slog.w(TAG, "Package " + mp.packageName + " code path changed from " +
+                                           mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir +
+                                   " Aborting move and returning error");
+                                   returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
+                               } else {
+                                   String oldCodePath = pkg.mPath;
+                                   String newCodePath = mp.targetArgs.getCodePath();
+                                   String newResPath = mp.targetArgs.getResourcePath();
+                                   pkg.mPath = newCodePath;
+                                   // Move dex files around
+                                   if (moveDexFilesLI(pkg)
+                                           != PackageManager.INSTALL_SUCCEEDED) {
+                                       // Moving of dex files failed. Set
+                                       // error code and abort move.
+                                       pkg.mPath = pkg.mScanPath;
+                                       returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
+                                   } else {
+                                       pkg.mScanPath = newCodePath;
+                                       pkg.applicationInfo.sourceDir = newCodePath;
+                                       pkg.applicationInfo.publicSourceDir = newResPath;
+                                       PackageSetting ps = (PackageSetting) pkg.mExtras;
+                                       ps.codePath = new File(pkg.applicationInfo.sourceDir);
+                                       ps.codePathString = ps.codePath.getPath();
+                                       ps.resourcePath = new File(pkg.applicationInfo.publicSourceDir);
+                                       ps.resourcePathString = ps.resourcePath.getPath();
+                                       // Set the application info flag correctly.
+                                       if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
+                                           pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
+                                       } else {
+                                           pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
+                                       }
+                                       ps.setFlags(pkg.applicationInfo.flags);
+                                       mAppDirs.remove(oldCodePath);
+                                       mAppDirs.put(newCodePath, pkg);
+                                       // Persist settings
+                                       mSettings.writeLP();
+                                   }
+                               }
+                           }
+                           // Send resources available broadcast
+                           sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
+                       }
+                   }
                }
-               if (!moveSucceeded){
+               if (returnCode != PackageManager.MOVE_SUCCEEDED){
                    // Clean up failed installation
                    if (mp.targetArgs != null) {
-                       mp.targetArgs.doPostInstall(
-                               returnCode);
+                       mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
                    }
                } else {
                    // Force a gc to clear things up.
@@ -9753,4 +9830,26 @@
            }
        });
    }
+
+   public boolean setInstallLocation(int loc) {
+       mContext.enforceCallingOrSelfPermission(
+               android.Manifest.permission.WRITE_SECURE_SETTINGS, null);
+       if (getInstallLocation() == loc) {
+           return true;
+       }
+       if (loc == PackageHelper.APP_INSTALL_AUTO ||
+               loc == PackageHelper.APP_INSTALL_INTERNAL ||
+               loc == PackageHelper.APP_INSTALL_EXTERNAL) {
+           android.provider.Settings.System.putInt(mContext.getContentResolver(),
+                   android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
+           return true;
+       }
+       return false;
+   }
+
+   public int getInstallLocation() {
+       return android.provider.Settings.System.getInt(mContext.getContentResolver(),
+               android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, PackageHelper.APP_INSTALL_AUTO);
+   }
 }
+
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3b655fa..bc26fa0 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1369,7 +1369,7 @@
                         return;
                     }
                 } else {
-                    procs = service.mLruProcesses;
+                    procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
                 }
             }
             dumpApplicationMemoryUsage(fd, pw, procs, "  ", args);
@@ -10202,7 +10202,7 @@
         return numPers;
     }
 
-    private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
+    static final void dumpApplicationMemoryUsage(FileDescriptor fd,
             PrintWriter pw, List list, String prefix, String[] args) {
         final boolean isCheckinRequest = scanArgs(args, "--checkin");
         long uptime = SystemClock.uptimeMillis();
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 55840e2..465ff2e 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -818,7 +818,7 @@
 
         final ContentResolver cr = mContext.getContentResolver();
         if (Settings.System.getInt(cr,
-                Settings.System.POWER_SOUNDS_ENABLED, 1) == 1) 
+                Settings.System.POWER_SOUNDS_ENABLED, 1) == 1)
         {
             final String soundPath = Settings.System.getString(cr,
                 Settings.System.LOW_BATTERY_SOUND);
@@ -972,7 +972,8 @@
         int iconLevel = -1;
         int[] iconList;
 
-        if (!hasService()) {
+        // Display signal strength while in "emergency calls only" mode
+        if (!hasService() && !mServiceState.isEmergencyOnly()) {
             //Slog.d(TAG, "updateSignalStrength: no service");
             if (Settings.System.getInt(mContext.getContentResolver(),
                     Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 48a40fa..6c66559 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -113,6 +113,8 @@
     private String mOperatorNumeric;
     private boolean mIsManualNetworkSelection;
 
+    private boolean mIsEmergencyOnly;
+
     //***** CDMA
     private int mRadioTechnology;
     private boolean mCssIndicator;
@@ -170,6 +172,7 @@
         mCdmaDefaultRoamingIndicator = s.mCdmaDefaultRoamingIndicator;
         mCdmaEriIconIndex = s.mCdmaEriIconIndex;
         mCdmaEriIconMode = s.mCdmaEriIconMode;
+        mIsEmergencyOnly = s.mIsEmergencyOnly;
     }
 
     /**
@@ -190,6 +193,7 @@
         mCdmaDefaultRoamingIndicator = in.readInt();
         mCdmaEriIconIndex = in.readInt();
         mCdmaEriIconMode = in.readInt();
+        mIsEmergencyOnly = in.readInt() != 0;
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -207,6 +211,7 @@
         out.writeInt(mCdmaDefaultRoamingIndicator);
         out.writeInt(mCdmaEriIconIndex);
         out.writeInt(mCdmaEriIconMode);
+        out.writeInt(mIsEmergencyOnly ? 1 : 0);
     }
 
     public int describeContents() {
@@ -250,6 +255,13 @@
     /**
      * @hide
      */
+    public boolean isEmergencyOnly() {
+        return mIsEmergencyOnly;
+    }
+
+    /**
+     * @hide
+     */
     public int getCdmaRoamingIndicator(){
         return this.mCdmaRoamingIndicator;
     }
@@ -330,7 +342,8 @@
                 + ((null == mOperatorAlphaShort) ? 0 : mOperatorAlphaShort.hashCode())
                 + ((null == mOperatorNumeric) ? 0 : mOperatorNumeric.hashCode())
                 + mCdmaRoamingIndicator
-                + mCdmaDefaultRoamingIndicator);
+                + mCdmaDefaultRoamingIndicator
+                + (mIsEmergencyOnly ? 1 : 0));
     }
 
     @Override
@@ -359,7 +372,8 @@
                 && equalsHandlesNulls(mSystemId, s.mSystemId)
                 && equalsHandlesNulls(mCdmaRoamingIndicator, s.mCdmaRoamingIndicator)
                 && equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
-                        s.mCdmaDefaultRoamingIndicator));
+                        s.mCdmaDefaultRoamingIndicator)
+                && mIsEmergencyOnly == s.mIsEmergencyOnly);
     }
 
     @Override
@@ -418,7 +432,8 @@
                 + " " + mNetworkId
                 + " " + mSystemId
                 + "RoamInd: " + mCdmaRoamingIndicator
-                + "DefRoamInd: " + mCdmaDefaultRoamingIndicator);
+                + "DefRoamInd: " + mCdmaDefaultRoamingIndicator
+                + "EmergOnly: " + mIsEmergencyOnly);
     }
 
     public void setStateOutOfService() {
@@ -436,6 +451,7 @@
         mCdmaDefaultRoamingIndicator = -1;
         mCdmaEriIconIndex = -1;
         mCdmaEriIconMode = -1;
+        mIsEmergencyOnly = false;
     }
 
     // TODO - can't this be combined with the above func..
@@ -454,6 +470,7 @@
         mCdmaDefaultRoamingIndicator = -1;
         mCdmaEriIconIndex = -1;
         mCdmaEriIconMode = -1;
+        mIsEmergencyOnly = false;
     }
 
     public void setState(int state) {
@@ -464,6 +481,14 @@
         mRoaming = roaming;
     }
 
+
+    /**
+     * @hide
+     */
+    public void setEmergencyOnly(boolean emergencyOnly) {
+        mIsEmergencyOnly = emergencyOnly;
+    }
+
     /**
      * @hide
      */
@@ -542,6 +567,7 @@
         mSystemId = m.getInt("systemId");
         mCdmaRoamingIndicator = m.getInt("cdmaRoamingIndicator");
         mCdmaDefaultRoamingIndicator = m.getInt("cdmaDefaultRoamingIndicator");
+        mIsEmergencyOnly = m.getBoolean("emergencyOnly");
     }
 
     /**
@@ -563,6 +589,7 @@
         m.putInt("systemId", mSystemId);
         m.putInt("cdmaRoamingIndicator", mCdmaRoamingIndicator);
         m.putInt("cdmaDefaultRoamingIndicator", mCdmaDefaultRoamingIndicator);
+        m.putBoolean("emergencyOnly", Boolean.valueOf(mIsEmergencyOnly));
     }
 
     //***** CDMA
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index e4fcf6c..50b8eba 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -102,7 +102,6 @@
      * Mark when service state is in emergency call only mode
      */
     private boolean mEmergencyOnly = false;
-    private boolean mNewEmergencyOnly = false;
 
     private RegistrantList gprsAttachedRegistrants = new RegistrantList();
     private RegistrantList gprsDetachedRegistrants = new RegistrantList();
@@ -591,8 +590,8 @@
         if (rule != curSpnRule
                 || !TextUtils.equals(spn, curSpn)
                 || !TextUtils.equals(plmn, curPlmn)) {
-            boolean showSpn = mEmergencyOnly
-                || (rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN;
+            boolean showSpn = !mEmergencyOnly
+                && (rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN;
             boolean showPlmn =
                 (rule & SIMRecords.SPN_RULE_SHOW_PLMN) == SIMRecords.SPN_RULE_SHOW_PLMN;
 
@@ -672,9 +671,9 @@
                     newSS.setState (regCodeToServiceState(regState));
 
                     if (regState == 10 || regState == 12 || regState == 13 || regState == 14) {
-                        mNewEmergencyOnly = true;
+                        mEmergencyOnly = true;
                     } else {
-                        mNewEmergencyOnly = false;
+                        mEmergencyOnly = false;
                     }
 
                     // LAC and CID are -1 if not avail
@@ -741,6 +740,7 @@
                 roaming = false;
             }
             newSS.setRoaming(roaming);
+            newSS.setEmergencyOnly(mEmergencyOnly);
             pollStateDone();
         }
     }
@@ -886,8 +886,6 @@
 
         boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
 
-        boolean hasEmergencyOnlyChanged = mNewEmergencyOnly != mEmergencyOnly;
-
         // Add an event log when connection state changes
         if (ss.getState() != newSS.getState() || gprsState != newGPRSState) {
             EventLog.writeEvent(EventLogTags.GSM_SERVICE_STATE_CHANGE,
@@ -905,8 +903,6 @@
         cellLoc = newCellLoc;
         newCellLoc = tcl;
 
-        mEmergencyOnly = mNewEmergencyOnly;
-
         // Add an event log when network type switched
         // TODO: we may add filtering to reduce the event logged,
         // i.e. check preferred network setting, only switch to 2G, etc
@@ -937,6 +933,8 @@
         if (hasChanged) {
             String operatorNumeric;
 
+            updateSpnDisplay();
+
             phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
                 ss.getOperatorAlphaLong());
 
@@ -1005,10 +1003,6 @@
             phone.notifyServiceStateChanged(ss);
         }
 
-        if (hasChanged || hasEmergencyOnlyChanged) {
-            updateSpnDisplay();
-        }
-
         if (hasGprsAttached) {
             gprsAttachedRegistrants.notifyRegistrants();
         }