1 /* 2 * Copyright 2014, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.managedprovisioning.task; 18 19 import static com.android.internal.util.Preconditions.checkNotNull; 20 21 import android.content.Context; 22 import android.content.pm.IPackageDeleteObserver; 23 import android.content.pm.PackageInfo; 24 import android.content.pm.PackageManager; 25 26 import com.android.internal.annotations.VisibleForTesting; 27 import com.android.managedprovisioning.analytics.MetricsWriterFactory; 28 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker; 29 import com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences; 30 import com.android.managedprovisioning.common.ProvisionLogger; 31 import com.android.managedprovisioning.common.SettingsFacade; 32 import com.android.managedprovisioning.model.ProvisioningParams; 33 import com.android.managedprovisioning.task.nonrequiredapps.NonRequiredAppsLogic; 34 35 import java.util.HashSet; 36 import java.util.Set; 37 import java.util.concurrent.atomic.AtomicInteger; 38 39 /** 40 * Deletes all non-required apps. 41 * 42 * This task may be run when a profile (both for managed device and managed profile) is created. 43 * In that case the firstTimeCreation flag should be true. 44 * 45 * It should also be run after a system update with firstTimeCreation false. Note that only 46 * newly installed system apps will be deleted. 47 */ 48 public class DeleteNonRequiredAppsTask extends AbstractProvisioningTask { 49 private final PackageManager mPm; 50 private final NonRequiredAppsLogic mLogic; 51 DeleteNonRequiredAppsTask( boolean firstTimeCreation, Context context, ProvisioningParams params, Callback callback)52 public DeleteNonRequiredAppsTask( 53 boolean firstTimeCreation, 54 Context context, 55 ProvisioningParams params, 56 Callback callback) { 57 this( 58 context, 59 params, 60 callback, 61 new NonRequiredAppsLogic(context, firstTimeCreation, params), 62 new ProvisioningAnalyticsTracker( 63 MetricsWriterFactory.getMetricsWriter(context, new SettingsFacade()), 64 new ManagedProvisioningSharedPreferences(context))); 65 } 66 67 @VisibleForTesting DeleteNonRequiredAppsTask( boolean firstTimeCreation, Context context, ProvisioningParams params, Callback callback, ProvisioningAnalyticsTracker provisioningAnalyticsTracker)68 public DeleteNonRequiredAppsTask( 69 boolean firstTimeCreation, 70 Context context, 71 ProvisioningParams params, 72 Callback callback, 73 ProvisioningAnalyticsTracker provisioningAnalyticsTracker) { 74 this( 75 context, 76 params, 77 callback, 78 new NonRequiredAppsLogic(context, firstTimeCreation, params), 79 provisioningAnalyticsTracker); 80 } 81 82 @VisibleForTesting DeleteNonRequiredAppsTask( Context context, ProvisioningParams params, Callback callback, NonRequiredAppsLogic logic, ProvisioningAnalyticsTracker provisioningAnalyticsTracker)83 DeleteNonRequiredAppsTask( 84 Context context, 85 ProvisioningParams params, 86 Callback callback, 87 NonRequiredAppsLogic logic, 88 ProvisioningAnalyticsTracker provisioningAnalyticsTracker) { 89 super(context, params, callback, provisioningAnalyticsTracker); 90 91 mPm = checkNotNull(context.getPackageManager()); 92 mLogic = checkNotNull(logic); 93 } 94 95 @Override run(int userId)96 public void run(int userId) { 97 Set<String> packagesToDelete = mLogic.getSystemAppsToRemove(userId); 98 mLogic.maybeTakeSystemAppsSnapshot(userId); 99 100 // Remove all packages that are not currently installed 101 removeNonInstalledPackages(packagesToDelete, userId); 102 103 if (packagesToDelete.isEmpty()) { 104 success(); 105 return; 106 } 107 108 PackageDeleteObserver packageDeleteObserver = 109 new PackageDeleteObserver(packagesToDelete.size()); 110 for (String packageName : packagesToDelete) { 111 ProvisionLogger.logd("Deleting package [" + packageName + "] as user " + userId); 112 mPm.deletePackageAsUser(packageName, packageDeleteObserver, 113 PackageManager.DELETE_SYSTEM_APP, userId); 114 } 115 } 116 removeNonInstalledPackages(Set<String> packages, int userId)117 private void removeNonInstalledPackages(Set<String> packages, int userId) { 118 Set<String> toBeRemoved = new HashSet<>(); 119 for (String packageName : packages) { 120 try { 121 PackageInfo info = mPm.getPackageInfoAsUser( 122 packageName, 0 /* default flags */, 123 userId); 124 if (info == null) { 125 toBeRemoved.add(packageName); 126 } 127 } catch (PackageManager.NameNotFoundException e) { 128 toBeRemoved.add(packageName); 129 } 130 } 131 packages.removeAll(toBeRemoved); 132 } 133 134 /** 135 * Runs the next task when all packages have been deleted or shuts down the activity if package 136 * deletion fails. 137 */ 138 class PackageDeleteObserver extends IPackageDeleteObserver.Stub { 139 private final AtomicInteger mPackageCount = new AtomicInteger(0); 140 PackageDeleteObserver(int packageCount)141 public PackageDeleteObserver(int packageCount) { 142 this.mPackageCount.set(packageCount); 143 } 144 145 @Override packageDeleted(String packageName, int returnCode)146 public void packageDeleted(String packageName, int returnCode) { 147 if (returnCode != PackageManager.DELETE_SUCCEEDED) { 148 ProvisionLogger.logw( 149 "Could not finish the provisioning: package deletion failed"); 150 error(0); 151 return; 152 } 153 int currentPackageCount = mPackageCount.decrementAndGet(); 154 if (currentPackageCount == 0) { 155 ProvisionLogger.logi("All non-required system apps with launcher icon, " 156 + "and all disallowed apps have been uninstalled."); 157 success(); 158 } 159 } 160 } 161 } 162