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