1 /* 2 * Copyright 2016, 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.nonrequiredapps; 18 19 import static com.android.internal.util.Preconditions.checkNotNull; 20 21 import android.annotation.IntDef; 22 import android.app.AppGlobals; 23 import android.app.admin.DevicePolicyManager; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.pm.IPackageManager; 27 28 import com.android.internal.annotations.VisibleForTesting; 29 import com.android.managedprovisioning.common.IllegalProvisioningArgumentException; 30 import com.android.managedprovisioning.common.ProvisionLogger; 31 import com.android.managedprovisioning.common.Utils; 32 import com.android.managedprovisioning.model.ProvisioningParams; 33 34 import java.lang.annotation.Retention; 35 import java.lang.annotation.RetentionPolicy; 36 import java.util.Collections; 37 import java.util.Set; 38 39 /** 40 * Logic that calculates which system apps should be removed during profile creation and subsequent 41 * OTAs. It also decides whether a snapshot should be taken or not. 42 */ 43 public class NonRequiredAppsLogic { 44 45 @IntDef({ 46 Case.OTA_LEAVE_APPS, 47 Case.OTA_REMOVE_APPS, 48 Case.NEW_PROFILE_LEAVE_APPS, 49 Case.NEW_PROFILE_REMOVE_APPS 50 }) 51 @Retention(RetentionPolicy.SOURCE) 52 private @interface Case { 53 int OTA_LEAVE_APPS = 0; 54 int OTA_REMOVE_APPS = 1; 55 int NEW_PROFILE_LEAVE_APPS = 2; 56 int NEW_PROFILE_REMOVE_APPS = 3; 57 } 58 59 private final Context mContext; 60 private final IPackageManager mIPackageManager; 61 private final DevicePolicyManager mDevicePolicyManager; 62 private final boolean mNewProfile; 63 private final ProvisioningParams mParams; 64 private final SystemAppsSnapshot mSnapshot; 65 private final Utils mUtils; 66 67 public NonRequiredAppsLogic( 68 Context context, 69 boolean newProfile, 70 ProvisioningParams params) { 71 this( 72 context, 73 AppGlobals.getPackageManager(), 74 (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE), 75 newProfile, 76 params, 77 new SystemAppsSnapshot(context), 78 new Utils()); 79 } 80 81 @VisibleForTesting 82 NonRequiredAppsLogic( 83 Context context, 84 IPackageManager iPackageManager, 85 DevicePolicyManager devicePolicyManager, 86 boolean newProfile, 87 ProvisioningParams params, 88 SystemAppsSnapshot snapshot, 89 Utils utils) { 90 mContext = context; 91 mIPackageManager = checkNotNull(iPackageManager); 92 mDevicePolicyManager = checkNotNull(devicePolicyManager); 93 mNewProfile = newProfile; 94 mParams = checkNotNull(params); 95 mSnapshot = checkNotNull(snapshot); 96 mUtils = checkNotNull(utils); 97 } 98 99 public Set<String> getSystemAppsToRemove(int userId) { 100 if (!shouldDeleteSystemApps(userId)) { 101 return Collections.emptySet(); 102 } 103 104 // Start with all system apps 105 Set<String> newSystemApps = mUtils.getCurrentSystemApps(mIPackageManager, userId); 106 107 // Remove the ones that were already present in the last snapshot only when OTA 108 if (!mNewProfile) { 109 newSystemApps.removeAll(mSnapshot.getSnapshot(userId)); 110 } 111 ComponentName deviceAdminComponentName; 112 try { 113 deviceAdminComponentName = mParams.inferDeviceAdminComponentName( 114 mUtils, mContext, userId); 115 } catch (IllegalProvisioningArgumentException ex) { 116 // Should not happen 117 throw new RuntimeException("Failed to infer device admin component name", ex); 118 } 119 // Get the packages from the black/white lists 120 Set<String> packagesToDelete = mDevicePolicyManager.getDisallowedSystemApps( 121 deviceAdminComponentName, userId, mParams.provisioningAction); 122 123 // Retain only new system apps 124 packagesToDelete.retainAll(newSystemApps); 125 126 return packagesToDelete; 127 } 128 129 public void maybeTakeSystemAppsSnapshot(int userId) { 130 if (shouldDeleteSystemApps(userId)) { 131 mSnapshot.takeNewSnapshot(userId); 132 } 133 } 134 135 private boolean shouldDeleteSystemApps(int userId) { 136 @Case int which = getCase(userId); 137 return (Case.NEW_PROFILE_REMOVE_APPS == which) || (Case.OTA_REMOVE_APPS == which); 138 } 139 140 @Case 141 private int getCase(int userId) { 142 if (mNewProfile) { 143 if (mParams.leaveAllSystemAppsEnabled) { 144 return Case.NEW_PROFILE_LEAVE_APPS; 145 } else { 146 return Case.NEW_PROFILE_REMOVE_APPS; 147 } 148 } else { 149 if (mSnapshot.hasSnapshot(userId)) { 150 return Case.OTA_REMOVE_APPS; 151 } else { 152 return Case.OTA_LEAVE_APPS; 153 } 154 } 155 } 156 } 157