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