• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
OverlayPackagesProvider(Context context, ProvisioningParams params)68     public OverlayPackagesProvider(Context context, ProvisioningParams params) {
69         this(context, params, getIInputMethodManager());
70     }
71 
72     @VisibleForTesting
OverlayPackagesProvider( Context context, ProvisioningParams params, IInputMethodManager iInputMethodManager)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      */
getNonRequiredApps(int userId)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 
getCurrentAppsWithLauncher(int userId)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 
getSystemInputMethods()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 
getRequiredApps()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 
getDisallowedApps()200     private Set<String> getDisallowedApps() {
201         HashSet<String> disallowedApps = new HashSet<>();
202         disallowedApps.addAll(mDisallowedAppsList);
203         disallowedApps.addAll(mVendorDisallowedAppsList);
204         return disallowedApps;
205     }
206 
getIInputMethodManager()207     private static IInputMethodManager getIInputMethodManager() {
208         IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
209         return IInputMethodManager.Stub.asInterface(b);
210     }
211 }
212