15f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot/*
25f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot * Copyright 2014, The Android Open Source Project
35f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot *
45f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot * Licensed under the Apache License, Version 2.0 (the "License");
55f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot * you may not use this file except in compliance with the License.
65f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot * You may obtain a copy of the License at
75f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot *
85f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot *     http://www.apache.org/licenses/LICENSE-2.0
95f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot *
105f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot * Unless required by applicable law or agreed to in writing, software
115f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot * distributed under the License is distributed on an "AS IS" BASIS,
125f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot * See the License for the specific language governing permissions and
145f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot * limitations under the License.
155f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot */
165f22bf5fcf695d794e3de83c03ab88e4b21808fdNicolas Prevot
172818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnsepackage com.android.managedprovisioning.task;
182818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse
193b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport android.content.BroadcastReceiver;
20c319f8de1ccf824a1c40997f3f0a71d47099b616Nicolas Prevotimport android.content.ComponentName;
212818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport android.content.Context;
222818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport android.content.Intent;
233b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport android.content.pm.ApplicationInfo;
24b20503c00736a21c24cfdf45ae72e3f7a264b4b6Nicolas Prevotimport android.content.pm.ComponentInfo;
25012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connorsimport android.content.pm.IPackageDeleteObserver;
262818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport android.content.pm.IPackageManager;
27089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnseimport android.content.pm.PackageInfo;
283b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport android.content.pm.PackageManager.NameNotFoundException;
292818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport android.content.pm.PackageManager;
302818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport android.content.pm.ResolveInfo;
31089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnseimport android.content.res.Resources;
322818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport android.os.RemoteException;
332818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport android.os.ServiceManager;
343b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport android.util.Xml;
353d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shankaimport android.view.inputmethod.InputMethodInfo;
363d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shankaimport android.view.inputmethod.InputMethodManager;
372818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse
383b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport com.android.internal.util.FastXmlSerializer;
392818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport com.android.managedprovisioning.ProvisionLogger;
402818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport com.android.managedprovisioning.R;
41d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport com.android.managedprovisioning.Utils;
422818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse
433b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport java.io.File;
443b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport java.io.FileInputStream;
453b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport java.io.FileOutputStream;
463b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport java.io.IOException;
473b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot
48b20503c00736a21c24cfdf45ae72e3f7a264b4b6Nicolas Prevotimport java.util.ArrayList;
492818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport java.util.Arrays;
50d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport java.util.Collections;
512818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport java.util.HashSet;
522818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport java.util.List;
532818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnseimport java.util.Set;
54012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connorsimport java.util.concurrent.atomic.AtomicInteger;
552818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse
563b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport org.xmlpull.v1.XmlPullParser;
573b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport org.xmlpull.v1.XmlPullParserException;
583b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevotimport org.xmlpull.v1.XmlSerializer;
593b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot
602818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse/**
61d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * Deletes all system apps with a launcher that are not in the required set of packages.
62089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse * Furthermore deletes all disallowed apps.
63089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse *
64089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse * Note: If an app is mistakenly listed as both required and disallowed, it will be treated as
65089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse * required.
66d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse *
67d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * This task may be run when a profile (both for managed device and managed profile) is created.
68d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * In that case the newProfile flag should be true.
69d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse *
70d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * It should also be run after a system update with newProfile false, if
71d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * {@link #shouldDeleteNonRequiredApps} returns true. Note that only newly installed system apps
72d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * will be deleted.
732818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse */
742818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnsepublic class DeleteNonRequiredAppsTask {
7528bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse    private final Callback mCallback;
762818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse    private final Context mContext;
77089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    private final String mMdmPackageName;
782818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse    private final IPackageManager mIpm;
792818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse    private final PackageManager mPm;
80089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    private final List<String> mRequiredAppsList;
81089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    private final List<String> mDisallowedAppsList;
82089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    private final List<String> mVendorRequiredAppsList;
83089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    private final List<String> mVendorDisallowedAppsList;
842818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse    private final int mUserId;
853d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka    private final int mProvisioningType;
86089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    private final boolean mNewProfile; // If we are provisioning a new managed profile/device.
87ccd60165065172486fff32b581a0fb4d724b2991Julia Reynolds    private final boolean mLeaveAllSystemAppsEnabled;
883b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot
89418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot    private static final String TAG_SYSTEM_APPS = "system-apps";
903b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot    private static final String TAG_PACKAGE_LIST_ITEM = "item";
913b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot    private static final String ATTR_VALUE = "value";
922818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse
93089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    public static final int DEVICE_OWNER = 0;
94089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    public static final int PROFILE_OWNER = 1;
95d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse
96089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    /**
97089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse     * Provisioning type should be either {@link #DEVICE_OWNER} or {@link #PROFILE_OWNER}.
98089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse     **/
99089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    public DeleteNonRequiredAppsTask(Context context, String mdmPackageName, int provisioningType,
100ccd60165065172486fff32b581a0fb4d724b2991Julia Reynolds            boolean newProfile, int userId, boolean leaveAllSystemAppsEnabled, Callback callback) {
101089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse
1022818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse        mCallback = callback;
1032818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse        mContext = context;
104089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        mMdmPackageName = mdmPackageName;
1053d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        mProvisioningType = provisioningType;
1062818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse        mUserId = userId;
107418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot        mNewProfile = newProfile;
108ccd60165065172486fff32b581a0fb4d724b2991Julia Reynolds        mLeaveAllSystemAppsEnabled = leaveAllSystemAppsEnabled;
109089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        mIpm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
110089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        mPm = context.getPackageManager();
111089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse
112089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        int requiredAppsListArray;
113089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        int vendorRequiredAppsListArray;
114089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        int disallowedAppsListArray;
115089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        int vendorDisallowedAppsListArray;
1163d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        if (mProvisioningType == DEVICE_OWNER) {
117089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse            requiredAppsListArray = R.array.required_apps_managed_device;
118089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse            disallowedAppsListArray = R.array.disallowed_apps_managed_device;
119089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse            vendorRequiredAppsListArray = R.array.vendor_required_apps_managed_device;
120089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse            vendorDisallowedAppsListArray = R.array.vendor_disallowed_apps_managed_device;
1213d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        } else if (mProvisioningType == PROFILE_OWNER) {
122089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse            requiredAppsListArray = R.array.required_apps_managed_profile;
123089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse            disallowedAppsListArray = R.array.disallowed_apps_managed_profile;
124089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse            vendorRequiredAppsListArray = R.array.vendor_required_apps_managed_profile;
125089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse            vendorDisallowedAppsListArray = R.array.vendor_disallowed_apps_managed_profile;
126089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        } else {
1273d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka            throw new IllegalArgumentException("Provisioning type " + mProvisioningType +
128089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                    " not supported.");
129089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        }
130089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse
131089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        Resources resources = mContext.getResources();
132089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        mRequiredAppsList = Arrays.asList(resources.getStringArray(requiredAppsListArray));
133089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        mDisallowedAppsList = Arrays.asList(resources.getStringArray(disallowedAppsListArray));
134089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        mVendorRequiredAppsList = Arrays.asList(
135089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                resources.getStringArray(vendorRequiredAppsListArray));
136089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        mVendorDisallowedAppsList = Arrays.asList(
137089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                resources.getStringArray(vendorDisallowedAppsListArray));
1382818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse    }
1392818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse
1402818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse    public void run() {
141ccd60165065172486fff32b581a0fb4d724b2991Julia Reynolds        if (mLeaveAllSystemAppsEnabled) {
142ccd60165065172486fff32b581a0fb4d724b2991Julia Reynolds            ProvisionLogger.logd("Not deleting non-required apps.");
143ccd60165065172486fff32b581a0fb4d724b2991Julia Reynolds            mCallback.onSuccess();
144ccd60165065172486fff32b581a0fb4d724b2991Julia Reynolds            return;
145ccd60165065172486fff32b581a0fb4d724b2991Julia Reynolds        }
1463b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        ProvisionLogger.logd("Deleting non required apps.");
1473b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot
1487d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot        File systemAppsFile = getSystemAppsFile(mContext, mUserId);
1497d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot        systemAppsFile.getParentFile().mkdirs(); // Creating the folder if it does not exist
1503b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot
151d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        Set<String> currentApps = Utils.getCurrentSystemApps(mUserId);
152418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot        Set<String> previousApps;
153418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot        if (mNewProfile) {
1547d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot            // Provisioning case.
155418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot            previousApps = new HashSet<String>();
156418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot        } else {
1577d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot            // OTA case.
1587d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot            if (!systemAppsFile.exists()) {
159d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse                ProvisionLogger.loge("Could not find the system apps file " +
160d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse                        systemAppsFile.getAbsolutePath());
1617d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot                mCallback.onError();
162418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot                return;
163418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot            }
1647d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot            previousApps = readSystemApps(systemAppsFile);
165418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot        }
166d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse
1677d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot        writeSystemApps(currentApps, systemAppsFile);
1683b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        Set<String> newApps = currentApps;
1693b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        newApps.removeAll(previousApps);
1703b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot
171089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        // Newly installed system apps are uninstalled when they are not required and are either
172089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        // disallowed or have a launcher icon.
1733b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        Set<String> packagesToDelete = newApps;
174089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        packagesToDelete.removeAll(getRequiredApps());
175089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        Set<String> packagesToRetain = getCurrentAppsWithLauncher();
1763d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        // Don't delete the system input method packages in case of Device owner provisioning.
1773d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        if (mProvisioningType == DEVICE_OWNER) {
1783d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka            packagesToRetain.removeAll(getSystemInputMethods());
1793d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        }
180089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        packagesToRetain.addAll(getDisallowedApps());
181089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        packagesToDelete.retainAll(packagesToRetain);
182089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse
1837d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot        if (packagesToDelete.isEmpty()) {
1847d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot            mCallback.onSuccess();
1857d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot            return;
1867d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot        }
187089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        removeNonInstalledPackages(packagesToDelete);
188089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse
1897d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot        PackageDeleteObserver packageDeleteObserver =
1907d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot                new PackageDeleteObserver(packagesToDelete.size());
1917d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot        for (String packageName : packagesToDelete) {
1927d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot            try {
1937d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot                mIpm.deletePackageAsUser(packageName, packageDeleteObserver, mUserId,
1947d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot                        PackageManager.DELETE_SYSTEM_APP);
1957d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot            } catch (RemoteException neverThrown) {
196089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                // Never thrown, as we are making local calls.
197089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                ProvisionLogger.loge("This should not happen.", neverThrown);
198089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse            }
199089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        }
200089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    }
201089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse
202089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    /**
203089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse     * Remove all packages from the set that are not installed.
204089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse     */
205089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    private void removeNonInstalledPackages(Set<String> packages) {
206089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        Set<String> toBeRemoved = new HashSet<String>();
207089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        for (String packageName : packages) {
208089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse            try {
209089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                PackageInfo info = mIpm.getPackageInfo(packageName, 0 /* default flags */, mUserId);
210089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                if (info == null) {
211089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                    toBeRemoved.add(packageName);
212089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                }
213089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse            } catch (RemoteException neverThrown) {
214089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                // Never thrown, as we are making local calls.
2157d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot                ProvisionLogger.loge("This should not happen.", neverThrown);
2163b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            }
2173b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        }
218089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        packages.removeAll(toBeRemoved);
2193b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot    }
220b20503c00736a21c24cfdf45ae72e3f7a264b4b6Nicolas Prevot
2217d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot    /**
222d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse     * Returns if this task should be run on OTA.
223d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse     * This is indicated by the presence of the system apps file.
2247d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot     */
225d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse    public static boolean shouldDeleteNonRequiredApps(Context context, int userId) {
226d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        return getSystemAppsFile(context, userId).exists();
2273b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot    }
2282818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse
229d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse    static File getSystemAppsFile(Context context, int userId) {
230d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        return new File(context.getFilesDir() + File.separator + "system_apps"
231d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse                + File.separator + "user" + userId + ".xml");
2323b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot    }
2333b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot
2343b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot    private Set<String> getCurrentAppsWithLauncher() {
2352818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse        Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
2362818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse        launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
2373b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        List<ResolveInfo> resolveInfos = mPm.queryIntentActivitiesAsUser(launcherIntent,
2383bcd298ae1efa3c3ee78ecc4f114d498fcac2685Nicolas Prevot                PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS,
2393bcd298ae1efa3c3ee78ecc4f114d498fcac2685Nicolas Prevot                mUserId);
2403b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        Set<String> apps = new HashSet<String>();
2413b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        for (ResolveInfo resolveInfo : resolveInfos) {
2423b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            apps.add(resolveInfo.activityInfo.packageName);
2433b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        }
2443b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        return apps;
2453b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot    }
2462818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse
2473d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka    private Set<String> getSystemInputMethods() {
2483d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        final InputMethodManager inputMethodManager =
2493d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka                (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
2503d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        List<InputMethodInfo> inputMethods = inputMethodManager.getInputMethodList();
2513d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        Set<String> systemInputMethods = new HashSet<String>();
2523d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        for (InputMethodInfo inputMethodInfo : inputMethods) {
2533d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka            ApplicationInfo applicationInfo = inputMethodInfo.getServiceInfo().applicationInfo;
2543d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka            if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
2553d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka                systemInputMethods.add(inputMethodInfo.getPackageName());
2563d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka            }
2573d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        }
2583d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka        return systemInputMethods;
2593d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka    }
2603d24d0966fbbb4b67ceb06fe373db147a1b793bfSudheer Shanka
2617d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot    private void writeSystemApps(Set<String> packageNames, File systemAppsFile) {
2623b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        try {
2637d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot            FileOutputStream stream = new FileOutputStream(systemAppsFile, false);
2643b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            XmlSerializer serializer = new FastXmlSerializer();
2653b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            serializer.setOutput(stream, "utf-8");
2663b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            serializer.startDocument(null, true);
267418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot            serializer.startTag(null, TAG_SYSTEM_APPS);
2683b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            for (String packageName : packageNames) {
2693b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                serializer.startTag(null, TAG_PACKAGE_LIST_ITEM);
2703b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                serializer.attribute(null, ATTR_VALUE, packageName);
2713b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                serializer.endTag(null, TAG_PACKAGE_LIST_ITEM);
2722818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse            }
273418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot            serializer.endTag(null, TAG_SYSTEM_APPS);
2743b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            serializer.endDocument();
2753b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            stream.close();
2763b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        } catch (IOException e) {
277418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot            ProvisionLogger.loge("IOException trying to write the system apps", e);
2782818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse        }
2793b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot    }
2802818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse
2817d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot    private Set<String> readSystemApps(File systemAppsFile) {
2823b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        Set<String> result = new HashSet<String>();
2837d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot        if (!systemAppsFile.exists()) {
2843b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            return result;
2853b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        }
2863b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        try {
2877d56b9097cf040afa85bfc93f78a30436754eaf8Nicolas Prevot            FileInputStream stream = new FileInputStream(systemAppsFile);
2883b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot
2893b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            XmlPullParser parser = Xml.newPullParser();
2903b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            parser.setInput(stream, null);
2913b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot
2923b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            int type = parser.next();
2933b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            int outerDepth = parser.getDepth();
2943b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
2953b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                   && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2963b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2973b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                    continue;
2983b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                }
2993b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                String tag = parser.getName();
3003b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                if (tag.equals(TAG_PACKAGE_LIST_ITEM)) {
3013b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                    result.add(parser.getAttributeValue(null, ATTR_VALUE));
3023b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                } else {
3033b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                    ProvisionLogger.loge("Unknown tag: " + tag);
3043b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot                }
3052818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse            }
3063b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot            stream.close();
3073b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        } catch (IOException e) {
308418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot            ProvisionLogger.loge("IOException trying to read the system apps", e);
3093b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        } catch (XmlPullParserException e) {
310418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot            ProvisionLogger.loge("XmlPullParserException trying to read the system apps", e);
3112818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse        }
3123b76f0d34ed293c310605a66711cf3aba42f09e6Nicolas Prevot        return result;
3132818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse    }
3142818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse
315089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    protected Set<String> getRequiredApps() {
316089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        HashSet<String> requiredApps = new HashSet<String>();
317089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        requiredApps.addAll(mRequiredAppsList);
318089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        requiredApps.addAll(mVendorRequiredAppsList);
319089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        requiredApps.add(mMdmPackageName);
3202818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse        return requiredApps;
3212818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse    }
3222818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse
323089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse    private Set<String> getDisallowedApps() {
324089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        HashSet<String> disallowedApps = new HashSet<String>();
325089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        disallowedApps.addAll(mDisallowedAppsList);
326089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        disallowedApps.addAll(mVendorDisallowedAppsList);
327089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse        return disallowedApps;
328d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse    }
329d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse
330012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors    /**
331012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors     * Runs the next task when all packages have been deleted or shuts down the activity if package
332012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors     * deletion fails.
333012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors     */
334012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors    class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
335012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors        private final AtomicInteger mPackageCount = new AtomicInteger(0);
336012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors
337012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors        public PackageDeleteObserver(int packageCount) {
338012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors            this.mPackageCount.set(packageCount);
339012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors        }
340012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors
341012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors        @Override
342012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors        public void packageDeleted(String packageName, int returnCode) {
343012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors            if (returnCode != PackageManager.DELETE_SUCCEEDED) {
344012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors                ProvisionLogger.logw(
345418aaf4c4ff54e5f890bff004e120d8d5e5af755Nicolas Prevot                        "Could not finish the provisioning: package deletion failed");
346012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors                mCallback.onError();
347d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse                return;
348012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors            }
349012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors            int currentPackageCount = mPackageCount.decrementAndGet();
350012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors            if (currentPackageCount == 0) {
351089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                ProvisionLogger.logi("All non-required system apps with launcher icon, "
352089a4fada683bf5e6415e0fa8b2b62ecb333f9c7Sander Alewijnse                        + "and all disallowed apps have been uninstalled.");
353012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors                mCallback.onSuccess();
354012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors            }
355012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors        }
356012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors    }
357012c9bbe972e78cc7341000c3ec517ccfc27d22aAdam Connors
3582818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse    public abstract static class Callback {
3592818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse        public abstract void onSuccess();
3602818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse        public abstract void onError();
3612818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse    }
3622818d32aa494363a59d3b0f47695e317f47b689bSander Alewijnse}
363