Home | History | Annotate | Download | only in nonrequiredapps
      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