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 android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; 20 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; 21 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE; 22 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER; 23 import static com.android.internal.util.Preconditions.checkNotNull; 24 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.pm.ApplicationInfo; 28 import android.content.pm.PackageManager; 29 import android.content.pm.ResolveInfo; 30 import android.content.res.Resources; 31 import android.os.IBinder; 32 import android.os.RemoteException; 33 import android.os.ServiceManager; 34 import android.view.inputmethod.InputMethodInfo; 35 36 import com.android.internal.annotations.VisibleForTesting; 37 import com.android.internal.view.IInputMethodManager; 38 import com.android.managedprovisioning.R; 39 import com.android.managedprovisioning.common.ProvisionLogger; 40 import com.android.managedprovisioning.model.ProvisioningParams; 41 42 import java.util.Arrays; 43 import java.util.Collections; 44 import java.util.HashSet; 45 import java.util.List; 46 import java.util.Set; 47 48 /** 49 * Class that provides the apps that are not required on a managed device / profile according to the 50 * overlays provided via (vendor_|)required_apps_managed_(profile|device).xml. 51 */ 52 public class OverlayPackagesProvider { 53 54 private static final int DEVICE_OWNER = 0; 55 private static final int PROFILE_OWNER = 1; 56 private static final int MANAGED_USER = 2; 57 58 private final PackageManager mPm; 59 private final IInputMethodManager mIInputMethodManager; 60 private final String mDpcPackageName; 61 private final List<String> mRequiredAppsList; 62 private final List<String> mDisallowedAppsList; 63 private final List<String> mVendorRequiredAppsList; 64 private final List<String> mVendorDisallowedAppsList; 65 private final int mProvisioningType; 66 private final boolean mLeaveAllSystemAppsEnabled; 67 68 public OverlayPackagesProvider(Context context, ProvisioningParams params) { 69 this(context, params, getIInputMethodManager()); 70 } 71 72 @VisibleForTesting 73 OverlayPackagesProvider( 74 Context context, 75 ProvisioningParams params, 76 IInputMethodManager iInputMethodManager) { 77 mPm = checkNotNull(context.getPackageManager()); 78 mIInputMethodManager = checkNotNull(iInputMethodManager); 79 mDpcPackageName = checkNotNull(params.inferDeviceAdminPackageName()); 80 81 // For split system user devices that will have a system device owner, don't adjust the set 82 // of enabled packages in the system user as we expect the right set of packages to be 83 // enabled for the system user out of the box. For other devices, the set of available 84 // packages can vary depending on management state. 85 mLeaveAllSystemAppsEnabled = params.leaveAllSystemAppsEnabled || 86 params.provisioningAction.equals(ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE); 87 88 int requiredAppsListArray; 89 int vendorRequiredAppsListArray; 90 int disallowedAppsListArray; 91 int vendorDisallowedAppsListArray; 92 switch (params.provisioningAction) { 93 case ACTION_PROVISION_MANAGED_USER: 94 mProvisioningType = MANAGED_USER; 95 requiredAppsListArray = R.array.required_apps_managed_user; 96 disallowedAppsListArray = R.array.disallowed_apps_managed_user; 97 vendorRequiredAppsListArray = R.array.vendor_required_apps_managed_user; 98 vendorDisallowedAppsListArray = R.array.vendor_disallowed_apps_managed_user; 99 break; 100 case ACTION_PROVISION_MANAGED_PROFILE: 101 mProvisioningType = PROFILE_OWNER; 102 requiredAppsListArray = R.array.required_apps_managed_profile; 103 disallowedAppsListArray = R.array.disallowed_apps_managed_profile; 104 vendorRequiredAppsListArray = R.array.vendor_required_apps_managed_profile; 105 vendorDisallowedAppsListArray = R.array.vendor_disallowed_apps_managed_profile; 106 break; 107 case ACTION_PROVISION_MANAGED_DEVICE: 108 case ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE: 109 mProvisioningType = DEVICE_OWNER; 110 requiredAppsListArray = R.array.required_apps_managed_device; 111 disallowedAppsListArray = R.array.disallowed_apps_managed_device; 112 vendorRequiredAppsListArray = R.array.vendor_required_apps_managed_device; 113 vendorDisallowedAppsListArray = R.array.vendor_disallowed_apps_managed_device; 114 break; 115 default: 116 throw new IllegalArgumentException("Provisioning action " 117 + params.provisioningAction + " not implemented."); 118 } 119 120 Resources resources = context.getResources(); 121 mRequiredAppsList = Arrays.asList(resources.getStringArray(requiredAppsListArray)); 122 mDisallowedAppsList = Arrays.asList(resources.getStringArray(disallowedAppsListArray)); 123 mVendorRequiredAppsList = Arrays.asList( 124 resources.getStringArray(vendorRequiredAppsListArray)); 125 mVendorDisallowedAppsList = Arrays.asList( 126 resources.getStringArray(vendorDisallowedAppsListArray)); 127 } 128 129 /** 130 * Computes non-required apps. All the system apps with a launcher that are not in 131 * the required set of packages will be considered as non-required apps. 132 * 133 * Note: If an app is mistakenly listed as both required and disallowed, it will be treated as 134 * disallowed. 135 * 136 * @param userId The userId for which the non-required apps needs to be computed. 137 * @return the set of non-required apps. 138 */ 139 public Set<String> getNonRequiredApps(int userId) { 140 if (mLeaveAllSystemAppsEnabled) { 141 return Collections.emptySet(); 142 } 143 144 Set<String> nonRequiredApps = getCurrentAppsWithLauncher(userId); 145 // Newly installed system apps are uninstalled when they are not required and are either 146 // disallowed or have a launcher icon. 147 nonRequiredApps.removeAll(getRequiredApps()); 148 // Don't delete the system input method packages in case of Device owner provisioning. 149 if (mProvisioningType == DEVICE_OWNER || mProvisioningType == MANAGED_USER) { 150 nonRequiredApps.removeAll(getSystemInputMethods()); 151 } 152 nonRequiredApps.addAll(getDisallowedApps()); 153 return nonRequiredApps; 154 } 155 156 private Set<String> getCurrentAppsWithLauncher(int userId) { 157 Intent launcherIntent = new Intent(Intent.ACTION_MAIN); 158 launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER); 159 List<ResolveInfo> resolveInfos = mPm.queryIntentActivitiesAsUser(launcherIntent, 160 PackageManager.MATCH_UNINSTALLED_PACKAGES 161 | PackageManager.MATCH_DISABLED_COMPONENTS 162 | PackageManager.MATCH_DIRECT_BOOT_AWARE 163 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 164 userId); 165 Set<String> apps = new HashSet<>(); 166 for (ResolveInfo resolveInfo : resolveInfos) { 167 apps.add(resolveInfo.activityInfo.packageName); 168 } 169 return apps; 170 } 171 172 private Set<String> getSystemInputMethods() { 173 // InputMethodManager is final so it cannot be mocked. 174 // So, we're using IInputMethodManager directly because it can be mocked. 175 List<InputMethodInfo> inputMethods; 176 try { 177 inputMethods = mIInputMethodManager.getInputMethodList(); 178 } catch (RemoteException e) { 179 ProvisionLogger.loge("Could not communicate with IInputMethodManager", e); 180 return Collections.emptySet(); 181 } 182 Set<String> systemInputMethods = new HashSet<>(); 183 for (InputMethodInfo inputMethodInfo : inputMethods) { 184 ApplicationInfo applicationInfo = inputMethodInfo.getServiceInfo().applicationInfo; 185 if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 186 systemInputMethods.add(inputMethodInfo.getPackageName()); 187 } 188 } 189 return systemInputMethods; 190 } 191 192 private Set<String> getRequiredApps() { 193 HashSet<String> requiredApps = new HashSet<>(); 194 requiredApps.addAll(mRequiredAppsList); 195 requiredApps.addAll(mVendorRequiredAppsList); 196 requiredApps.add(mDpcPackageName); 197 return requiredApps; 198 } 199 200 private Set<String> getDisallowedApps() { 201 HashSet<String> disallowedApps = new HashSet<>(); 202 disallowedApps.addAll(mDisallowedAppsList); 203 disallowedApps.addAll(mVendorDisallowedAppsList); 204 return disallowedApps; 205 } 206 207 private static IInputMethodManager getIInputMethodManager() { 208 IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE); 209 return IInputMethodManager.Stub.asInterface(b); 210 } 211 } 212