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