• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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