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.R; 28 import com.android.managedprovisioning.common.ProvisionLogger; 29 import com.android.managedprovisioning.model.ProvisioningParams; 30 import com.android.managedprovisioning.task.nonrequiredapps.NonRequiredAppsLogic; 31 32 import java.util.HashSet; 33 import java.util.Set; 34 import java.util.concurrent.atomic.AtomicInteger; 35 36 /** 37 * Deletes all non-required apps. 38 * 39 * This task may be run when a profile (both for managed device and managed profile) is created. 40 * In that case the firstTimeCreation flag should be true. 41 * 42 * It should also be run after a system update with firstTimeCreation false. Note that only 43 * newly installed system apps will be deleted. 44 */ 45 public class DeleteNonRequiredAppsTask extends AbstractProvisioningTask { 46 private final PackageManager mPm; 47 private final NonRequiredAppsLogic mLogic; 48 DeleteNonRequiredAppsTask( boolean firstTimeCreation, Context context, ProvisioningParams params, Callback callback)49 public DeleteNonRequiredAppsTask( 50 boolean firstTimeCreation, 51 Context context, 52 ProvisioningParams params, 53 Callback callback) { 54 this( 55 context, 56 params, 57 callback, 58 new NonRequiredAppsLogic(context, firstTimeCreation, params)); 59 } 60 61 @VisibleForTesting DeleteNonRequiredAppsTask( Context context, ProvisioningParams params, Callback callback, NonRequiredAppsLogic logic)62 DeleteNonRequiredAppsTask( 63 Context context, 64 ProvisioningParams params, 65 Callback callback, 66 NonRequiredAppsLogic logic) { 67 super(context, params, callback); 68 69 mPm = checkNotNull(context.getPackageManager()); 70 mLogic = checkNotNull(logic); 71 } 72 73 @Override run(int userId)74 public void run(int userId) { 75 Set<String> packagesToDelete = mLogic.getSystemAppsToRemove(userId); 76 mLogic.maybeTakeSystemAppsSnapshot(userId); 77 78 // Remove all packages that are not currently installed 79 removeNonInstalledPackages(packagesToDelete, userId); 80 81 if (packagesToDelete.isEmpty()) { 82 success(); 83 return; 84 } 85 86 PackageDeleteObserver packageDeleteObserver = 87 new PackageDeleteObserver(packagesToDelete.size()); 88 for (String packageName : packagesToDelete) { 89 ProvisionLogger.logd("Deleting package [" + packageName + "] as user " + userId); 90 mPm.deletePackageAsUser(packageName, packageDeleteObserver, 91 PackageManager.DELETE_SYSTEM_APP, userId); 92 } 93 } 94 removeNonInstalledPackages(Set<String> packages, int userId)95 private void removeNonInstalledPackages(Set<String> packages, int userId) { 96 Set<String> toBeRemoved = new HashSet<>(); 97 for (String packageName : packages) { 98 try { 99 PackageInfo info = mPm.getPackageInfoAsUser( 100 packageName, 0 /* default flags */, 101 userId); 102 if (info == null) { 103 toBeRemoved.add(packageName); 104 } 105 } catch (PackageManager.NameNotFoundException e) { 106 toBeRemoved.add(packageName); 107 } 108 } 109 packages.removeAll(toBeRemoved); 110 } 111 112 @Override getStatusMsgId()113 public int getStatusMsgId() { 114 return R.string.progress_delete_non_required_apps; 115 } 116 117 /** 118 * Runs the next task when all packages have been deleted or shuts down the activity if package 119 * deletion fails. 120 */ 121 class PackageDeleteObserver extends IPackageDeleteObserver.Stub { 122 private final AtomicInteger mPackageCount = new AtomicInteger(0); 123 PackageDeleteObserver(int packageCount)124 public PackageDeleteObserver(int packageCount) { 125 this.mPackageCount.set(packageCount); 126 } 127 128 @Override packageDeleted(String packageName, int returnCode)129 public void packageDeleted(String packageName, int returnCode) { 130 if (returnCode != PackageManager.DELETE_SUCCEEDED) { 131 ProvisionLogger.logw( 132 "Could not finish the provisioning: package deletion failed"); 133 error(0); 134 return; 135 } 136 int currentPackageCount = mPackageCount.decrementAndGet(); 137 if (currentPackageCount == 0) { 138 ProvisionLogger.logi("All non-required system apps with launcher icon, " 139 + "and all disallowed apps have been uninstalled."); 140 success(); 141 } 142 } 143 } 144 } 145