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         if (mContext.getUserId() != UserHandle.USER_SYSTEM) {
96             return;
97         }
98         // Migrate snapshot files to use user serial number as file name.
99         mTaskExecutor.execute(
100                 UserHandle.USER_SYSTEM, new MigrateSystemAppsSnapshotTask(
101                         mContext, mTaskExecutor, mProvisioningAnalyticsTracker));
102 
103         // Check for device owner.
104         final int deviceOwnerUserId = mDevicePolicyManager.getDeviceOwnerUserId();
105         if (deviceOwnerUserId != UserHandle.USER_NULL) {
106             addDeviceOwnerTasks(deviceOwnerUserId, mContext);
107         }
108 
109         for (UserInfo userInfo : mUserManager.getUsers()) {
110             if (userInfo.isManagedProfile()) {
111                 addManagedProfileTasks(userInfo.id, mContext);
112             } else if (mDevicePolicyManager.getProfileOwnerAsUser(userInfo.id) != null) {
113                 addManagedUserTasks(userInfo.id, mContext);
114             } else {
115                 // if this user has managed profiles, reset the cross-profile intent filters between
116                 // this user and its managed profiles.
117                 mDevicePolicyManager.resetDefaultCrossProfileIntentFilters(userInfo.id);
118             }
119         }
120 
121         mTaskExecutor.execute(mContext.getUserId(), new UpdateInteractAcrossProfilesAppOpTask(
122                 mContext,
123                 /* params= */ null,
124                 mTaskExecutor,
125                 mProvisioningAnalyticsTracker
126         ));
127     }
128 
addDeviceOwnerTasks(final int userId, Context context)129     void addDeviceOwnerTasks(final int userId, Context context) {
130         ComponentName deviceOwner = mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser();
131         if (deviceOwner == null) {
132             // Shouldn't happen
133             ProvisionLogger.loge("No device owner found.");
134             return;
135         }
136 
137         // Build a set of fake params to be able to run the tasks
138         ProvisioningParams fakeParams = new ProvisioningParams.Builder()
139                 .setDeviceAdminComponentName(deviceOwner)
140                 .setProvisioningAction(ACTION_PROVISION_MANAGED_DEVICE)
141                 .build();
142 
143         mTaskExecutor.execute(userId,
144                 new DeleteNonRequiredAppsTask(false, context, fakeParams, mTaskExecutor,
145                         mProvisioningAnalyticsTracker));
146         mTaskExecutor.execute(userId,
147                 new DisallowAddUserTask(UserManager.isHeadlessSystemUserMode(), context, fakeParams,
148                         mTaskExecutor, mProvisioningAnalyticsTracker));
149     }
150 
addManagedProfileTasks(final int userId, Context context)151     void addManagedProfileTasks(final int userId, Context context) {
152         mUserManager.setUserRestriction(UserManager.DISALLOW_WALLPAPER, true,
153                 UserHandle.of(userId));
154         // Enabling telecom package as it supports managed profiles from N.
155         mTaskExecutor.execute(userId,
156                 new InstallExistingPackageTask(TELECOM_PACKAGE, context, null, mTaskExecutor,
157                         mProvisioningAnalyticsTracker));
158 
159         ComponentName profileOwner = mDevicePolicyManager.getProfileOwnerAsUser(userId);
160         if (profileOwner == null) {
161             // Shouldn't happen.
162             ProvisionLogger.loge("No profile owner on managed profile " + userId);
163             return;
164         }
165 
166         // Build a set of fake params to be able to run the tasks
167         ProvisioningParams fakeParams = new ProvisioningParams.Builder()
168                 .setDeviceAdminComponentName(profileOwner)
169                 .setProvisioningAction(ACTION_PROVISION_MANAGED_PROFILE)
170                 .build();
171         mTaskExecutor.execute(userId,
172                 new DeleteNonRequiredAppsTask(false, context, fakeParams, mTaskExecutor,
173                         mProvisioningAnalyticsTracker));
174 
175         // Copying missing system IMEs if necessary.
176         mMissingSystemImeProvider.apply(userId).forEach(packageName -> mTaskExecutor.execute(userId,
177                 new InstallExistingPackageTask(packageName, context, fakeParams, mTaskExecutor,
178                         mProvisioningAnalyticsTracker)));
179     }
180 
addManagedUserTasks(final int userId, Context context)181     void addManagedUserTasks(final int userId, Context context) {
182         ComponentName profileOwner = mDevicePolicyManager.getProfileOwnerAsUser(userId);
183         if (profileOwner == null) {
184             // Shouldn't happen.
185             ProvisionLogger.loge("No profile owner on managed user " + userId);
186             return;
187         }
188 
189         // Build a set of fake params to be able to run the tasks
190         ProvisioningParams fakeParams = new ProvisioningParams.Builder()
191                 .setDeviceAdminComponentName(profileOwner)
192                 .setProvisioningAction(ACTION_PROVISION_MANAGED_USER)
193                 .build();
194         mTaskExecutor.execute(userId,
195                 new DeleteNonRequiredAppsTask(false, context, fakeParams, mTaskExecutor,
196                         mProvisioningAnalyticsTracker));
197     }
198 
199     /**
200      * Returns IME packages that can be installed from the profile parent user.
201      *
202      * @param context {@link Context} of the caller.
203      * @param userHandle {@link UserHandle} that specifies the user.
204      * @return A set of IME package names that can be installed from the profile parent user.
205      */
getMissingSystemImePackages(Context context, UserHandle userHandle)206     private static ArraySet<String> getMissingSystemImePackages(Context context,
207             UserHandle userHandle) {
208         ArraySet<String> profileParentSystemImes = getInstalledSystemImePackages(context,
209                 context.getSystemService(UserManager.class).getProfileParent(userHandle));
210         ArraySet<String> installedSystemImes = getInstalledSystemImePackages(context, userHandle);
211         profileParentSystemImes.removeAll(installedSystemImes);
212         return profileParentSystemImes;
213     }
214 
215     /**
216      * Returns a set of the installed IME package names for the given user.
217      *
218      * @param context {@link Context} of the caller.
219      * @param userHandle {@link UserHandle} that specifies the user.
220      * @return A set of IME package names.
221      */
getInstalledSystemImePackages(Context context, UserHandle userHandle)222     private static ArraySet<String> getInstalledSystemImePackages(Context context,
223             UserHandle userHandle) {
224         PackageManager packageManager;
225         try {
226             packageManager = context
227                     .createPackageContextAsUser("android", 0, userHandle)
228                     .getPackageManager();
229         } catch (PackageManager.NameNotFoundException e) {
230             return new ArraySet<>();
231         }
232         List<ResolveInfo> resolveInfoList = packageManager.queryIntentServices(
233                 new Intent(InputMethod.SERVICE_INTERFACE),
234                 PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DISABLED_COMPONENTS);
235         ArraySet<String> result = new ArraySet<>();
236         for (ResolveInfo resolveInfo : resolveInfoList) {
237             result.add(resolveInfo.serviceInfo.packageName);
238         }
239         return result;
240     }
241 }
242