On system update, do not delete system apps enabled by the profile owner.

Also, during the creation of a new profile, if there is a list of installed system apps present from a previously created profile with the same user id, ignore that file.

BUG:17423480
BUG:17434709
Change-Id: Ie69c707465cb42bb979e71f8913e68f07bb0c15d
diff --git a/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java b/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java
index 22656d0..45e8a17 100644
--- a/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java
+++ b/src/com/android/managedprovisioning/DeviceOwnerProvisioningService.java
@@ -245,7 +245,7 @@
         mDeleteNonRequiredAppsTask = new DeleteNonRequiredAppsTask(
                 this, params.mDeviceAdminPackageName, UserHandle.USER_OWNER,
                 R.array.required_apps_managed_device, R.array.vendor_required_apps_managed_device,
-                true /* Disable sharing via Nfc and Bluetooth */,
+                true /* We are creating a new profile */,
                 false /* Do not disable INSTALL_SHORTCUT listeners */,
                 new DeleteNonRequiredAppsTask.Callback() {
                     public void onSuccess() {
diff --git a/src/com/android/managedprovisioning/ManagedProvisioningService.java b/src/com/android/managedprovisioning/ManagedProvisioningService.java
index 0cac1ec..1126ee9 100644
--- a/src/com/android/managedprovisioning/ManagedProvisioningService.java
+++ b/src/com/android/managedprovisioning/ManagedProvisioningService.java
@@ -184,7 +184,7 @@
                 mMdmPackageName, mManagedProfileUserInfo.id,
                 R.array.required_apps_managed_profile,
                 R.array.vendor_required_apps_managed_profile,
-                true /* Disable Sharing via Nfc and Blueetoth */,
+                true /* We are creating a new profile */,
                 true /* Disable INSTALL_SHORTCUT listeners */,
                 new DeleteNonRequiredAppsTask.Callback() {
 
diff --git a/src/com/android/managedprovisioning/PreBootListener.java b/src/com/android/managedprovisioning/PreBootListener.java
index 5f6570d..942e202 100644
--- a/src/com/android/managedprovisioning/PreBootListener.java
+++ b/src/com/android/managedprovisioning/PreBootListener.java
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2014, The Android Open Source Project
  *
@@ -79,7 +78,7 @@
 
         new DeleteNonRequiredAppsTask(context, profileOwner.getPackageName(), userId,
                 R.array.required_apps_managed_profile, R.array.vendor_required_apps_managed_profile,
-                false /* Do not disable sharing via Nfc and Blueetooth, it has already been done */,
+                false /* We are not creating a new profile */,
                 true /* Disable INSTALL_SHORTCUT listeners */,
                 new DeleteNonRequiredAppsTask.Callback() {
 
diff --git a/src/com/android/managedprovisioning/task/DeleteNonRequiredAppsTask.java b/src/com/android/managedprovisioning/task/DeleteNonRequiredAppsTask.java
index 0218f2e..dac9663 100644
--- a/src/com/android/managedprovisioning/task/DeleteNonRequiredAppsTask.java
+++ b/src/com/android/managedprovisioning/task/DeleteNonRequiredAppsTask.java
@@ -52,11 +52,11 @@
 import org.xmlpull.v1.XmlSerializer;
 
 /**
- * Removes all apps with a launcher that are not required.
- * There are two decendants of this class:
- * {@link DeleteNonRequiredAppsTask} for profile owner provisioning,
- * and {@link DeleteNonRequiredAppsTask} for device owner provisioning.
- * The decendents specify which apps are required.
+ * Removes all system apps with a launcher that are not required.
+ * Also disables sharing via Bluetooth and Nfc, and components that listen to
+ * ACTION_INSTALL_SHORTCUT.
+ * This class is called a first time when a user is created, but also after a system update.
+ * In this case, it checks if the system apps that have been added need to be disabled.
  */
 public class DeleteNonRequiredAppsTask {
     private final Callback mCallback;
@@ -67,15 +67,15 @@
     private final int mReqAppsList;
     private final int mVendorReqAppsList;
     private final int mUserId;
-    private final boolean mDisableNfcBluetoothSharing;
+    private final boolean mNewProfile; // If we are provisioning a new profile.
     private final boolean mDisableInstallShortcutListeners;
 
-    private static final String TAG_APPS_WITH_LAUNCHER = "apps-with-launcher";
+    private static final String TAG_SYSTEM_APPS = "system-apps";
     private static final String TAG_PACKAGE_LIST_ITEM = "item";
     private static final String ATTR_VALUE = "value";
 
     public DeleteNonRequiredAppsTask(Context context, String mdmPackageName, int userId,
-            int requiredAppsList, int vendorRequiredAppsList, boolean disableNfcBluetoothSharing,
+            int requiredAppsList, int vendorRequiredAppsList, boolean newProfile,
             boolean disableInstallShortcutListeners, Callback callback) {
         mCallback = callback;
         mContext = context;
@@ -85,12 +85,12 @@
         mPm = context.getPackageManager();
         mReqAppsList = requiredAppsList;
         mVendorReqAppsList = vendorRequiredAppsList;
-        mDisableNfcBluetoothSharing = disableNfcBluetoothSharing;
+        mNewProfile = newProfile;
         mDisableInstallShortcutListeners = disableInstallShortcutListeners;
     }
 
     public void run() {
-        if (mDisableNfcBluetoothSharing) {
+        if (mNewProfile) {
             disableNfcBluetoothSharing();
         }
         deleteNonRequiredApps();
@@ -106,12 +106,27 @@
     private void deleteNonRequiredApps() {
         ProvisionLogger.logd("Deleting non required apps.");
 
-        File file = new File(mContext.getFilesDir() + File.separator + "system_apps_with_launcher"
+        File file = new File(mContext.getFilesDir() + File.separator + "system_apps"
                 + File.separator + "user" + mUserId + ".xml");
         file.getParentFile().mkdirs(); // Creating the folder if it does not exist
 
         Set<String> currentApps = getCurrentSystemApps();
-        Set<String> previousApps = readSystemApps(file);
+        Set<String> previousApps;
+        if (mNewProfile) {
+            // If this userId was a managed profile before, file may exist. In this case, we ignore
+            // what is in this file.
+            previousApps = new HashSet<String>();
+        } else {
+            if (file.exists()) {
+                previousApps = readSystemApps(file);
+            } else {
+                // If for some reason, the system apps have not been written to file before, we will
+                // not delete any system apps this time.
+                writeSystemApps(currentApps, file);
+                mCallback.onSuccess();
+                return;
+            }
+        }
         writeSystemApps(currentApps, file);
         Set<String> newApps = currentApps;
         newApps.removeAll(previousApps);
@@ -135,18 +150,24 @@
         packagesToDelete.removeAll(getRequiredApps());
         packagesToDelete.retainAll(getCurrentAppsWithLauncher());
         // com.android.telecomm should not handle CALL intents in the managed profile.
-        packagesToDelete.add("com.android.telecomm");
-
-        PackageDeleteObserver packageDeleteObserver =
-                    new PackageDeleteObserver(packagesToDelete.size());
-        for (String packageName : packagesToDelete) {
-            try {
-                mIpm.deletePackageAsUser(packageName, packageDeleteObserver, mUserId,
-                        PackageManager.DELETE_SYSTEM_APP);
-            } catch (RemoteException neverThrown) {
-                // Never thrown, as we are making local calls.
-                ProvisionLogger.loge("This should not happen.", neverThrown);
+        if (mNewProfile) {
+            packagesToDelete.add("com.android.telecomm");
+        }
+        int size = packagesToDelete.size();
+        if (size > 0) {
+            PackageDeleteObserver packageDeleteObserver =
+                        new PackageDeleteObserver(packagesToDelete.size());
+            for (String packageName : packagesToDelete) {
+                try {
+                    mIpm.deletePackageAsUser(packageName, packageDeleteObserver, mUserId,
+                            PackageManager.DELETE_SYSTEM_APP);
+                } catch (RemoteException neverThrown) {
+                    // Never thrown, as we are making local calls.
+                    ProvisionLogger.loge("This should not happen.", neverThrown);
+                }
             }
+        } else {
+            mCallback.onSuccess();
         }
     }
 
@@ -179,7 +200,7 @@
 
     /**
      * Returns the set of package names of apps that are in the system image,
-     * whether they have been deleted or not for the managed profile.
+     * whether they have been deleted or not.
      */
     private Set<String> getCurrentSystemApps() {
         Set<String> apps = new HashSet<String>();
@@ -217,17 +238,17 @@
             XmlSerializer serializer = new FastXmlSerializer();
             serializer.setOutput(stream, "utf-8");
             serializer.startDocument(null, true);
-            serializer.startTag(null, TAG_APPS_WITH_LAUNCHER);
+            serializer.startTag(null, TAG_SYSTEM_APPS);
             for (String packageName : packageNames) {
                 serializer.startTag(null, TAG_PACKAGE_LIST_ITEM);
                 serializer.attribute(null, ATTR_VALUE, packageName);
                 serializer.endTag(null, TAG_PACKAGE_LIST_ITEM);
             }
-            serializer.endTag(null, TAG_APPS_WITH_LAUNCHER);
+            serializer.endTag(null, TAG_SYSTEM_APPS);
             serializer.endDocument();
             stream.close();
         } catch (IOException e) {
-            ProvisionLogger.loge("IOException trying to read the apps with launcher", e);
+            ProvisionLogger.loge("IOException trying to write the system apps", e);
         }
     }
 
@@ -258,9 +279,9 @@
             }
             stream.close();
         } catch (IOException e) {
-            ProvisionLogger.loge("IOException trying to read the apps with launcher", e);
+            ProvisionLogger.loge("IOException trying to read the system apps", e);
         } catch (XmlPullParserException e) {
-            ProvisionLogger.loge("XmlPullParserException trying to read the apps with launcher", e);
+            ProvisionLogger.loge("XmlPullParserException trying to read the system apps", e);
         }
         return result;
     }
@@ -289,7 +310,7 @@
         public void packageDeleted(String packageName, int returnCode) {
             if (returnCode != PackageManager.DELETE_SUCCEEDED) {
                 ProvisionLogger.logw(
-                        "Could not finish managed profile provisioning: package deletion failed");
+                        "Could not finish the provisioning: package deletion failed");
                 mCallback.onError();
             }
             int currentPackageCount = mPackageCount.decrementAndGet();