Merge "Better file permissions enforcement on system keystore."
diff --git a/api/current.xml b/api/current.xml
index 33a8020..2729ff4 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -26277,6 +26277,83 @@
 </parameter>
 </method>
 </interface>
+<class name="UiModeManager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="disableCarMode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNightMode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setNightMode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<field name="MODE_AUTO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MODE_NIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MODE_NOTNIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="WallpaperInfo"
  extends="java.lang.Object"
  abstract="false"
@@ -34549,6 +34626,17 @@
  visibility="public"
 >
 </field>
+<field name="UI_MODE_SERVICE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;uimode&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="VIBRATOR_SERVICE"
  type="java.lang.String"
  transient="false"
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 832f599..fe81056 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -16,8 +16,16 @@
 
 package android.app;
 
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemProperties;
+import android.provider.Settings;
 import android.util.Printer;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -38,6 +46,13 @@
  */
 
 public class ApplicationErrorReport implements Parcelable {
+    // System property defining error report receiver for system apps
+    static final String SYSTEM_APPS_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.system.apps";
+
+    // System property defining default error report receiver
+    static final String DEFAULT_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.default";
+
+    
     /**
      * Uninitialized error report.
      */
@@ -54,8 +69,13 @@
     public static final int TYPE_ANR = 2;
 
     /**
+     * An error report about an application that's consuming too much battery.
+     */
+    public static final int TYPE_BATTERY = 3;
+
+    /**
      * Type of this report. Can be one of {@link #TYPE_NONE},
-     * {@link #TYPE_CRASH} or {@link #TYPE_ANR}.
+     * {@link #TYPE_CRASH}, {@link #TYPE_ANR}, or {@link #TYPE_BATTERY}.
      */
     public int type;
 
@@ -99,6 +119,11 @@
     public AnrInfo anrInfo;
 
     /**
+     * Text containing battery usage data.
+     */
+    public String batteryText;
+    
+    /**
      * Create an uninitialized instance of {@link ApplicationErrorReport}.
      */
     public ApplicationErrorReport() {
@@ -112,6 +137,68 @@
         readFromParcel(in);
     }
 
+    public static ComponentName getErrorReportReceiver(Context context,
+            String packageName, int appFlags) {
+        // check if error reporting is enabled in secure settings
+        int enabled = Settings.Secure.getInt(context.getContentResolver(),
+                Settings.Secure.SEND_ACTION_APP_ERROR, 0);
+        if (enabled == 0) {
+            return null;
+        }
+
+        PackageManager pm = context.getPackageManager();
+
+        // look for receiver in the installer package
+        String candidate = pm.getInstallerPackageName(packageName);
+        ComponentName result = getErrorReportReceiver(pm, packageName, candidate);
+        if (result != null) {
+            return result;
+        }
+
+        // if the error app is on the system image, look for system apps
+        // error receiver
+        if ((appFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
+            candidate = SystemProperties.get(SYSTEM_APPS_ERROR_RECEIVER_PROPERTY);
+            result = getErrorReportReceiver(pm, packageName, candidate);
+            if (result != null) {
+                return result;
+            }
+        }
+
+        // if there is a default receiver, try that
+        candidate = SystemProperties.get(DEFAULT_ERROR_RECEIVER_PROPERTY);
+        return getErrorReportReceiver(pm, packageName, candidate);
+    }
+    
+    /**
+     * Return activity in receiverPackage that handles ACTION_APP_ERROR.
+     *
+     * @param pm PackageManager isntance
+     * @param errorPackage package which caused the error
+     * @param receiverPackage candidate package to receive the error
+     * @return activity component within receiverPackage which handles
+     * ACTION_APP_ERROR, or null if not found
+     */
+    static ComponentName getErrorReportReceiver(PackageManager pm, String errorPackage,
+            String receiverPackage) {
+        if (receiverPackage == null || receiverPackage.length() == 0) {
+            return null;
+        }
+
+        // break the loop if it's the error report receiver package that crashed
+        if (receiverPackage.equals(errorPackage)) {
+            return null;
+        }
+
+        Intent intent = new Intent(Intent.ACTION_APP_ERROR);
+        intent.setPackage(receiverPackage);
+        ResolveInfo info = pm.resolveActivity(intent, 0);
+        if (info == null || info.activityInfo == null) {
+            return null;
+        }
+        return new ComponentName(receiverPackage, info.activityInfo.name);
+    }
+
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(type);
         dest.writeString(packageName);
@@ -127,6 +214,9 @@
             case TYPE_ANR:
                 anrInfo.writeToParcel(dest, flags);
                 break;
+            case TYPE_BATTERY:
+                dest.writeString(batteryText);
+                break;
         }
     }
 
@@ -142,10 +232,17 @@
             case TYPE_CRASH:
                 crashInfo = new CrashInfo(in);
                 anrInfo = null;
+                batteryText = null;
                 break;
             case TYPE_ANR:
                 anrInfo = new AnrInfo(in);
                 crashInfo = null;
+                batteryText = null;
+                break;
+            case TYPE_BATTERY:
+                batteryText = in.readString();
+                anrInfo = null;
+                crashInfo = null;
                 break;
         }
     }
@@ -347,6 +444,9 @@
             case TYPE_ANR:
                 anrInfo.dump(pw, prefix);
                 break;
+            case TYPE_BATTERY:
+                pw.println(batteryText);
+                break;
         }
     }
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1d004ee..50dcdf9 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -194,6 +194,7 @@
     private AccountManager mAccountManager; // protected by mSync
     private DropBoxManager mDropBoxManager = null;
     private DevicePolicyManager mDevicePolicyManager = null;
+    private UiModeManager mUiModeManager = null;
 
     private final Object mSync = new Object();
 
@@ -960,6 +961,8 @@
             return getDropBoxManager();
         } else if (DEVICE_POLICY_SERVICE.equals(name)) {
             return getDevicePolicyManager();
+        } else if (UI_MODE_SERVICE.equals(name)) {
+            return getUiModeManager();
         }
 
         return null;
@@ -1146,13 +1149,22 @@
     private DevicePolicyManager getDevicePolicyManager() {
         synchronized (mSync) {
             if (mDevicePolicyManager == null) {
-                mDevicePolicyManager = new DevicePolicyManager(this,
+                mDevicePolicyManager = DevicePolicyManager.create(this,
                         mMainThread.getHandler());
             }
         }
         return mDevicePolicyManager;
     }
 
+    private UiModeManager getUiModeManager() {
+        synchronized (mSync) {
+            if (mUiModeManager == null) {
+                mUiModeManager = new UiModeManager();
+            }
+        }
+        return mUiModeManager;
+    }
+
     @Override
     public int checkPermission(String permission, int pid, int uid) {
         if (permission == null) {
diff --git a/core/java/android/app/DeviceAdminInfo.java b/core/java/android/app/DeviceAdminInfo.java
index bedf4b4..61e1bb339 100644
--- a/core/java/android/app/DeviceAdminInfo.java
+++ b/core/java/android/app/DeviceAdminInfo.java
@@ -18,6 +18,7 @@
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
 
 import android.content.ComponentName;
 import android.content.Context;
@@ -331,6 +332,19 @@
         return res;
     }
     
+    /** @hide */
+    public void writePoliciesToXml(XmlSerializer out)
+            throws IllegalArgumentException, IllegalStateException, IOException {
+        out.attribute(null, "flags", Integer.toString(mUsesPolicies));
+    }
+    
+    /** @hide */
+    public void readPoliciesFromXml(XmlPullParser parser)
+            throws XmlPullParserException, IOException {
+        mUsesPolicies = Integer.parseInt(
+                parser.getAttributeValue(null, "flags"));
+    }
+    
     public void dump(Printer pw, String prefix) {
         pw.println(prefix + "Receiver:");
         mReceiver.dump(pw, prefix + "  ");
diff --git a/core/java/android/app/DevicePolicyManager.java b/core/java/android/app/DevicePolicyManager.java
index d611807..0e8c1ab 100644
--- a/core/java/android/app/DevicePolicyManager.java
+++ b/core/java/android/app/DevicePolicyManager.java
@@ -49,13 +49,18 @@
     
     private final Handler mHandler;
 
-    /*package*/ DevicePolicyManager(Context context, Handler handler) {
+    private DevicePolicyManager(Context context, Handler handler) {
         mContext = context;
         mHandler = handler;
         mService = IDevicePolicyManager.Stub.asInterface(
                 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
     }
 
+    /*package*/ static DevicePolicyManager create(Context context, Handler handler) {
+        DevicePolicyManager me = new DevicePolicyManager(context, handler);
+        return me.mService != null ? me : null;
+    }
+    
     /**
      * Activity action: ask the user to add a new device administrator to the system.
      * The desired policy is the ComponentName of the policy in the
@@ -133,6 +138,20 @@
     }
     
     /**
+     * @hide
+     */
+    public boolean packageHasActiveAdmins(String packageName) {
+        if (mService != null) {
+            try {
+                return mService.packageHasActiveAdmins(packageName);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return false;
+    }
+    
+    /**
      * Remove a current administration component.  This can only be called
      * by the application that owns the administration component; if you
      * try to remove someone else's component, a security exception will be
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 4598bb5..0ed5eb8 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -822,13 +822,15 @@
         final SearchManager searchManager = (SearchManager) mContext
                 .getSystemService(Context.SEARCH_SERVICE);
 
-        // associate search with owner activity if possible (otherwise it will default to
-        // global search).
+        // associate search with owner activity
         final ComponentName appName = getAssociatedActivity();
-        final boolean globalSearch = (appName == null);
-        searchManager.startSearch(null, false, appName, null, globalSearch);
-        dismiss();
-        return true;
+        if (appName != null) {
+            searchManager.startSearch(null, false, appName, null, false);
+            dismiss();
+            return true;
+        } else {
+            return false;
+        }
     }
 
     /**
diff --git a/core/java/android/app/IDevicePolicyManager.aidl b/core/java/android/app/IDevicePolicyManager.aidl
index ae5c4bf..b138720 100644
--- a/core/java/android/app/IDevicePolicyManager.aidl
+++ b/core/java/android/app/IDevicePolicyManager.aidl
@@ -49,6 +49,7 @@
     void setActiveAdmin(in ComponentName policyReceiver);
     boolean isAdminActive(in ComponentName policyReceiver);
     List<ComponentName> getActiveAdmins();
+    boolean packageHasActiveAdmins(String packageName);
     void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result);
     void removeActiveAdmin(in ComponentName policyReceiver);
     
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index ce5f1bf..99edfac 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1639,6 +1639,7 @@
             return;
         }
         Intent intent = new Intent(INTENT_ACTION_GLOBAL_SEARCH);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.setComponent(globalSearchActivity);
         // TODO: Always pass name of calling package as an extra?
         if (appSearchData != null) {
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
new file mode 100644
index 0000000..aca8ab4
--- /dev/null
+++ b/core/java/android/app/UiModeManager.java
@@ -0,0 +1,83 @@
+package android.app;
+
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+/**
+ * This class provides access to the system uimode services.  These services
+ * allow applications to control UI modes of the device.
+ * It provides functionality to disable the car mode and it gives access to the
+ * night mode settings.
+ *
+ * <p>You do not instantiate this class directly; instead, retrieve it through
+ * {@link android.content.Context#getSystemService
+ * Context.getSystemService(Context.UI_MODE_SERVICE)}.
+ */
+public class UiModeManager {
+    private static final String TAG = "UiModeManager";
+
+    public static final int MODE_NOTNIGHT = 1;
+    public static final int MODE_NIGHT = 2;
+    public static final int MODE_AUTO = 3;
+
+    private IUiModeManager mService;
+
+    /*package*/ UiModeManager() {
+        mService = IUiModeManager.Stub.asInterface(
+                ServiceManager.getService("uimode"));
+    }
+
+    /**
+     * Disables the car mode.
+     */
+    public void disableCarMode() {
+        if (mService != null) {
+            try {
+                mService.disableCarMode();
+            } catch (RemoteException e) {
+                Log.e(TAG, "disableCarMode: RemoteException", e);
+            }
+        }
+    }
+
+    /**
+     * Sets the night mode.  Changes to the night mode are only effective when
+     * the car mode is enabled on a device.
+     *
+     * <p>The mode can be one of:
+     * <ul>
+     *   <li><em>{@link #MODE_NOTNIGHT}<em> - sets the device into notnight
+     *       mode.</li>
+     *   <li><em>{@link #MODE_NIGHT}</em> - sets the device into night mode.
+     *   </li>
+     *   <li><em>{@link #MODE_AUTO}</em> - automatic night/notnight switching
+     *       depending on the location and certain other sensors.</li>
+     */
+    public void setNightMode(int mode) {
+        if (mService != null) {
+            try {
+                mService.setNightMode(mode);
+            } catch (RemoteException e) {
+                Log.e(TAG, "setNightMode: RemoteException", e);
+            }
+        }
+    }
+
+    /**
+     * Returns the currently configured night mode.
+     *
+     * @return {@link #MODE_NOTNIGHT}, {@link #MODE_NIGHT} or {@link #MODE_AUTO}
+     *         When an error occurred -1 is returned.
+     */
+    public int getNightMode() {
+        if (mService != null) {
+            try {
+                return mService.getNightMode();
+            } catch (RemoteException e) {
+                Log.e(TAG, "getNightMode: RemoteException", e);
+            }
+        }
+        return -1;
+    }
+}
diff --git a/core/java/android/content/ComponentName.java b/core/java/android/content/ComponentName.java
index c4ba05d..7ca0f01 100644
--- a/core/java/android/content/ComponentName.java
+++ b/core/java/android/content/ComponentName.java
@@ -126,7 +126,7 @@
     }
     
     /**
-     * The samee as {@link #flattenToString()}, but abbreviates the class
+     * The same as {@link #flattenToString()}, but abbreviates the class
      * name if it is a suffix of the package.  The result can still be used
      * with {@link #unflattenFromString(String)}.
      * 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 672e5f7..897d702 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1204,6 +1204,8 @@
      * <dt> {@link #INPUT_METHOD_SERVICE} ("input_method")
      * <dd> An {@link android.view.inputmethod.InputMethodManager InputMethodManager}
      * for management of input methods.
+     * <dt> {@link #UI_MODE_SERVICE} ("uimode")
+     * <dd> An {@link android.app.UiModeManager} for controlling UI modes.
      * </dl>
      * 
      * <p>Note:  System services obtained via this API may be closely associated with
@@ -1249,6 +1251,8 @@
      * @see android.telephony.TelephonyManager
      * @see #INPUT_METHOD_SERVICE
      * @see android.view.inputmethod.InputMethodManager
+     * @see #UI_MODE_SERVICE
+     * @see android.app.UiModeManager
      */
     public abstract Object getSystemService(String name);
 
@@ -1511,6 +1515,14 @@
     public static final String DEVICE_POLICY_SERVICE = "device_policy";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a
+     * {@link android.app.UiModeManager} for controlling UI modes.
+     *
+     * @see #getSystemService
+     */
+    public static final String UI_MODE_SERVICE = "uimode";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 1b0437c..607605d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1316,6 +1316,21 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
     /**
+     * @hide
+     * Broadcast Action: Ask system services if there is any reason to
+     * restart the given package.  The data contains the name of the
+     * package.
+     * <ul>
+     * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package.
+     * <li> {@link #EXTRA_PACKAGES} String array of all packages to check.
+     * </ul>
+     *
+     * <p class="note">This is a protected intent that can only be sent
+     * by the system.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
+    /**
      * Broadcast Action: The user has restarted a package, and all of its
      * processes have been killed.  All runtime state
      * associated with it (processes, alarms, notifications, etc) should
@@ -2098,6 +2113,7 @@
      * number to call in a {@link android.content.Intent#ACTION_CALL}.
      */
     public static final String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
+    
     /**
      * Used as an int extra field in {@link android.content.Intent#ACTION_UID_REMOVED}
      * intents to supply the uid the package had been assigned.  Also an optional
@@ -2108,6 +2124,11 @@
     public static final String EXTRA_UID = "android.intent.extra.UID";
 
     /**
+     * @hide String array of package names.
+     */
+    public static final String EXTRA_PACKAGES = "android.intent.extra.PACKAGES";
+
+    /**
      * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
      * intents to indicate whether this represents a full uninstall (removing
      * both the code and its data) or a partial uninstall (leaving its data,
diff --git a/core/java/android/database/sqlite/SQLiteCompiledSql.java b/core/java/android/database/sqlite/SQLiteCompiledSql.java
index eb85822..a7a1d9a 100644
--- a/core/java/android/database/sqlite/SQLiteCompiledSql.java
+++ b/core/java/android/database/sqlite/SQLiteCompiledSql.java
@@ -95,12 +95,16 @@
         }
     }
 
-    /* package */ synchronized boolean isInUse() {
-        return mInUse;
-    }
-
-    /* package */ synchronized void acquire() {
+    /**
+     * returns true if acquire() succeeds. false otherwise.
+     */
+    /* package */ synchronized boolean acquire() {
+        if (mInUse) {
+            // someone already has acquired it.
+            return false;
+        }
         mInUse = true;
+        return true;
     }
 
     /* package */ synchronized void release() {
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 2bb2f5d..a3a8486 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -61,16 +61,13 @@
             mCompiledSql.acquire();
         } else {
             // it is already in compiled-sql cache.
-            if (mCompiledSql.isInUse()) {
-                // but the CompiledSql in cache is in use by some other SQLiteProgram object.
+            // try to acquire the object.
+            if (!mCompiledSql.acquire()) {
+                // the SQLiteCompiledSql in cache is in use by some other SQLiteProgram object.
                 // we can't have two different SQLiteProgam objects can't share the same
                 // CompiledSql object. create a new one.
                 // finalize it when I am done with it in "this" object.
                 mCompiledSql = new SQLiteCompiledSql(db, sql);
-            } else {
-                // the CompiledSql in cache is NOT in use by any other SQLiteProgram object.
-                // it is safe to give it to this SQLIteProgram Object.
-                mCompiledSql.acquire();
             }
         }
         nStatement = mCompiledSql.nStatement;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index b706c5c..56a05ee 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -750,11 +750,8 @@
      * Checkin server version of dump to produce more compact, computer-readable log.
      * 
      * NOTE: all times are expressed in 'ms'.
-     * @param fd
-     * @param pw
-     * @param which
      */
-    private final void dumpCheckinLocked(PrintWriter pw, int which) {
+    public final void dumpCheckinLocked(PrintWriter pw, int which, int reqUid) {
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
         final long batteryUptime = getBatteryUptime(rawUptime);
@@ -856,19 +853,24 @@
                     getDischargeCurrentLevel());
         }
         
-        Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
-        if (kernelWakelocks.size() > 0) {
-            for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
-                sb.setLength(0);
-                printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
-
-                dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(), 
-                        sb.toString());
+        if (reqUid < 0) {
+            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
+            if (kernelWakelocks.size() > 0) {
+                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
+                    sb.setLength(0);
+                    printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
+    
+                    dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(), 
+                            sb.toString());
+                }
             }
         }
         
         for (int iu = 0; iu < NU; iu++) {
             final int uid = uidStats.keyAt(iu);
+            if (reqUid >= 0 && uid != reqUid) {
+                continue;
+            }
             Uid u = uidStats.valueAt(iu);
             // Dump Network stats per uid, if any
             long rx = u.getTcpBytesReceived(which);
@@ -987,7 +989,7 @@
     }
 
     @SuppressWarnings("unused")
-    private final void dumpLocked(PrintWriter pw, String prefix, int which) {
+    public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUid) {
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
         final long batteryUptime = getBatteryUptime(rawUptime);
@@ -1063,23 +1065,25 @@
         long fullWakeLockTimeTotalMicros = 0;
         long partialWakeLockTimeTotalMicros = 0;
         
-        Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
-        if (kernelWakelocks.size() > 0) {
-            for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
-                
-                String linePrefix = ": ";
-                sb.setLength(0);
-                sb.append(prefix);
-                sb.append("  Kernel Wake lock ");
-                sb.append(ent.getKey());
-                linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which, 
-                        linePrefix);
-                if (!linePrefix.equals(": ")) {
-                    sb.append(" realtime");
-                } else {
-                    sb.append(": (nothing executed)");
+        if (reqUid < 0) {
+            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
+            if (kernelWakelocks.size() > 0) {
+                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
+                    
+                    String linePrefix = ": ";
+                    sb.setLength(0);
+                    sb.append(prefix);
+                    sb.append("  Kernel Wake lock ");
+                    sb.append(ent.getKey());
+                    linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which, 
+                            linePrefix);
+                    if (!linePrefix.equals(": ")) {
+                        sb.append(" realtime");
+                    } else {
+                        sb.append(": (nothing executed)");
+                    }
+                    pw.println(sb.toString());
                 }
-                pw.println(sb.toString());
             }
         }
     
@@ -1212,7 +1216,12 @@
 
         for (int iu=0; iu<NU; iu++) {
             final int uid = uidStats.keyAt(iu);
+            if (reqUid >= 0 && uid != reqUid) {
+                continue;
+            }
+            
             Uid u = uidStats.valueAt(iu);
+            
             pw.println(prefix + "  #" + uid + ":");
             boolean uidActivity = false;
             
@@ -1421,16 +1430,16 @@
         pw.println("Total Statistics (Current and Historic):");
         pw.println("  System starts: " + getStartCount()
                 + ", currently on battery: " + getIsOnBattery());
-        dumpLocked(pw, "", STATS_TOTAL);
+        dumpLocked(pw, "", STATS_TOTAL, -1);
         pw.println("");
         pw.println("Last Run Statistics (Previous run of system):");
-        dumpLocked(pw, "", STATS_LAST);
+        dumpLocked(pw, "", STATS_LAST, -1);
         pw.println("");
         pw.println("Current Battery Statistics (Currently running system):");
-        dumpLocked(pw, "", STATS_CURRENT);
+        dumpLocked(pw, "", STATS_CURRENT, -1);
         pw.println("");
         pw.println("Unplugged Statistics (Since last unplugged from power):");
-        dumpLocked(pw, "", STATS_UNPLUGGED);
+        dumpLocked(pw, "", STATS_UNPLUGGED, -1);
     }
     
     @SuppressWarnings("unused")
@@ -1445,13 +1454,13 @@
         }
         
         if (isUnpluggedOnly) {
-            dumpCheckinLocked(pw, STATS_UNPLUGGED);
+            dumpCheckinLocked(pw, STATS_UNPLUGGED, -1);
         }
         else {
-            dumpCheckinLocked(pw, STATS_TOTAL);
-            dumpCheckinLocked(pw, STATS_LAST);
-            dumpCheckinLocked(pw, STATS_UNPLUGGED);
-            dumpCheckinLocked(pw, STATS_CURRENT);
+            dumpCheckinLocked(pw, STATS_TOTAL, -1);
+            dumpCheckinLocked(pw, STATS_LAST, -1);
+            dumpCheckinLocked(pw, STATS_UNPLUGGED, -1);
+            dumpCheckinLocked(pw, STATS_CURRENT, -1);
         }
     }
     
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index a79bbee..17d5bb7 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1960,7 +1960,6 @@
             if (getHeight() > 0 && getChildCount() > 0) {
                 // We do not lose focus initiating a touch (since AbsListView is focusable in
                 // touch mode). Force an initial layout to get rid of the selection.
-                mLayoutMode = LAYOUT_NORMAL;
                 layoutChildren();
             }
         } else {
@@ -3118,7 +3117,9 @@
 
     void hideSelector() {
         if (mSelectedPosition != INVALID_POSITION) {
-            mResurrectToPosition = mSelectedPosition;
+            if (mLayoutMode != LAYOUT_SPECIFIC) {
+                mResurrectToPosition = mSelectedPosition;
+            }
             if (mNextSelectedPosition >= 0 && mNextSelectedPosition != mSelectedPosition) {
                 mResurrectToPosition = mNextSelectedPosition;
             }
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
new file mode 100644
index 0000000..343041f
--- /dev/null
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -0,0 +1,287 @@
+package com.android.internal.content;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+
+import java.util.HashSet;
+
+/**
+ * Helper class for monitoring the state of packages: adding, removing,
+ * updating, and disappearing and reappearing on the SD card.
+ */
+public abstract class PackageMonitor extends android.content.BroadcastReceiver {
+    static final IntentFilter sPackageFilt = new IntentFilter();
+    static final IntentFilter sNonDataFilt = new IntentFilter();
+    static final IntentFilter sExternalFilt = new IntentFilter();
+    
+    static {
+        sPackageFilt.addAction(Intent.ACTION_PACKAGE_ADDED);
+        sPackageFilt.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        sPackageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        sPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
+        sPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+        sPackageFilt.addAction(Intent.ACTION_UID_REMOVED);
+        sPackageFilt.addDataScheme("package");
+        sNonDataFilt.addAction(Intent.ACTION_UID_REMOVED);
+        sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+        sExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+    }
+    
+    final HashSet<String> mUpdatingPackages = new HashSet<String>();
+    
+    Context mRegisteredContext;
+    String[] mDisappearingPackages;
+    String[] mAppearingPackages;
+    String[] mModifiedPackages;
+    int mChangeType;
+    boolean mSomePackagesChanged;
+    
+    String[] mTempArray = new String[1];
+    
+    public void register(Context context, boolean externalStorage) {
+        if (mRegisteredContext != null) {
+            throw new IllegalStateException("Already registered");
+        }
+        mRegisteredContext = context;
+        context.registerReceiver(this, sPackageFilt);
+        context.registerReceiver(this, sNonDataFilt);
+        if (externalStorage) {
+            context.registerReceiver(this, sExternalFilt);
+        }
+    }
+    
+    public void unregister() {
+        if (mRegisteredContext == null) {
+            throw new IllegalStateException("Not registered");
+        }
+        mRegisteredContext.unregisterReceiver(this);
+        mRegisteredContext = null;
+    }
+    
+    //not yet implemented
+    boolean isPackageUpdating(String packageName) {
+        synchronized (mUpdatingPackages) {
+            return mUpdatingPackages.contains(packageName);
+        }
+    }
+    
+    public void onBeginPackageChanges() {
+    }
+    
+    public void onPackageAdded(String packageName, int uid) {
+    }
+    
+    public void onPackageRemoved(String packageName, int uid) {
+    }
+    
+    public void onPackageUpdateStarted(String packageName, int uid) {
+    }
+    
+    public void onPackageUpdateFinished(String packageName, int uid) {
+    }
+    
+    public void onPackageChanged(String packageName, int uid, String[] components) {
+    }
+    
+    public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
+        return false;
+    }
+    
+    public void onUidRemoved(int uid) {
+    }
+    
+    public void onPackagesAvailable(String[] packages) {
+    }
+    
+    public void onPackagesUnavailable(String[] packages) {
+    }
+    
+    public static final int PACKAGE_UNCHANGED = 0;
+    public static final int PACKAGE_UPDATING = 1;
+    public static final int PACKAGE_TEMPORARY_CHANGE = 2;
+    public static final int PACKAGE_PERMANENT_CHANGE = 3;
+    
+    public void onPackageDisappeared(String packageName, int reason) {
+    }
+    
+    public void onPackageAppeared(String packageName, int reason) {
+    }
+    
+    public void onPackageModified(String packageName) {
+    }
+    
+    public boolean didSomePackagesChange() {
+        return mSomePackagesChanged;
+    }
+    
+    public int isPackageAppearing(String packageName) {
+        if (mAppearingPackages != null) {
+            for (int i=mAppearingPackages.length-1; i>=0; i--) {
+                if (packageName.equals(mAppearingPackages[i])) {
+                    return mChangeType;
+                }
+            }
+        }
+        return PACKAGE_UNCHANGED;
+    }
+    
+    public boolean anyPackagesAppearing() {
+        return mAppearingPackages != null;
+    }
+    
+    public int isPackageDisappearing(String packageName) {
+        if (mDisappearingPackages != null) {
+            for (int i=mDisappearingPackages.length-1; i>=0; i--) {
+                if (packageName.equals(mDisappearingPackages[i])) {
+                    return mChangeType;
+                }
+            }
+        }
+        return PACKAGE_UNCHANGED;
+    }
+    
+    public boolean anyPackagesDisappearing() {
+        return mDisappearingPackages != null;
+    }
+    
+    public boolean isPackageModified(String packageName) {
+        if (mModifiedPackages != null) {
+            for (int i=mModifiedPackages.length-1; i>=0; i--) {
+                if (packageName.equals(mModifiedPackages[i])) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    
+    public void onSomePackagesChanged() {
+    }
+    
+    public void onFinishPackageChanges() {
+    }
+    
+    String getPackageName(Intent intent) {
+        Uri uri = intent.getData();
+        String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
+        return pkg;
+    }
+    
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        onBeginPackageChanges();
+        
+        mDisappearingPackages = mAppearingPackages = null;
+        mSomePackagesChanged = false;
+        
+        String action = intent.getAction();
+        if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+            String pkg = getPackageName(intent);
+            int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
+            // We consider something to have changed regardless of whether
+            // this is just an update, because the update is now finished
+            // and the contents of the package may have changed.
+            mSomePackagesChanged = true;
+            if (pkg != null) {
+                mAppearingPackages = mTempArray;
+                mTempArray[0] = pkg;
+                if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                    mModifiedPackages = mTempArray;
+                    mChangeType = PACKAGE_UPDATING;
+                    onPackageUpdateFinished(pkg, uid);
+                    onPackageModified(pkg);
+                } else {
+                    mChangeType = PACKAGE_PERMANENT_CHANGE;
+                    onPackageAdded(pkg, uid);
+                }
+                onPackageAppeared(pkg, mChangeType);
+                if (mChangeType == PACKAGE_UPDATING) {
+                    synchronized (mUpdatingPackages) {
+                        mUpdatingPackages.remove(pkg);
+                    }
+                }
+            }
+        } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+            String pkg = getPackageName(intent);
+            int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
+            if (pkg != null) {
+                mDisappearingPackages = mTempArray;
+                mTempArray[0] = pkg;
+                if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                    mChangeType = PACKAGE_UPDATING;
+                    synchronized (mUpdatingPackages) {
+                        //not used for now
+                        //mUpdatingPackages.add(pkg);
+                    }
+                    onPackageUpdateStarted(pkg, uid);
+                } else {
+                    mChangeType = PACKAGE_PERMANENT_CHANGE;
+                    // We only consider something to have changed if this is
+                    // not a replace; for a replace, we just need to consider
+                    // it when it is re-added.
+                    mSomePackagesChanged = true;
+                    onPackageRemoved(pkg, uid);
+                }
+                onPackageDisappeared(pkg, mChangeType);
+            }
+        } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
+            String pkg = getPackageName(intent);
+            int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
+            String[] components = intent.getStringArrayExtra(
+                    Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+            if (pkg != null) {
+                mModifiedPackages = mTempArray;
+                mTempArray[0] = pkg;
+                onPackageChanged(pkg, uid, components);
+                // XXX Don't want this to always cause mSomePackagesChanged,
+                // since it can happen a fair amount.
+                onPackageModified(pkg);
+            }
+        } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
+            mDisappearingPackages = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
+            mChangeType = PACKAGE_TEMPORARY_CHANGE;
+            boolean canRestart = onHandleForceStop(intent,
+                    mDisappearingPackages,
+                    intent.getIntExtra(Intent.EXTRA_UID, 0), false);
+            if (canRestart) setResultCode(Activity.RESULT_OK);
+        } else if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
+            mDisappearingPackages = new String[] {getPackageName(intent)};
+            mChangeType = PACKAGE_TEMPORARY_CHANGE;
+            onHandleForceStop(intent, mDisappearingPackages,
+                    intent.getIntExtra(Intent.EXTRA_UID, 0), true);
+        } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
+            onUidRemoved(intent.getIntExtra(Intent.EXTRA_UID, 0));
+        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
+            String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+            mAppearingPackages = pkgList;
+            mChangeType = PACKAGE_TEMPORARY_CHANGE;
+            mSomePackagesChanged = true;
+            if (pkgList != null) {
+                onPackagesAvailable(pkgList);
+                for (int i=0; i<pkgList.length; i++) {
+                    onPackageAppeared(pkgList[i], PACKAGE_TEMPORARY_CHANGE);
+                }
+            }
+        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
+            String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+            mDisappearingPackages = pkgList;
+            mChangeType = PACKAGE_TEMPORARY_CHANGE;
+            mSomePackagesChanged = true;
+            if (pkgList != null) {
+                onPackagesUnavailable(pkgList);
+                for (int i=0; i<pkgList.length; i++) {
+                    onPackageDisappeared(pkgList[i], PACKAGE_TEMPORARY_CHANGE);
+                }
+            }
+        }
+        
+        if (mSomePackagesChanged) {
+            onSomePackagesChanged();
+        }
+        
+        onFinishPackageChanges();
+    }
+}
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index c5dfbb5..3f9c6d6 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -709,7 +709,9 @@
 
 bool AudioSystem::isLowVisibility(stream_type stream)
 {
-    if (stream == AudioSystem::SYSTEM || stream == AudioSystem::NOTIFICATION) {
+    if (stream == AudioSystem::SYSTEM ||
+        stream == AudioSystem::NOTIFICATION ||
+        stream == AudioSystem::RING) {
         return true;
     } else {
         return false;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index cf34d4e..5b616b3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -618,18 +618,9 @@
 
        if (upgradeVersion == 48) {
            /*
-            * Adding a new setting for which voice recognition service to use.
+            * Default recognition service no longer initialized here,
+            * moved to RecognitionManagerService.
             */
-           db.beginTransaction();
-           try {
-               SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
-                       + " VALUES(?,?);");
-               loadVoiceRecognitionServiceSetting(stmt);
-               stmt.close();
-               db.setTransactionSuccessful();
-           } finally {
-               db.endTransaction();
-           }
            upgradeVersion = 49;
        }
 
@@ -1028,8 +1019,6 @@
         loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED,
                 R.bool.def_mount_ums_notify_enabled);
 
-        loadVoiceRecognitionServiceSetting(stmt);
-
         stmt.close();
     }
 
@@ -1041,32 +1030,6 @@
                 R.string.def_backup_transport);
     }
 
-    /**
-     * Introduced in database version 49.
-     */
-    private void loadVoiceRecognitionServiceSetting(SQLiteStatement stmt) {
-        String selectedService = null;
-        List<ResolveInfo> availableRecognitionServices =
-                mContext.getPackageManager().queryIntentServices(
-                        new Intent(RecognitionService.SERVICE_INTERFACE), 0);
-        int numAvailable = availableRecognitionServices.size();
-
-        if (numAvailable == 0) {
-            Log.w(TAG, "no available voice recognition services found");
-        } else {
-            if (numAvailable > 1) {
-                Log.w(TAG, "more than one voice recognition service found, picking first");
-            }
-
-            ServiceInfo serviceInfo = availableRecognitionServices.get(0).serviceInfo;
-            selectedService =
-                    new ComponentName(serviceInfo.packageName, serviceInfo.name).flattenToString();
-        }
-
-        loadSetting(stmt, Settings.Secure.VOICE_RECOGNITION_SERVICE,
-                selectedService == null ? "" : selectedService);
-    }
-
     private void loadSetting(SQLiteStatement stmt, String key, Object value) {
         stmt.bindString(1, key);
         stmt.bindString(2, value.toString());
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 4080a6a..db802d3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -20,7 +20,6 @@
 import java.io.UnsupportedEncodingException;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
-import java.util.Random;
 
 import android.backup.BackupManager;
 import android.content.ContentProvider;
@@ -30,14 +29,11 @@
 import android.content.pm.PackageManager;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
-import android.database.SQLException;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteQueryBuilder;
-import android.media.Ringtone;
 import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
-import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.provider.DrmStore;
 import android.provider.MediaStore;
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index 477ea0c..c55dcb3 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.HandlerCaller.SomeArgs;
 
@@ -56,6 +57,7 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -145,13 +147,58 @@
     private void registerPackageChangeAndBootCompletedBroadcastReceiver() {
         Context context = mContext;
 
-        BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
+        PackageMonitor monitor = new PackageMonitor() {
             @Override
-            public void onReceive(Context context, Intent intent) {
+            public void onSomePackagesChanged() {
                 synchronized (mLock) {
                     populateAccessibilityServiceListLocked();
+                    manageServicesLocked();
+                }
+            }
+            
+            @Override
+            public boolean onHandleForceStop(Intent intent, String[] packages,
+                    int uid, boolean doit) {
+                synchronized (mLock) {
+                    boolean changed = false;
+                    Iterator<ComponentName> it = mEnabledServices.iterator();
+                    while (it.hasNext()) {
+                        ComponentName comp = it.next();
+                        String compPkg = comp.getPackageName();
+                        for (String pkg : packages) {
+                            if (compPkg.equals(pkg)) {
+                                if (!doit) {
+                                    return true;
+                                }
+                                it.remove();
+                                changed = true;
+                            }
+                        }
+                    }
+                    if (changed) {
+                        it = mEnabledServices.iterator();
+                        StringBuilder str = new StringBuilder();
+                        while (it.hasNext()) {
+                            if (str.length() > 0) {
+                                str.append(':');
+                            }
+                            str.append(it.next().flattenToShortString());
+                        }
+                        Settings.Secure.putString(mContext.getContentResolver(),
+                                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                                str.toString());
+                        manageServicesLocked();
+                    }
+                    return false;
+                }
+            }
+            
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (intent.getAction() == Intent.ACTION_BOOT_COMPLETED) {
+                    synchronized (mLock) {
+                        populateAccessibilityServiceListLocked();
 
-                    if (intent.getAction() == Intent.ACTION_BOOT_COMPLETED) {
                         // get the accessibility enabled setting on boot
                         mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
                                 Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
@@ -160,29 +207,23 @@
                         if (mIsEnabled) {
                             updateClientsLocked();
                         }
-                    }
 
-                    manageServicesLocked();
+                        manageServicesLocked();
+                    }
+                    
+                    return;
                 }
+                
+                super.onReceive(context, intent);
             }
         };
 
         // package changes
-        IntentFilter packageFilter = new IntentFilter();
-        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
-        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        packageFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
-        packageFilter.addDataScheme("package");
-        context.registerReceiver(broadcastReceiver, packageFilter);
-        // Register for events related to sdcard installation.
-        IntentFilter sdFilter = new IntentFilter();
-        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
-        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
-        mContext.registerReceiver(broadcastReceiver, sdFilter);
+        monitor.register(context, true);
 
         // boot completed
         IntentFilter bootFiler = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
-        mContext.registerReceiver(broadcastReceiver, bootFiler);
+        mContext.registerReceiver(monitor, bootFiler);
     }
 
     /**
@@ -529,8 +570,14 @@
             TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
             splitter.setString(servicesValue);
             while (splitter.hasNext()) {
-                ComponentName enabledService = ComponentName.unflattenFromString(splitter.next());
-                enabledServices.add(enabledService);
+                String str = splitter.next();
+                if (str == null || str.length() <= 0) {
+                    continue;
+                }
+                ComponentName enabledService = ComponentName.unflattenFromString(str);
+                if (enabledService != null) {
+                    enabledServices.add(enabledService);
+                }
             }
         }
     }
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 44cc0bb..f480209 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.app.Activity;
 import android.app.ActivityManagerNative;
 import android.app.AlarmManager;
 import android.app.IAlarmManager;
@@ -344,6 +345,22 @@
         }
     }
     
+    public boolean lookForPackageLocked(String packageName) {
+        return lookForPackageLocked(mRtcWakeupAlarms, packageName)
+                || lookForPackageLocked(mRtcAlarms, packageName)
+                || lookForPackageLocked(mElapsedRealtimeWakeupAlarms, packageName)
+                || lookForPackageLocked(mElapsedRealtimeAlarms, packageName);
+    }
+
+    private boolean lookForPackageLocked(ArrayList<Alarm> alarmList, String packageName) {
+        for (int i=alarmList.size()-1; i>=0; i--) {
+            if (alarmList.get(i).operation.getTargetPackage().equals(packageName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
     private ArrayList<Alarm> getAlarmList(int type) {
         switch (type) {
             case AlarmManager.RTC_WAKEUP:              return mRtcWakeupAlarms;
@@ -778,6 +795,7 @@
             IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
             filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+            filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
             filter.addDataScheme("package");
             mContext.registerReceiver(this, filter);
              // Register for events related to sdcard installation.
@@ -791,7 +809,16 @@
             synchronized (mLock) {
                 String action = intent.getAction();
                 String pkgList[] = null;
-                if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
+                if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
+                    pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
+                    for (String packageName : pkgList) {
+                        if (lookForPackageLocked(packageName)) {
+                            setResultCode(Activity.RESULT_OK);
+                            return;
+                        }
+                    }
+                    return;
+                } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                 } else {
                     Uri data = intent.getData();
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index a267e0f..ac65aa9 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -17,6 +17,8 @@
 package com.android.server;
 
 import com.android.common.FastXmlSerializer;
+import com.android.common.XmlUtils;
+import com.android.internal.content.PackageMonitor;
 import com.android.internal.widget.LockPatternUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -34,6 +36,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.IPowerManager;
@@ -58,9 +61,10 @@
  * Implementation of the device policy APIs.
  */
 public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
-    private static final String TAG = "DevicePolicyManagerService";
+    static final String TAG = "DevicePolicyManagerService";
     
-    private final Context mContext;
+    final Context mContext;
+    final MyPackageMonitor mMonitor;
 
     IPowerManager mIPowerManager;
     
@@ -89,6 +93,9 @@
         
         void writeToXml(XmlSerializer out)
                 throws IllegalArgumentException, IllegalStateException, IOException {
+            out.startTag(null, "policies");
+            info.writePoliciesToXml(out);
+            out.endTag(null, "policies");
             if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
                 out.startTag(null, "password-quality");
                 out.attribute(null, "value", Integer.toString(passwordQuality));
@@ -121,7 +128,9 @@
                     continue;
                 }
                 String tag = parser.getName();
-                if ("password-quality".equals(tag)) {
+                if ("policies".equals(tag)) {
+                    info.readPoliciesFromXml(parser);
+                } else if ("password-quality".equals(tag)) {
                     passwordQuality = Integer.parseInt(
                             parser.getAttributeValue(null, "value"));
                 } else if ("min-password-length".equals(tag)) {
@@ -133,6 +142,35 @@
                 } else if ("max-failed-password-wipe".equals(tag)) {
                     maximumFailedPasswordsForWipe = Integer.parseInt(
                             parser.getAttributeValue(null, "value"));
+                } else {
+                    Log.w(TAG, "Unknown admin tag: " + tag);
+                }
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+    
+    class MyPackageMonitor extends PackageMonitor {
+        public void onSomePackagesChanged() {
+            synchronized (DevicePolicyManagerService.this) {
+                for (int i=mAdminList.size()-1; i>=0; i--) {
+                    ActiveAdmin aa = mAdminList.get(i);
+                    int change = isPackageDisappearing(aa.info.getPackageName()); 
+                    if (change == PACKAGE_PERMANENT_CHANGE
+                            || change == PACKAGE_TEMPORARY_CHANGE) {
+                        Log.w(TAG, "Admin unexpectedly uninstalled: "
+                                + aa.info.getComponent());
+                        mAdminList.remove(i);
+                    } else if (isPackageModified(aa.info.getPackageName())) {
+                        try {
+                            mContext.getPackageManager().getReceiverInfo(
+                                    aa.info.getComponent(), 0);
+                        } catch (NameNotFoundException e) {
+                            Log.w(TAG, "Admin package change removed component: "
+                                    + aa.info.getComponent());
+                            mAdminList.remove(i);
+                        }
+                    }
                 }
             }
         }
@@ -143,6 +181,8 @@
      */
     public DevicePolicyManagerService(Context context) {
         mContext = context;
+        mMonitor = new MyPackageMonitor();
+        mMonitor.register(context, true);
     }
 
     private IPowerManager getIPowerManager() {
@@ -336,6 +376,10 @@
                 } else if ("failed-password-attempts".equals(tag)) {
                     mFailedPasswordAttempts = Integer.parseInt(
                             parser.getAttributeValue(null, "value"));
+                    XmlUtils.skipCurrentTag(parser);
+                } else {
+                    Log.w(TAG, "Unknown tag: " + tag);
+                    XmlUtils.skipCurrentTag(parser);
                 }
             }
         } catch (NullPointerException e) {
@@ -420,6 +464,18 @@
         }
     }
     
+    public boolean packageHasActiveAdmins(String packageName) {
+        synchronized (this) {
+            final int N = mAdminList.size();
+            for (int i=0; i<N; i++) {
+                if (mAdminList.get(i).info.getPackageName().equals(packageName)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+    
     public void removeActiveAdmin(ComponentName adminReceiver) {
         synchronized (this) {
             ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 4791718..606b589 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -41,6 +41,7 @@
 import android.location.LocationManager;
 import android.location.LocationProvider;
 import android.os.Binder;
+import android.media.AudioManager;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
 import android.net.Uri;
@@ -379,7 +380,10 @@
                                     final Uri soundUri = Uri.parse("file://" + soundPath);
                                     if (soundUri != null) {
                                         final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
-                                        if (sfx != null) sfx.play();
+                                        if (sfx != null) {
+                                            sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+                                            sfx.play();
+                                        }
                                     }
                                 }
                             }
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 5e96a2f..59d4c9b 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethod;
@@ -48,7 +49,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.database.ContentObserver;
-import android.net.Uri;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -332,51 +332,68 @@
         }
     }
 
-    class PackageReceiver extends android.content.BroadcastReceiver {
+    class MyPackageMonitor extends PackageMonitor {
+        
         @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            String pkgList[] = null;
-            if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
-                    Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
-                Uri uri = intent.getData();
-                String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
-                if (pkg != null) {
-                    pkgList = new String[] { pkg };
-                }
-            } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action) ||
-                    Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
-                pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
-            }
-            if (pkgList == null || pkgList.length == 0) {
-                return;
-            }
+        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
             synchronized (mMethodMap) {
-                buildInputMethodListLocked(mMethodList, mMethodMap);
-
-                InputMethodInfo curIm = null;
-                String curInputMethodId = Settings.Secure.getString(context
+                String curInputMethodId = Settings.Secure.getString(mContext
                         .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
                 final int N = mMethodList.size();
                 if (curInputMethodId != null) {
                     for (int i=0; i<N; i++) {
-                        if (mMethodList.get(i).getId().equals(curInputMethodId)) {
-                            curIm = mMethodList.get(i);
+                        InputMethodInfo imi = mMethodList.get(i);
+                        if (imi.getId().equals(curInputMethodId)) {
+                            for (String pkg : packages) {
+                                if (imi.getPackageName().equals(pkg)) {
+                                    if (!doit) {
+                                        return true;
+                                    }
+                                    
+                                    Settings.Secure.putString(mContext.getContentResolver(),
+                                            Settings.Secure.DEFAULT_INPUT_METHOD, "");
+                                    chooseNewDefaultIMELocked();
+                                    return true;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public void onSomePackagesChanged() {
+            synchronized (mMethodMap) {
+                InputMethodInfo curIm = null;
+                String curInputMethodId = Settings.Secure.getString(mContext
+                        .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+                final int N = mMethodList.size();
+                if (curInputMethodId != null) {
+                    for (int i=0; i<N; i++) {
+                        InputMethodInfo imi = mMethodList.get(i);
+                        if (imi.getId().equals(curInputMethodId)) {
+                            curIm = imi;
+                        }
+                        int change = isPackageDisappearing(imi.getPackageName());
+                        if (change == PACKAGE_TEMPORARY_CHANGE
+                                || change == PACKAGE_PERMANENT_CHANGE) {
+                            Log.i(TAG, "Input method uninstalled, disabling: "
+                                    + imi.getComponent());
+                            setInputMethodEnabledLocked(imi.getId(), false);
                         }
                     }
                 }
 
+                buildInputMethodListLocked(mMethodList, mMethodMap);
+
                 boolean changed = false;
 
                 if (curIm != null) {
-                    boolean foundPkg = false;
-                    for (String pkg : pkgList) {
-                        if (curIm.getPackageName().equals(pkg)) {
-                            foundPkg = true;
-                            break;
-                        }
-                    }
-                    if (foundPkg) {
+                    int change = isPackageDisappearing(curIm.getPackageName()); 
+                    if (change == PACKAGE_TEMPORARY_CHANGE
+                            || change == PACKAGE_PERMANENT_CHANGE) {
                         ServiceInfo si = null;
                         try {
                             si = mContext.getPackageManager().getServiceInfo(
@@ -387,7 +404,7 @@
                             // Uh oh, current input method is no longer around!
                             // Pick another one...
                             Log.i(TAG, "Current input method removed: " + curInputMethodId);
-                            if (!chooseNewDefaultIME()) {
+                            if (!chooseNewDefaultIMELocked()) {
                                 changed = true;
                                 curIm = null;
                                 curInputMethodId = "";
@@ -397,16 +414,17 @@
                                         curInputMethodId);
                             }
                         }
-
-                    } else if (curIm == null) {
-                        // We currently don't have a default input method... is
-                        // one now available?
-                        changed = chooseNewDefaultIME();
                     }
+                }
+                
+                if (curIm == null) {
+                    // We currently don't have a default input method... is
+                    // one now available?
+                    changed = chooseNewDefaultIMELocked();
+                }
 
-                    if (changed) {
-                        updateFromSettingsLocked();
-                    }
+                if (changed) {
+                    updateFromSettingsLocked();
                 }
             }
         }
@@ -438,19 +456,7 @@
             }
         });
 
-        PackageReceiver mBroadcastReceiver = new PackageReceiver();
-        IntentFilter packageFilt = new IntentFilter();
-        packageFilt.addAction(Intent.ACTION_PACKAGE_ADDED);
-        packageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        packageFilt.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        packageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED);
-        packageFilt.addDataScheme("package");
-        mContext.registerReceiver(mBroadcastReceiver, packageFilt);
-        // Register for events related to sdcard installation.
-        IntentFilter sdFilter = new IntentFilter();
-        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
-        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
-        mContext.registerReceiver(mBroadcastReceiver, sdFilter);
+        (new MyPackageMonitor()).register(mContext, true);
 
         IntentFilter screenOnOffFilt = new IntentFilter();
         screenOnOffFilt.addAction(Intent.ACTION_SCREEN_ON);
@@ -1385,7 +1391,7 @@
                 & ApplicationInfo.FLAG_SYSTEM) != 0;
     }
 
-    private boolean chooseNewDefaultIME() {
+    private boolean chooseNewDefaultIMELocked() {
         List<InputMethodInfo> enabled = getEnabledInputMethodListLocked();
         if (enabled != null && enabled.size() > 0) {
             Settings.Secure.putString(mContext.getContentResolver(),
@@ -1446,7 +1452,7 @@
         String defaultIme = Settings.Secure.getString(mContext
                 .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
         if (!map.containsKey(defaultIme)) {
-            if (chooseNewDefaultIME()) {
+            if (chooseNewDefaultIMELocked()) {
                 updateFromSettingsLocked();
             }
         }
@@ -1557,91 +1563,95 @@
                         "Requires permission "
                         + android.Manifest.permission.WRITE_SECURE_SETTINGS);
             }
-
+            
             long ident = Binder.clearCallingIdentity();
             try {
-                // Make sure this is a valid input method.
-                InputMethodInfo imm = mMethodMap.get(id);
-                if (imm == null) {
-                    if (imm == null) {
-                        throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
-                    }
-                }
-
-                StringBuilder builder = new StringBuilder(256);
-
-                boolean removed = false;
-                String firstId = null;
-
-                // Look through the currently enabled input methods.
-                String enabledStr = Settings.Secure.getString(mContext.getContentResolver(),
-                        Settings.Secure.ENABLED_INPUT_METHODS);
-                if (enabledStr != null) {
-                    final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
-                    splitter.setString(enabledStr);
-                    while (splitter.hasNext()) {
-                        String curId = splitter.next();
-                        if (curId.equals(id)) {
-                            if (enabled) {
-                                // We are enabling this input method, but it is
-                                // already enabled.  Nothing to do.  The previous
-                                // state was enabled.
-                                return true;
-                            }
-                            // We are disabling this input method, and it is
-                            // currently enabled.  Skip it to remove from the
-                            // new list.
-                            removed = true;
-                        } else if (!enabled) {
-                            // We are building a new list of input methods that
-                            // doesn't contain the given one.
-                            if (firstId == null) firstId = curId;
-                            if (builder.length() > 0) builder.append(':');
-                            builder.append(curId);
-                        }
-                    }
-                }
-
-                if (!enabled) {
-                    if (!removed) {
-                        // We are disabling the input method but it is already
-                        // disabled.  Nothing to do.  The previous state was
-                        // disabled.
-                        return false;
-                    }
-                    // Update the setting with the new list of input methods.
-                    Settings.Secure.putString(mContext.getContentResolver(),
-                            Settings.Secure.ENABLED_INPUT_METHODS, builder.toString());
-                    // We the disabled input method is currently selected, switch
-                    // to another one.
-                    String selId = Settings.Secure.getString(mContext.getContentResolver(),
-                            Settings.Secure.DEFAULT_INPUT_METHOD);
-                    if (id.equals(selId)) {
-                        Settings.Secure.putString(mContext.getContentResolver(),
-                                Settings.Secure.DEFAULT_INPUT_METHOD,
-                                firstId != null ? firstId : "");
-                    }
-                    // Previous state was enabled.
-                    return true;
-                }
-
-                // Add in the newly enabled input method.
-                if (enabledStr == null || enabledStr.length() == 0) {
-                    enabledStr = id;
-                } else {
-                    enabledStr = enabledStr + ':' + id;
-                }
-
-                Settings.Secure.putString(mContext.getContentResolver(),
-                        Settings.Secure.ENABLED_INPUT_METHODS, enabledStr);
-
-                // Previous state was disabled.
-                return false;
+                return setInputMethodEnabledLocked(id, enabled);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
         }
     }
+    
+    boolean setInputMethodEnabledLocked(String id, boolean enabled) {
+        // Make sure this is a valid input method.
+        InputMethodInfo imm = mMethodMap.get(id);
+        if (imm == null) {
+            if (imm == null) {
+                throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
+            }
+        }
+
+        StringBuilder builder = new StringBuilder(256);
+
+        boolean removed = false;
+        String firstId = null;
+
+        // Look through the currently enabled input methods.
+        String enabledStr = Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.ENABLED_INPUT_METHODS);
+        if (enabledStr != null) {
+            final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
+            splitter.setString(enabledStr);
+            while (splitter.hasNext()) {
+                String curId = splitter.next();
+                if (curId.equals(id)) {
+                    if (enabled) {
+                        // We are enabling this input method, but it is
+                        // already enabled.  Nothing to do.  The previous
+                        // state was enabled.
+                        return true;
+                    }
+                    // We are disabling this input method, and it is
+                    // currently enabled.  Skip it to remove from the
+                    // new list.
+                    removed = true;
+                } else if (!enabled) {
+                    // We are building a new list of input methods that
+                    // doesn't contain the given one.
+                    if (firstId == null) firstId = curId;
+                    if (builder.length() > 0) builder.append(':');
+                    builder.append(curId);
+                }
+            }
+        }
+
+        if (!enabled) {
+            if (!removed) {
+                // We are disabling the input method but it is already
+                // disabled.  Nothing to do.  The previous state was
+                // disabled.
+                return false;
+            }
+            // Update the setting with the new list of input methods.
+            Settings.Secure.putString(mContext.getContentResolver(),
+                    Settings.Secure.ENABLED_INPUT_METHODS, builder.toString());
+            // We the disabled input method is currently selected, switch
+            // to another one.
+            String selId = Settings.Secure.getString(mContext.getContentResolver(),
+                    Settings.Secure.DEFAULT_INPUT_METHOD);
+            if (id.equals(selId)) {
+                Settings.Secure.putString(mContext.getContentResolver(),
+                        Settings.Secure.DEFAULT_INPUT_METHOD,
+                        firstId != null ? firstId : "");
+            }
+            // Previous state was enabled.
+            return true;
+        }
+
+        // Add in the newly enabled input method.
+        if (enabledStr == null || enabledStr.length() == 0) {
+            enabledStr = id;
+        } else {
+            enabledStr = enabledStr + ':' + id;
+        }
+
+        Settings.Secure.putString(mContext.getContentResolver(),
+                Settings.Secure.ENABLED_INPUT_METHODS, enabledStr);
+
+        // Previous state was disabled.
+        return false;
+    }
 
     // ----------------------------------------------------------------------
 
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 004fcf13..dd351be 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -27,6 +27,7 @@
 import java.util.Observer;
 import java.util.Set;
 
+import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -506,6 +507,7 @@
         // Register for Package Manager updates
         intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+        intentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
         mContext.registerReceiver(mBroadcastReceiver, intentFilter);
         IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
         mContext.registerReceiver(mBroadcastReceiver, sdFilter);
@@ -1539,8 +1541,9 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
-
-            if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
+            boolean queryRestart = action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART);
+            if (queryRestart
+                    || action.equals(Intent.ACTION_PACKAGE_REMOVED)
                     || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
                     || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
                 synchronized (mLock) {
@@ -1560,6 +1563,10 @@
                                 for (int j=i.size()-1; j>=0; j--) {
                                     UpdateRecord ur = i.get(j);
                                     if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) {
+                                        if (queryRestart) {
+                                            setResultCode(Activity.RESULT_OK);
+                                            return;
+                                        }
                                         if (removedRecs == null) {
                                             removedRecs = new ArrayList<Receiver>();
                                         }
@@ -1572,6 +1579,10 @@
                             ArrayList<ProximityAlert> removedAlerts = null;
                             for (ProximityAlert i : mProximityAlerts.values()) {
                                 if (i.mUid == uid) {
+                                    if (queryRestart) {
+                                        setResultCode(Activity.RESULT_OK);
+                                        return;
+                                    }
                                     if (removedAlerts == null) {
                                         removedAlerts = new ArrayList<ProximityAlert>();
                                     }
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 2a78806..39ee314 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -202,7 +202,7 @@
         String vs = getVolumeState(path);
         if (enable && vs.equals(Environment.MEDIA_MOUNTED)) {
             mUmsEnabling = enable; // Override for isUsbMassStorageEnabled()
-            int rc = doUnmountVolume(path, false);
+            int rc = doUnmountVolume(path, true);
             mUmsEnabling = false; // Clear override
             if (rc != StorageResultCode.OperationSucceeded) {
                 Log.e(TAG, String.format("Failed to unmount before enabling UMS (%d)", rc));
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 3657133..3c43352 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -307,6 +307,8 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
 
+            boolean queryRestart = false;
+            
             if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                 boolean batteryCharging = (intent.getIntExtra("plugged", 0) != 0);
                 int level = intent.getIntExtra("level", -1);
@@ -330,10 +332,13 @@
                 updateAdbNotification();
             } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
                     || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
+                    || (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART))
                     || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
                 String pkgList[] = null;
                 if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                } else if (queryRestart) {
+                    pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
                 } else {
                     Uri uri = intent.getData();
                     if (uri == null) {
@@ -347,7 +352,7 @@
                 }
                 if (pkgList != null && (pkgList.length > 0)) {
                     for (String pkgName : pkgList) {
-                        cancelAllNotificationsInt(pkgName, 0, 0);
+                        cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart);
                     }
                 }
             } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
@@ -436,11 +441,15 @@
         filter.addAction(Intent.ACTION_BATTERY_CHANGED);
         filter.addAction(Intent.ACTION_UMS_CONNECTED);
         filter.addAction(Intent.ACTION_UMS_DISCONNECTED);
-        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
         filter.addAction(Intent.ACTION_SCREEN_ON);
         filter.addAction(Intent.ACTION_SCREEN_OFF);
         mContext.registerReceiver(mIntentReceiver, filter);
+        IntentFilter pkgFilter = new IntentFilter();
+        pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        pkgFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+        pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
+        pkgFilter.addDataScheme("package");
+        mContext.registerReceiver(mIntentReceiver, pkgFilter);
         IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
         mContext.registerReceiver(mIntentReceiver, sdFilter);
 
@@ -920,8 +929,8 @@
      * Cancels all notifications from a given package that have all of the
      * {@code mustHaveFlags}.
      */
-    void cancelAllNotificationsInt(String pkg, int mustHaveFlags,
-            int mustNotHaveFlags) {
+    boolean cancelAllNotificationsInt(String pkg, int mustHaveFlags,
+            int mustNotHaveFlags, boolean doit) {
         EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL_ALL, pkg, mustHaveFlags);
 
         synchronized (mNotificationList) {
@@ -938,13 +947,17 @@
                 if (!r.pkg.equals(pkg)) {
                     continue;
                 }
+                canceledSomething = true;
+                if (!doit) {
+                    return true;
+                }
                 mNotificationList.remove(i);
                 cancelNotificationLocked(r);
-                canceledSomething = true;
             }
             if (canceledSomething) {
                 updateLightsLocked();
             }
+            return canceledSomething;
         }
     }
 
@@ -966,7 +979,7 @@
 
         // Calling from user space, don't allow the canceling of actively
         // running foreground services.
-        cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE);
+        cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true);
     }
 
     void checkIncomingCall(String pkg) {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 38d8615..4fdcd59 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -28,7 +28,9 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import android.app.ActivityManagerNative;
+import android.app.DevicePolicyManager;
 import android.app.IActivityManager;
+import android.app.IDevicePolicyManager;
 import android.backup.IBackupManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -5594,6 +5596,16 @@
         PackageRemovedInfo info = new PackageRemovedInfo();
         boolean res;
 
+        IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
+                ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
+        try {
+            if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
+                Log.w(TAG, "Not removing package " + packageName + ": has active device admin");
+                return false;
+            }
+        } catch (RemoteException e) {
+        }
+        
         synchronized (mInstallLock) {
             res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
         }
diff --git a/services/java/com/android/server/RecognitionManagerService.java b/services/java/com/android/server/RecognitionManagerService.java
new file mode 100644
index 0000000..7305b07
--- /dev/null
+++ b/services/java/com/android/server/RecognitionManagerService.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+package com.android.server;
+
+import com.android.internal.content.PackageMonitor;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Binder;
+import android.provider.Settings;
+import android.speech.RecognitionService;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.List;
+
+public class RecognitionManagerService extends Binder {
+    final static String TAG = "RecognitionManagerService";
+    
+    final Context mContext;
+    final MyPackageMonitor mMonitor;
+    
+    class MyPackageMonitor extends PackageMonitor {
+        public void onSomePackagesChanged() {
+            ComponentName comp = getCurRecognizer();
+            if (comp == null) {
+                if (anyPackagesAppearing()) {
+                    comp = findAvailRecognizer(null);
+                    if (comp != null) {
+                        setCurRecognizer(comp);
+                    }
+                }
+                return;
+            }
+            
+            int change = isPackageDisappearing(comp.getPackageName()); 
+            if (change == PACKAGE_PERMANENT_CHANGE
+                    || change == PACKAGE_TEMPORARY_CHANGE) {
+                setCurRecognizer(findAvailRecognizer(null));
+                
+            } else if (isPackageModified(comp.getPackageName())) {
+                setCurRecognizer(findAvailRecognizer(comp.getPackageName()));
+            }
+        }
+    }
+    
+    RecognitionManagerService(Context context) {
+        mContext = context;
+        mMonitor = new MyPackageMonitor();
+        mMonitor.register(context, true);
+    }
+    
+    public void systemReady() {
+        ComponentName comp = getCurRecognizer();
+        if (comp != null) {
+            // See if the current recognizer is no longer available.
+            try {
+                mContext.getPackageManager().getServiceInfo(comp, 0);
+            } catch (NameNotFoundException e) {
+                setCurRecognizer(null);
+            }
+        } else {
+            comp = findAvailRecognizer(null);
+            if (comp != null) {
+                setCurRecognizer(comp);
+            }
+        }
+    }
+    
+    ComponentName findAvailRecognizer(String prefPackage) {
+        List<ResolveInfo> available =
+                mContext.getPackageManager().queryIntentServices(
+                        new Intent(RecognitionService.SERVICE_INTERFACE), 0);
+        int numAvailable = available.size();
+    
+        if (numAvailable == 0) {
+            Log.w(TAG, "no available voice recognition services found");
+            return null;
+        } else {
+            if (prefPackage != null) {
+                for (int i=0; i<numAvailable; i++) {
+                    ServiceInfo serviceInfo = available.get(i).serviceInfo;
+                    if (prefPackage.equals(serviceInfo.packageName)) {
+                        return new ComponentName(serviceInfo.packageName, serviceInfo.name);
+                    }
+                }
+            }
+            if (numAvailable > 1) {
+                Log.w(TAG, "more than one voice recognition service found, picking first");
+            }
+    
+            ServiceInfo serviceInfo = available.get(0).serviceInfo;
+            return new ComponentName(serviceInfo.packageName, serviceInfo.name);
+        }
+    }
+    
+    ComponentName getCurRecognizer() {
+        String curRecognizer = Settings.Secure.getString(
+                mContext.getContentResolver(),
+                Settings.Secure.VOICE_RECOGNITION_SERVICE);
+        if (TextUtils.isEmpty(curRecognizer)) {
+            return null;
+        }
+        return ComponentName.unflattenFromString(curRecognizer);
+    }
+    
+    void setCurRecognizer(ComponentName comp) {
+        Settings.Secure.putString(mContext.getContentResolver(),
+                Settings.Secure.VOICE_RECOGNITION_SERVICE,
+                comp != null ? comp.flattenToShortString() : "");
+    }
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a09896a..38df02f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -97,6 +97,7 @@
         BluetoothA2dpService bluetoothA2dp = null;
         HeadsetObserver headset = null;
         DockObserver dock = null;
+        RecognitionManagerService recognition = null;
 
         // Critical services...
         try {
@@ -377,6 +378,13 @@
             }
 
             try {
+                Log.i(TAG, "Recognition Service");
+                recognition = new RecognitionManagerService(context);
+            } catch (Throwable e) {
+                Log.e(TAG, "Failure starting Recognition Service", e);
+            }
+
+            try {
                 com.android.server.status.StatusBarPolicy.installIcons(context, statusBar);
             } catch (Throwable e) {
                 Log.e(TAG, "Failure installing status bar icons", e);
@@ -435,6 +443,7 @@
         final AppWidgetService appWidgetF = appWidget;
         final WallpaperManagerService wallpaperF = wallpaper;
         final InputMethodManagerService immF = imm;
+        final RecognitionManagerService recognitionF = recognition;
 
         // We now tell the activity manager it is okay to run third party
         // code.  It will call back into us once it has gotten to the state
@@ -449,6 +458,7 @@
                 if (batteryF != null) batteryF.systemReady();
                 if (connectivityF != null) connectivityF.systemReady();
                 if (dockF != null) dockF.systemReady();
+                if (recognitionF != null) recognitionF.systemReady();
                 Watchdog.getInstance().start();
 
                 // It is now okay to let the various system services start their
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 81255ee..481e6a4 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -65,7 +65,10 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import com.android.internal.content.PackageMonitor;
 import com.android.internal.service.wallpaper.ImageWallpaper;
+import com.android.server.DevicePolicyManagerService.ActiveAdmin;
+import com.android.server.DevicePolicyManagerService.MyPackageMonitor;
 import com.android.common.FastXmlSerializer;
 
 class WallpaperManagerService extends IWallpaperManager.Stub {
@@ -122,6 +125,7 @@
     
     final Context mContext;
     final IWindowManager mIWindowManager;
+    final MyPackageMonitor mMonitor;
 
     int mWidth = -1;
     int mHeight = -1;
@@ -150,6 +154,7 @@
     
     WallpaperConnection mWallpaperConnection;
     long mLastDiedTime;
+    boolean mWallpaperUpdating;
     
     class WallpaperConnection extends IWallpaperConnection.Stub
             implements ServiceConnection {
@@ -165,6 +170,7 @@
         public void onServiceConnected(ComponentName name, IBinder service) {
             synchronized (mLock) {
                 if (mWallpaperConnection == this) {
+                    mLastDiedTime = SystemClock.uptimeMillis();
                     mService = IWallpaperService.Stub.asInterface(service);
                     attachServiceLocked(this);
                     // XXX should probably do saveSettingsLocked() later
@@ -182,8 +188,8 @@
                 mEngine = null;
                 if (mWallpaperConnection == this) {
                     Log.w(TAG, "Wallpaper service gone: " + mWallpaperComponent);
-                    if ((mLastDiedTime+MIN_WALLPAPER_CRASH_TIME)
-                            < SystemClock.uptimeMillis()) {
+                    if (!mWallpaperUpdating && (mLastDiedTime+MIN_WALLPAPER_CRASH_TIME)
+                                > SystemClock.uptimeMillis()) {
                         Log.w(TAG, "Reverting to built-in wallpaper!");
                         bindWallpaperComponentLocked(null);
                     }
@@ -205,11 +211,92 @@
         }
     }
     
+    class MyPackageMonitor extends PackageMonitor {
+        @Override
+        public void onPackageUpdateFinished(String packageName, int uid) {
+            synchronized (mLock) {
+                if (mWallpaperComponent != null &&
+                        mWallpaperComponent.getPackageName().equals(packageName)) {
+                    mWallpaperUpdating = false;
+                    ComponentName comp = mWallpaperComponent;
+                    clearWallpaperComponentLocked();
+                    bindWallpaperComponentLocked(comp);
+                }
+            }
+        }
+
+        @Override
+        public void onPackageUpdateStarted(String packageName, int uid) {
+            synchronized (mLock) {
+                if (mWallpaperComponent != null &&
+                        mWallpaperComponent.getPackageName().equals(packageName)) {
+                    mWallpaperUpdating = true;
+                }
+            }
+        }
+
+        @Override
+        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
+            return doPackagesChanged(doit);
+        }
+
+        @Override
+        public void onSomePackagesChanged() {
+            doPackagesChanged(true);
+        }
+        
+        boolean doPackagesChanged(boolean doit) {
+            boolean changed = false;
+            synchronized (mLock) {
+                if (mWallpaperComponent != null) {
+                    int change = isPackageDisappearing(mWallpaperComponent.getPackageName());
+                    if (change == PACKAGE_PERMANENT_CHANGE
+                            || change == PACKAGE_TEMPORARY_CHANGE) {
+                        changed = true;
+                        if (doit) {
+                            Log.w(TAG, "Wallpaper uninstalled, removing: " + mWallpaperComponent);
+                            clearWallpaperLocked();
+                        }
+                    }
+                }
+                if (mNextWallpaperComponent != null) {
+                    int change = isPackageDisappearing(mNextWallpaperComponent.getPackageName());
+                    if (change == PACKAGE_PERMANENT_CHANGE
+                            || change == PACKAGE_TEMPORARY_CHANGE) {
+                        mNextWallpaperComponent = null;
+                    }
+                }
+                if (mWallpaperComponent != null
+                        && isPackageModified(mWallpaperComponent.getPackageName())) {
+                    try {
+                        mContext.getPackageManager().getServiceInfo(
+                                mWallpaperComponent, 0);
+                    } catch (NameNotFoundException e) {
+                        Log.w(TAG, "Wallpaper component gone, removing: " + mWallpaperComponent);
+                        clearWallpaperLocked();
+                    }
+                }
+                if (mNextWallpaperComponent != null
+                        && isPackageModified(mNextWallpaperComponent.getPackageName())) {
+                    try {
+                        mContext.getPackageManager().getServiceInfo(
+                                mNextWallpaperComponent, 0);
+                    } catch (NameNotFoundException e) {
+                        mNextWallpaperComponent = null;
+                    }
+                }
+            }
+            return changed;
+        }
+    }
+    
     public WallpaperManagerService(Context context) {
         if (DEBUG) Log.v(TAG, "WallpaperService startup");
         mContext = context;
         mIWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
+        mMonitor = new MyPackageMonitor();
+        mMonitor.register(context, true);
         WALLPAPER_DIR.mkdirs();
         loadSettingsLocked();
         mWallpaperObserver.startWatching();
@@ -241,16 +328,20 @@
     public void clearWallpaper() {
         if (DEBUG) Log.v(TAG, "clearWallpaper");
         synchronized (mLock) {
-            File f = WALLPAPER_FILE;
-            if (f.exists()) {
-                f.delete();
-            }
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                bindWallpaperComponentLocked(null);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+            clearWallpaperLocked();
+        }
+    }
+
+    public void clearWallpaperLocked() {
+        File f = WALLPAPER_FILE;
+        if (f.exists()) {
+            f.delete();
+        }
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            bindWallpaperComponentLocked(null);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -499,7 +590,9 @@
                     mWidth, mHeight);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed attaching wallpaper; clearing", e);
-            bindWallpaperComponentLocked(null);
+            if (!mWallpaperUpdating) {
+                bindWallpaperComponentLocked(null);
+            }
         }
     }
     
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 45c3f00..5b37f47 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -47,6 +47,7 @@
 import android.app.Service;
 import android.backup.IBackupManager;
 import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -93,7 +94,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
-import android.text.TextUtils;
 import android.util.Config;
 import android.util.EventLog;
 import android.util.Log;
@@ -107,7 +107,6 @@
 
 import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -296,12 +295,6 @@
     // Memory pages are 4K.
     static final int PAGE_SIZE = 4*1024;
     
-    // System property defining error report receiver for system apps
-    static final String SYSTEM_APPS_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.system.apps";
-
-    // System property defining default error report receiver
-    static final String DEFAULT_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.default";
-
     // Corresponding memory levels for above adjustments.
     static final int EMPTY_APP_MEM;
     static final int HIDDEN_APP_MEM;
@@ -1193,7 +1186,7 @@
                     int uid = msg.arg1;
                     boolean restart = (msg.arg2 == 1);
                     String pkg = (String) msg.obj;
-                    forceStopPackageLocked(pkg, uid, restart, false);
+                    forceStopPackageLocked(pkg, uid, restart, false, true);
                 }
             } break;
             }
@@ -1396,7 +1389,8 @@
         GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
             ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
 
-        mConfiguration.makeDefault();
+        mConfiguration.setToDefaults();
+        mConfiguration.locale = Locale.getDefault();
         mProcessStats.init();
         
         // Add ourself to the Watchdog monitors.
@@ -4846,7 +4840,7 @@
                     return;
                 }
                 killPackageProcessesLocked(packageName, pkgUid,
-                        SECONDARY_SERVER_ADJ, false);
+                        SECONDARY_SERVER_ADJ, false, true);
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -4988,7 +4982,7 @@
     }
 
     private void forceStopPackageLocked(final String packageName, int uid) {
-        forceStopPackageLocked(packageName, uid, false, false);
+        forceStopPackageLocked(packageName, uid, false, false, true);
         Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
                 Uri.fromParts("package", packageName, null));
         intent.putExtra(Intent.EXTRA_UID, uid);
@@ -4997,8 +4991,8 @@
                 false, false, MY_PID, Process.SYSTEM_UID);
     }
     
-    private final void killPackageProcessesLocked(String packageName, int uid,
-            int minOomAdj, boolean callerWillRestart) {
+    private final boolean killPackageProcessesLocked(String packageName, int uid,
+            int minOomAdj, boolean callerWillRestart, boolean doit) {
         ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
 
         // Remove all processes this package may have touched: all with the
@@ -5010,11 +5004,16 @@
             for (int ia=0; ia<NA; ia++) {
                 ProcessRecord app = apps.valueAt(ia);
                 if (app.removed) {
-                    procs.add(app);
+                    if (doit) {
+                        procs.add(app);
+                    }
                 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
                         || app.processName.equals(packageName)
                         || app.processName.startsWith(procNamePrefix)) {
                     if (app.setAdj >= minOomAdj) {
+                        if (!doit) {
+                            return true;
+                        }
                         app.removed = true;
                         procs.add(app);
                     }
@@ -5026,10 +5025,11 @@
         for (int i=0; i<N; i++) {
             removeProcessLocked(procs.get(i), callerWillRestart);
         }
+        return N > 0;
     }
 
-    private final void forceStopPackageLocked(String name, int uid,
-            boolean callerWillRestart, boolean purgeCache) {
+    private final boolean forceStopPackageLocked(String name, int uid,
+            boolean callerWillRestart, boolean purgeCache, boolean doit) {
         int i, N;
 
         if (uid < 0) {
@@ -5039,21 +5039,28 @@
             }
         }
 
-        Log.i(TAG, "Force stopping package " + name + " uid=" + uid);
+        if (doit) {
+            Log.i(TAG, "Force stopping package " + name + " uid=" + uid);
 
-        Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
-        while (badApps.hasNext()) {
-            SparseArray<Long> ba = badApps.next();
-            if (ba.get(uid) != null) {
-                badApps.remove();
+            Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
+            while (badApps.hasNext()) {
+                SparseArray<Long> ba = badApps.next();
+                if (ba.get(uid) != null) {
+                    badApps.remove();
+                }
             }
         }
-
-        killPackageProcessesLocked(name, uid, -100, callerWillRestart);
+        
+        boolean didSomething = killPackageProcessesLocked(name, uid, -100,
+                callerWillRestart, doit);
         
         for (i=mHistory.size()-1; i>=0; i--) {
             HistoryRecord r = (HistoryRecord)mHistory.get(i);
             if (r.packageName.equals(name)) {
+                if (!doit) {
+                    return true;
+                }
+                didSomething = true;
                 Log.i(TAG, "  Force finishing activity " + r);
                 if (r.app != null) {
                     r.app.removed = true;
@@ -5066,6 +5073,10 @@
         ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
         for (ServiceRecord service : mServices.values()) {
             if (service.packageName.equals(name)) {
+                if (!doit) {
+                    return true;
+                }
+                didSomething = true;
                 Log.i(TAG, "  Force stopping service " + service);
                 if (service.app != null) {
                     service.app.removed = true;
@@ -5080,13 +5091,17 @@
             bringDownServiceLocked(services.get(i), true);
         }
         
-        resumeTopActivityLocked(null);
-        if (purgeCache) {
-            AttributeCache ac = AttributeCache.instance();
-            if (ac != null) {
-                ac.removePackage(name);
+        if (doit) {
+            if (purgeCache) {
+                AttributeCache ac = AttributeCache.instance();
+                if (ac != null) {
+                    ac.removePackage(name);
+                }
             }
+            resumeTopActivityLocked(null);
         }
+        
+        return didSomething;
     }
 
     private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
@@ -5583,19 +5598,38 @@
     }
 
     final void finishBooting() {
-        // Ensure that any processes we had put on hold are now started
-        // up.
-        final int NP = mProcessesOnHold.size();
-        if (NP > 0) {
-            ArrayList<ProcessRecord> procs =
-                new ArrayList<ProcessRecord>(mProcessesOnHold);
-            for (int ip=0; ip<NP; ip++) {
-                this.startProcessLocked(procs.get(ip), "on-hold", null);
+        IntentFilter pkgFilter = new IntentFilter();
+        pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
+        pkgFilter.addDataScheme("package");
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
+                if (pkgs != null) {
+                    for (String pkg : pkgs) {
+                        if (forceStopPackageLocked(pkg, -1, false, false, false)) {
+                            setResultCode(Activity.RESULT_OK);
+                            return;
+                        }
+                    }
+                }
             }
-        }
-        if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
-            // Tell anyone interested that we are done booting!
-            synchronized (this) {
+        }, pkgFilter);
+        
+        synchronized (this) {
+            // Ensure that any processes we had put on hold are now started
+            // up.
+            final int NP = mProcessesOnHold.size();
+            if (NP > 0) {
+                ArrayList<ProcessRecord> procs =
+                    new ArrayList<ProcessRecord>(mProcessesOnHold);
+                for (int ip=0; ip<NP; ip++) {
+                    this.startProcessLocked(procs.get(ip), "on-hold", null);
+                }
+            }
+            
+            if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
+                // Tell anyone interested that we are done booting!
                 broadcastIntentLocked(null, null,
                         new Intent(Intent.ACTION_BOOT_COMPLETED, null),
                         null, null, 0, null, null,
@@ -8050,7 +8084,7 @@
             mDebugTransient = !persistent;
             if (packageName != null) {
                 final long origId = Binder.clearCallingIdentity();
-                forceStopPackageLocked(packageName, -1, false, false);
+                forceStopPackageLocked(packageName, -1, false, false, true);
                 Binder.restoreCallingIdentity(origId);
             }
         }
@@ -8339,7 +8373,6 @@
             mAlwaysFinishActivities = alwaysFinishActivities;
             // This happens before any activities are started, so we can
             // change mConfiguration in-place.
-            mConfiguration.locale = Locale.getDefault();
             mConfiguration.updateFrom(configuration);
             mConfigurationSeq = mConfiguration.seq = 1;
             if (DEBUG_CONFIGURATION) Log.v(TAG, "Initial config: " + mConfiguration);
@@ -8537,73 +8570,6 @@
         return handleAppCrashLocked(app);
     }
 
-    private ComponentName getErrorReportReceiver(ProcessRecord app) {
-        // check if error reporting is enabled in secure settings
-        int enabled = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.SEND_ACTION_APP_ERROR, 0);
-        if (enabled == 0) {
-            return null;
-        }
-
-        IPackageManager pm = ActivityThread.getPackageManager();
-
-        try {
-            // look for receiver in the installer package
-            String candidate = pm.getInstallerPackageName(app.info.packageName);
-            ComponentName result = getErrorReportReceiver(pm, app.info.packageName, candidate);
-            if (result != null) {
-                return result;
-            }
-
-            // if the error app is on the system image, look for system apps
-            // error receiver
-            if ((app.info.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
-                candidate = SystemProperties.get(SYSTEM_APPS_ERROR_RECEIVER_PROPERTY);
-                result = getErrorReportReceiver(pm, app.info.packageName, candidate);
-                if (result != null) {
-                    return result;
-                }
-            }
-
-            // if there is a default receiver, try that
-            candidate = SystemProperties.get(DEFAULT_ERROR_RECEIVER_PROPERTY);
-            return getErrorReportReceiver(pm, app.info.packageName, candidate);
-        } catch (RemoteException e) {
-            // should not happen
-            Log.e(TAG, "error talking to PackageManager", e);
-            return null;
-        }
-    }
-
-    /**
-     * Return activity in receiverPackage that handles ACTION_APP_ERROR.
-     *
-     * @param pm PackageManager isntance
-     * @param errorPackage package which caused the error
-     * @param receiverPackage candidate package to receive the error
-     * @return activity component within receiverPackage which handles
-     * ACTION_APP_ERROR, or null if not found
-     */
-    private ComponentName getErrorReportReceiver(IPackageManager pm, String errorPackage,
-            String receiverPackage) throws RemoteException {
-        if (receiverPackage == null || receiverPackage.length() == 0) {
-            return null;
-        }
-
-        // break the loop if it's the error report receiver package that crashed
-        if (receiverPackage.equals(errorPackage)) {
-            return null;
-        }
-
-        Intent intent = new Intent(Intent.ACTION_APP_ERROR);
-        intent.setPackage(receiverPackage);
-        ResolveInfo info = pm.resolveIntent(intent, null, 0);
-        if (info == null || info.activityInfo == null) {
-            return null;
-        }
-        return new ComponentName(receiverPackage, info.activityInfo.name);
-    }
-
     private void makeAppNotRespondingLocked(ProcessRecord app,
             String activity, String shortMsg, String longMsg) {
         app.notResponding = true;
@@ -8717,7 +8683,8 @@
     }
 
     void startAppProblemLocked(ProcessRecord app) {
-        app.errorReportReceiver = getErrorReportReceiver(app);
+        app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
+                mContext, app.info.packageName, app.info.flags);
         skipCurrentReceiverLocked(app);
     }
 
@@ -11951,7 +11918,7 @@
                         String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                         if (list != null && (list.length > 0)) {
                             for (String pkg : list) {
-                                forceStopPackageLocked(pkg, -1, false, true);
+                                forceStopPackageLocked(pkg, -1, false, true, true);
                             }
                         }
                     } else {
@@ -11960,7 +11927,7 @@
                         if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
                             if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
                                 forceStopPackageLocked(ssp,
-                                        intent.getIntExtra(Intent.EXTRA_UID, -1), false, true);
+                                        intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
                             }
                         }
                     }
@@ -12931,7 +12898,7 @@
             }
 
             final long origId = Binder.clearCallingIdentity();
-            forceStopPackageLocked(ii.targetPackage, -1, true, false);
+            forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
             ProcessRecord app = addAppLocked(ai);
             app.instrumentationClass = className;
             app.instrumentationInfo = ai;
@@ -12986,7 +12953,7 @@
         app.instrumentationProfileFile = null;
         app.instrumentationArguments = null;
 
-        forceStopPackageLocked(app.processName, -1, false, false);
+        forceStopPackageLocked(app.processName, -1, false, false, true);
     }
 
     public void finishInstrumentation(IApplicationThread target,
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index d13f9d3..f1ccb9b 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -826,7 +826,10 @@
                 final Uri soundUri = Uri.parse("file://" + soundPath);
                 if (soundUri != null) {
                     final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
-                    if (sfx != null) sfx.play();
+                    if (sfx != null) {
+                        sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+                        sfx.play();
+                    }
                 }
             }
         }