• 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.ota;
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_USER;
22 
23 import static com.android.internal.util.Preconditions.checkNotNull;
24 
25 import android.app.admin.DevicePolicyManager;
26 import android.content.ComponentName;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.pm.PackageManager;
30 import android.content.pm.ResolveInfo;
31 import android.content.pm.UserInfo;
32 import android.os.UserHandle;
33 import android.os.UserManager;
34 import android.util.ArraySet;
35 import android.view.inputmethod.InputMethod;
36 
37 import com.android.internal.annotations.VisibleForTesting;
38 import com.android.managedprovisioning.analytics.MetricsWriterFactory;
39 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker;
40 import com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences;
41 import com.android.managedprovisioning.common.ProvisionLogger;
42 import com.android.managedprovisioning.common.SettingsFacade;
43 import com.android.managedprovisioning.model.ProvisioningParams;
44 import com.android.managedprovisioning.task.CrossProfileIntentFiltersSetter;
45 import com.android.managedprovisioning.task.DeleteNonRequiredAppsTask;
46 import com.android.managedprovisioning.task.DisableInstallShortcutListenersTask;
47 import com.android.managedprovisioning.task.DisallowAddUserTask;
48 import com.android.managedprovisioning.task.InstallExistingPackageTask;
49 import com.android.managedprovisioning.task.MigrateSystemAppsSnapshotTask;
50 import com.android.managedprovisioning.task.UpdateInteractAcrossProfilesAppOpTask;
51 
52 import java.util.List;
53 import java.util.function.IntFunction;
54 
55 /**
56  * After a system update, this class resets the cross-profile intent filters and performs any
57  * tasks necessary to bring the system up to date.
58  */
59 public class OtaController {
60 
61     private static final String TELECOM_PACKAGE = "com.android.server.telecom";
62 
63     private final Context mContext;
64     private final TaskExecutor mTaskExecutor;
65     private final CrossProfileIntentFiltersSetter mCrossProfileIntentFiltersSetter;
66 
67     private final UserManager mUserManager;
68     private final DevicePolicyManager mDevicePolicyManager;
69 
70     private final IntFunction<ArraySet<String>> mMissingSystemImeProvider;
71     private final ProvisioningAnalyticsTracker mProvisioningAnalyticsTracker;
72 
OtaController(Context context)73     public OtaController(Context context) {
74         this(context, new TaskExecutor(), new CrossProfileIntentFiltersSetter(context),
75                 userId -> getMissingSystemImePackages(context, UserHandle.of(userId)),
76                 new ProvisioningAnalyticsTracker(
77                         MetricsWriterFactory.getMetricsWriter(context, new SettingsFacade()),
78                         new ManagedProvisioningSharedPreferences(context)));
79     }
80 
81     @VisibleForTesting
OtaController(Context context, TaskExecutor taskExecutor, CrossProfileIntentFiltersSetter crossProfileIntentFiltersSetter, IntFunction<ArraySet<String>> missingSystemImeProvider, ProvisioningAnalyticsTracker provisioningAnalyticsTracker)82     OtaController(Context context, TaskExecutor taskExecutor,
83             CrossProfileIntentFiltersSetter crossProfileIntentFiltersSetter,
84             IntFunction<ArraySet<String>> missingSystemImeProvider,
85             ProvisioningAnalyticsTracker provisioningAnalyticsTracker) {
86         mContext = checkNotNull(context);
87         mTaskExecutor = checkNotNull(taskExecutor);
88         mCrossProfileIntentFiltersSetter = checkNotNull(crossProfileIntentFiltersSetter);
89         mProvisioningAnalyticsTracker = checkNotNull(provisioningAnalyticsTracker);
90 
91         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
92         mDevicePolicyManager = (DevicePolicyManager) context.getSystemService(
93                 Context.DEVICE_POLICY_SERVICE);
94 
95         mMissingSystemImeProvider = missingSystemImeProvider;
96     }
97 
run()98     public void run() {
99         if (mContext.getUserId() != UserHandle.USER_SYSTEM) {
100             return;
101         }
102         // Migrate snapshot files to use user serial number as file name.
103         mTaskExecutor.execute(
104                 UserHandle.USER_SYSTEM, new MigrateSystemAppsSnapshotTask(
105                         mContext, mTaskExecutor, mProvisioningAnalyticsTracker));
106 
107         // Check for device owner.
108         final int deviceOwnerUserId = mDevicePolicyManager.getDeviceOwnerUserId();
109         if (deviceOwnerUserId != UserHandle.USER_NULL) {
110             addDeviceOwnerTasks(deviceOwnerUserId, mContext);
111         }
112 
113         for (UserInfo userInfo : mUserManager.getUsers()) {
114             if (userInfo.isManagedProfile()) {
115                 addManagedProfileTasks(userInfo.id, mContext);
116             } else if (mDevicePolicyManager.getProfileOwnerAsUser(userInfo.id) != null) {
117                 addManagedUserTasks(userInfo.id, mContext);
118             } else {
119                 // if this user has managed profiles, reset the cross-profile intent filters between
120                 // this user and its managed profiles.
121                 mCrossProfileIntentFiltersSetter.resetFilters(userInfo.id);
122             }
123         }
124 
125         mTaskExecutor.execute(mContext.getUserId(), new UpdateInteractAcrossProfilesAppOpTask(
126                 mContext,
127                 /* params= */ null,
128                 mTaskExecutor,
129                 mProvisioningAnalyticsTracker
130         ));
131     }
132 
addDeviceOwnerTasks(final int userId, Context context)133     void addDeviceOwnerTasks(final int userId, Context context) {
134         ComponentName deviceOwner = mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser();
135         if (deviceOwner == null) {
136             // Shouldn't happen
137             ProvisionLogger.loge("No device owner found.");
138             return;
139         }
140 
141         // Build a set of fake params to be able to run the tasks
142         ProvisioningParams fakeParams = new ProvisioningParams.Builder()
143                 .setDeviceAdminComponentName(deviceOwner)
144                 .setProvisioningAction(ACTION_PROVISION_MANAGED_DEVICE)
145                 .build();
146 
147         mTaskExecutor.execute(userId,
148                 new DeleteNonRequiredAppsTask(false, context, fakeParams, mTaskExecutor,
149                         mProvisioningAnalyticsTracker));
150         mTaskExecutor.execute(userId,
151                 new DisallowAddUserTask(UserManager.isSplitSystemUser(), context, fakeParams,
152                         mTaskExecutor, mProvisioningAnalyticsTracker));
153     }
154 
addManagedProfileTasks(final int userId, Context context)155     void addManagedProfileTasks(final int userId, Context context) {
156         mUserManager.setUserRestriction(UserManager.DISALLOW_WALLPAPER, true,
157                 UserHandle.of(userId));
158         // Enabling telecom package as it supports managed profiles from N.
159         mTaskExecutor.execute(userId,
160                 new InstallExistingPackageTask(TELECOM_PACKAGE, context, null, mTaskExecutor,
161                         mProvisioningAnalyticsTracker));
162 
163         ComponentName profileOwner = mDevicePolicyManager.getProfileOwnerAsUser(userId);
164         if (profileOwner == null) {
165             // Shouldn't happen.
166             ProvisionLogger.loge("No profile owner on managed profile " + userId);
167             return;
168         }
169 
170         // Build a set of fake params to be able to run the tasks
171         ProvisioningParams fakeParams = new ProvisioningParams.Builder()
172                 .setDeviceAdminComponentName(profileOwner)
173                 .setProvisioningAction(ACTION_PROVISION_MANAGED_PROFILE)
174                 .build();
175         mTaskExecutor.execute(userId,
176                 new DisableInstallShortcutListenersTask(context, fakeParams, mTaskExecutor,
177                         mProvisioningAnalyticsTracker));
178         mTaskExecutor.execute(userId,
179                 new DeleteNonRequiredAppsTask(false, context, fakeParams, mTaskExecutor,
180                         mProvisioningAnalyticsTracker));
181 
182         // Copying missing system IMEs if necessary.
183         mMissingSystemImeProvider.apply(userId).forEach(packageName -> mTaskExecutor.execute(userId,
184                 new InstallExistingPackageTask(packageName, context, fakeParams, mTaskExecutor,
185                         mProvisioningAnalyticsTracker)));
186     }
187 
addManagedUserTasks(final int userId, Context context)188     void addManagedUserTasks(final int userId, Context context) {
189         ComponentName profileOwner = mDevicePolicyManager.getProfileOwnerAsUser(userId);
190         if (profileOwner == null) {
191             // Shouldn't happen.
192             ProvisionLogger.loge("No profile owner on managed user " + userId);
193             return;
194         }
195 
196         // Build a set of fake params to be able to run the tasks
197         ProvisioningParams fakeParams = new ProvisioningParams.Builder()
198                 .setDeviceAdminComponentName(profileOwner)
199                 .setProvisioningAction(ACTION_PROVISION_MANAGED_USER)
200                 .build();
201         mTaskExecutor.execute(userId,
202                 new DeleteNonRequiredAppsTask(false, context, fakeParams, mTaskExecutor,
203                         mProvisioningAnalyticsTracker));
204     }
205 
206     /**
207      * Returns IME packages that can be installed from the profile parent user.
208      *
209      * @param context {@link Context} of the caller.
210      * @param userHandle {@link UserHandle} that specifies the user.
211      * @return A set of IME package names that can be installed from the profile parent user.
212      */
getMissingSystemImePackages(Context context, UserHandle userHandle)213     private static ArraySet<String> getMissingSystemImePackages(Context context,
214             UserHandle userHandle) {
215         ArraySet<String> profileParentSystemImes = getInstalledSystemImePackages(context,
216                 context.getSystemService(UserManager.class).getProfileParent(userHandle));
217         ArraySet<String> installedSystemImes = getInstalledSystemImePackages(context, userHandle);
218         profileParentSystemImes.removeAll(installedSystemImes);
219         return profileParentSystemImes;
220     }
221 
222     /**
223      * Returns a set of the installed IME package names for the given user.
224      *
225      * @param context {@link Context} of the caller.
226      * @param userHandle {@link UserHandle} that specifies the user.
227      * @return A set of IME package names.
228      */
getInstalledSystemImePackages(Context context, UserHandle userHandle)229     private static ArraySet<String> getInstalledSystemImePackages(Context context,
230             UserHandle userHandle) {
231         PackageManager packageManager;
232         try {
233             packageManager = context
234                     .createPackageContextAsUser("android", 0, userHandle)
235                     .getPackageManager();
236         } catch (PackageManager.NameNotFoundException e) {
237             return new ArraySet<>();
238         }
239         List<ResolveInfo> resolveInfoList = packageManager.queryIntentServices(
240                 new Intent(InputMethod.SERVICE_INTERFACE),
241                 PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DISABLED_COMPONENTS);
242         ArraySet<String> result = new ArraySet<>();
243         for (ResolveInfo resolveInfo : resolveInfoList) {
244             result.add(resolveInfo.serviceInfo.packageName);
245         }
246         return result;
247     }
248 }
249