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 NonRequiredAppsLogic( Context context, boolean newProfile, ProvisioningParams params)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 NonRequiredAppsLogic( Context context, IPackageManager iPackageManager, DevicePolicyManager devicePolicyManager, boolean newProfile, ProvisioningParams params, SystemAppsSnapshot snapshot, Utils utils)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 getSystemAppsToRemove(int userId)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 maybeTakeSystemAppsSnapshot(int userId)129 public void maybeTakeSystemAppsSnapshot(int userId) { 130 if (shouldDeleteSystemApps(userId)) { 131 mSnapshot.takeNewSnapshot(userId); 132 } 133 } 134 shouldDeleteSystemApps(int userId)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 getCase(int userId)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