Fix issue #2438980: Implement package watcher for voice recognizer service setting

I am getting tired of writing package monitor code, realized this is missing in
a number of places, and at this point it has gotten complicated enough that I
don't think anyone actually does it 100% right so:

Introducing PackageMonitor.

Yes there are no Java docs.  I am still playing around with just what this
thing is to figure out what makes sense and how people will use it.  It is
being used to fix this bug for monitoring voice recognizers (integrating the
code from the settings provider for setting an initial value), to replace
the existing code for monitoring input methods (and fix the bug where we
wouldn't remove an input method from the enabled list when it got
uninstalled), to now monitor live wallpaper package changes (now allowing
us to avoid reverting back to the default live wallpaper when the current
one is updated!), and to monitor device admin changes.

Also includes a fix so you can't uninstall an .apk that is currently enabled
as a device admin.

Also includes a fix where the default time zone was not initialized early
enough which should fix issue #2455507 (Observed Google services frame work crash).

In addition, this finally introduces a mechanism to determine if the
"force stop" button should be enabled, with convenience in PackageMonitor
for system services to handle it.  All services have been updated to support
this.  There is also new infrastructure for reporting battery usage as an
applicatin error report.
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);