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 org.junit.Assert.assertEquals; 20 import static org.junit.Assert.fail; 21 import static org.mockito.Mockito.mock; 22 import static org.mockito.Mockito.never; 23 import static org.mockito.Mockito.verify; 24 import static org.mockito.Mockito.when; 25 26 import android.app.admin.DevicePolicyManager; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.pm.PackageManager; 30 import android.content.pm.UserInfo; 31 import android.os.UserHandle; 32 import android.os.UserManager; 33 import android.util.ArraySet; 34 import android.util.Pair; 35 36 import androidx.test.InstrumentationRegistry; 37 import androidx.test.filters.SmallTest; 38 39 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker; 40 import com.android.managedprovisioning.task.AbstractProvisioningTask; 41 import com.android.managedprovisioning.task.CrossProfileIntentFiltersSetter; 42 import com.android.managedprovisioning.task.DeleteNonRequiredAppsTask; 43 import com.android.managedprovisioning.task.DisableInstallShortcutListenersTask; 44 import com.android.managedprovisioning.task.DisallowAddUserTask; 45 import com.android.managedprovisioning.task.InstallExistingPackageTask; 46 import com.android.managedprovisioning.task.MigrateSystemAppsSnapshotTask; 47 import com.android.managedprovisioning.task.UpdateInteractAcrossProfilesAppOpTask; 48 49 import org.junit.Before; 50 import org.junit.Test; 51 import org.mockito.Mock; 52 import org.mockito.MockitoAnnotations; 53 54 import java.util.ArrayList; 55 import java.util.Collections; 56 import java.util.List; 57 import java.util.function.IntFunction; 58 59 /** 60 * Unit tests for {@link OtaController}. 61 */ 62 @SmallTest 63 public class OtaControllerTest { 64 private static final int DEVICE_OWNER_USER_ID = 12; 65 private static final int MANAGED_PROFILE_USER_ID = 15; 66 private static final int MANAGED_USER_USER_ID = 18; 67 68 private static final String DUMMY_SYSTEM_IME_PACKAGE_NAME = 69 "com.android.inputmethod.dummysystemime"; 70 71 private static final ComponentName ADMIN_COMPONENT = new ComponentName("com.test.admin", 72 ".AdminReceiver"); 73 74 private static final IntFunction<ArraySet<String>> NO_MISSING_SYSTEM_IME_PROVIDER 75 = userHandle -> new ArraySet<>(); 76 77 @Mock private Context mContext; 78 @Mock private DevicePolicyManager mDevicePolicyManager; 79 @Mock private PackageManager mPackageManager; 80 @Mock private UserManager mUserManager; 81 @Mock private CrossProfileIntentFiltersSetter mCrossProfileIntentFiltersSetter; 82 @Mock private ProvisioningAnalyticsTracker mProvisioningAnalyticsTracker; 83 84 private TaskExecutor mTaskExecutor; 85 86 private List<Pair<Integer, AbstractProvisioningTask>> mTasks = new ArrayList<>(); 87 private List<UserInfo> mUsers = new ArrayList<>(); 88 private List<UserInfo> mProfiles = new ArrayList<>(); 89 90 @Before setUp()91 public void setUp() { 92 MockitoAnnotations.initMocks(this); 93 94 when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) 95 .thenReturn(mDevicePolicyManager); 96 when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); 97 when(mContext.getPackageManager()).thenReturn(mPackageManager); 98 when(mContext.getResources()) 99 .thenReturn(InstrumentationRegistry.getTargetContext().getResources()); 100 101 when(mUserManager.getUsers()).thenReturn(mUsers); 102 when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(mProfiles); 103 104 mTaskExecutor = new FakeTaskExecutor(); 105 106 addSystemUser(); 107 } 108 109 @Test testDeviceOwnerSystemUser()110 public void testDeviceOwnerSystemUser() { 111 OtaController controller = new OtaController(mContext, mTaskExecutor, 112 mCrossProfileIntentFiltersSetter, NO_MISSING_SYSTEM_IME_PROVIDER, 113 mProvisioningAnalyticsTracker); 114 115 // GIVEN that there is a device owner on the system user 116 setDeviceOwner(UserHandle.USER_SYSTEM, ADMIN_COMPONENT); 117 118 // WHEN running the OtaController 119 controller.run(); 120 121 // THEN the task list should contain these tasks. 122 assertTaskList( 123 Pair.create(UserHandle.USER_SYSTEM, MigrateSystemAppsSnapshotTask.class), 124 Pair.create(UserHandle.USER_SYSTEM, DeleteNonRequiredAppsTask.class), 125 Pair.create(UserHandle.USER_SYSTEM, DisallowAddUserTask.class), 126 Pair.create(UserHandle.USER_SYSTEM, UpdateInteractAcrossProfilesAppOpTask.class)); 127 128 // THEN cross profile intent filters setter should be invoked for system user 129 verify(mCrossProfileIntentFiltersSetter).resetFilters(UserHandle.USER_SYSTEM); 130 } 131 132 @Test testDeviceOwnerSeparate()133 public void testDeviceOwnerSeparate() { 134 OtaController controller = new OtaController(mContext, mTaskExecutor, 135 mCrossProfileIntentFiltersSetter, NO_MISSING_SYSTEM_IME_PROVIDER, 136 mProvisioningAnalyticsTracker); 137 138 // GIVEN that there is a device owner on a non-system meat user 139 addMeatUser(DEVICE_OWNER_USER_ID); 140 setDeviceOwner(DEVICE_OWNER_USER_ID, ADMIN_COMPONENT); 141 142 // WHEN running the OtaController 143 controller.run(); 144 145 // THEN the task list should contain DeleteNonRequiredAppsTask and DisallowAddUserTask 146 assertTaskList( 147 Pair.create(UserHandle.USER_SYSTEM, MigrateSystemAppsSnapshotTask.class), 148 Pair.create(DEVICE_OWNER_USER_ID, DeleteNonRequiredAppsTask.class), 149 Pair.create(DEVICE_OWNER_USER_ID, DisallowAddUserTask.class), 150 Pair.create(UserHandle.USER_SYSTEM, UpdateInteractAcrossProfilesAppOpTask.class)); 151 152 // THEN cross profile intent filters setter should be invoked for both users 153 verify(mCrossProfileIntentFiltersSetter).resetFilters(UserHandle.USER_SYSTEM); 154 verify(mCrossProfileIntentFiltersSetter).resetFilters(DEVICE_OWNER_USER_ID); 155 } 156 157 @Test testManagedProfileWithoutMissingSystemIme()158 public void testManagedProfileWithoutMissingSystemIme() { 159 OtaController controller = new OtaController(mContext, mTaskExecutor, 160 mCrossProfileIntentFiltersSetter, NO_MISSING_SYSTEM_IME_PROVIDER, 161 mProvisioningAnalyticsTracker); 162 163 // GIVEN that there is a managed profile 164 addManagedProfile(MANAGED_PROFILE_USER_ID, ADMIN_COMPONENT); 165 166 // WHEN running the OtaController 167 controller.run(); 168 169 // THEN the task list should contain these tasks. 170 assertTaskList( 171 Pair.create(UserHandle.USER_SYSTEM, MigrateSystemAppsSnapshotTask.class), 172 Pair.create(MANAGED_PROFILE_USER_ID, InstallExistingPackageTask.class), 173 Pair.create(MANAGED_PROFILE_USER_ID, DisableInstallShortcutListenersTask.class), 174 Pair.create(MANAGED_PROFILE_USER_ID, DeleteNonRequiredAppsTask.class), 175 Pair.create(UserHandle.USER_SYSTEM, UpdateInteractAcrossProfilesAppOpTask.class)); 176 177 // THEN the cross profile intent filters should be reset 178 verify(mCrossProfileIntentFiltersSetter).resetFilters(UserHandle.USER_SYSTEM); 179 verify(mCrossProfileIntentFiltersSetter, never()).resetFilters(MANAGED_PROFILE_USER_ID); 180 181 // THEN the DISALLOW_WALLPAPER restriction should be set 182 verify(mUserManager).setUserRestriction(UserManager.DISALLOW_WALLPAPER, true, 183 UserHandle.of(MANAGED_PROFILE_USER_ID)); 184 } 185 186 @Test testManagedProfileWithMissingSystemIme()187 public void testManagedProfileWithMissingSystemIme() { 188 IntFunction<ArraySet<String>> missingSystemImeProvider = 189 (IntFunction<ArraySet<String>>) mock(IntFunction.class); 190 191 OtaController controller = new OtaController(mContext, mTaskExecutor, 192 mCrossProfileIntentFiltersSetter, missingSystemImeProvider, 193 mProvisioningAnalyticsTracker); 194 195 // GIVEN that there is a managed profile 196 addManagedProfile(MANAGED_PROFILE_USER_ID, ADMIN_COMPONENT); 197 198 // GIVEN that the managed profile does not have DUMMY_SYSTEM_IME_PACKAGE_NAME. 199 ArraySet<String> missingImes = new ArraySet<>(); 200 missingImes.add(DUMMY_SYSTEM_IME_PACKAGE_NAME); 201 when(missingSystemImeProvider.apply(MANAGED_PROFILE_USER_ID)).thenReturn(missingImes); 202 203 // WHEN running the OtaController 204 controller.run(); 205 206 // THEN the task list should contain these tasks. 207 assertTaskList( 208 Pair.create(UserHandle.USER_SYSTEM, MigrateSystemAppsSnapshotTask.class), 209 Pair.create(MANAGED_PROFILE_USER_ID, InstallExistingPackageTask.class), 210 Pair.create(MANAGED_PROFILE_USER_ID, InstallExistingPackageTask.class), 211 Pair.create(MANAGED_PROFILE_USER_ID, DisableInstallShortcutListenersTask.class), 212 Pair.create(MANAGED_PROFILE_USER_ID, DeleteNonRequiredAppsTask.class), 213 Pair.create(UserHandle.USER_SYSTEM, UpdateInteractAcrossProfilesAppOpTask.class)); 214 215 // THEN the cross profile intent filters should be reset 216 verify(mCrossProfileIntentFiltersSetter).resetFilters(UserHandle.USER_SYSTEM); 217 verify(mCrossProfileIntentFiltersSetter, never()).resetFilters(MANAGED_PROFILE_USER_ID); 218 219 // THEN the DISALLOW_WALLPAPER restriction should be set 220 verify(mUserManager).setUserRestriction(UserManager.DISALLOW_WALLPAPER, true, 221 UserHandle.of(MANAGED_PROFILE_USER_ID)); 222 223 // THEN the DUMMY_SYSTEM_IME_PACKAGE_NAME should be installed. 224 assertInstallExistingPackageTask(MANAGED_PROFILE_USER_ID, DUMMY_SYSTEM_IME_PACKAGE_NAME); 225 } 226 227 @Test testManagedUser()228 public void testManagedUser() { 229 OtaController controller = new OtaController(mContext, mTaskExecutor, 230 mCrossProfileIntentFiltersSetter, NO_MISSING_SYSTEM_IME_PROVIDER, 231 mProvisioningAnalyticsTracker); 232 233 // GIVEN that there is a managed profile 234 addManagedUser(MANAGED_USER_USER_ID, ADMIN_COMPONENT); 235 236 // WHEN running the OtaController 237 controller.run(); 238 239 // THEN the task list should contain these tasks. 240 assertTaskList( 241 Pair.create(UserHandle.USER_SYSTEM, MigrateSystemAppsSnapshotTask.class), 242 Pair.create(MANAGED_USER_USER_ID, DeleteNonRequiredAppsTask.class), 243 Pair.create(UserHandle.USER_SYSTEM, UpdateInteractAcrossProfilesAppOpTask.class)); 244 } 245 246 private class FakeTaskExecutor extends TaskExecutor { 247 FakeTaskExecutor()248 public FakeTaskExecutor() { 249 super(); 250 } 251 252 @Override execute(int userId, AbstractProvisioningTask task)253 public synchronized void execute(int userId, AbstractProvisioningTask task) { 254 mTasks.add(Pair.create(userId, task)); 255 } 256 } 257 addMeatUser(int userId)258 private void addMeatUser(int userId) { 259 UserInfo ui = new UserInfo(userId, null, 0); 260 mUsers.add(ui); 261 when(mUserManager.getProfiles(userId)).thenReturn(Collections.singletonList(ui)); 262 } 263 setDeviceOwner(int userId, ComponentName admin)264 private void setDeviceOwner(int userId, ComponentName admin) { 265 when(mDevicePolicyManager.getDeviceOwnerUserId()).thenReturn(userId); 266 when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(admin); 267 } 268 addManagedProfile(int userId, ComponentName admin)269 private void addManagedProfile(int userId, ComponentName admin) { 270 UserInfo ui = new UserInfo(userId, null, UserInfo.FLAG_MANAGED_PROFILE); 271 mUsers.add(ui); 272 when(mDevicePolicyManager.getProfileOwnerAsUser(userId)).thenReturn(admin); 273 when(mUserManager.getProfiles(userId)).thenReturn(Collections.singletonList(ui)); 274 mProfiles.add(ui); 275 } 276 addManagedUser(int userId, ComponentName admin)277 private void addManagedUser(int userId, ComponentName admin) { 278 UserInfo ui = new UserInfo(userId, null, 0); 279 mUsers.add(ui); 280 when(mDevicePolicyManager.getProfileOwnerAsUser(userId)).thenReturn(admin); 281 } 282 addSystemUser()283 private void addSystemUser() { 284 UserInfo ui = new UserInfo(UserHandle.USER_SYSTEM, null, UserInfo.FLAG_PRIMARY); 285 mUsers.add(ui); 286 mProfiles.add(ui); 287 } 288 assertTaskList(Pair<Integer, Class>.... tasks)289 private void assertTaskList(Pair<Integer, Class>... tasks) { 290 assertEquals(tasks.length, mTasks.size()); 291 292 for (Pair<Integer, Class> task : tasks) { 293 assertTaskListContains(task.first, task.second); 294 } 295 } 296 assertTaskListContains(Integer userId, Class taskClass)297 private void assertTaskListContains(Integer userId, Class taskClass) { 298 for (Pair<Integer, AbstractProvisioningTask> task : mTasks) { 299 if (userId == task.first && taskClass.isInstance(task.second)) { 300 return; 301 } 302 } 303 fail("Task for class " + taskClass + " and userId " + userId + " not executed"); 304 } 305 assertInstallExistingPackageTask(int userId, String packageName)306 private void assertInstallExistingPackageTask(int userId, String packageName) { 307 for (Pair<Integer, AbstractProvisioningTask> task : mTasks) { 308 if (userId != task.first || !InstallExistingPackageTask.class.isInstance(task.second)) { 309 continue; 310 } 311 InstallExistingPackageTask installExistingPackageTask = 312 (InstallExistingPackageTask) task.second; 313 if (packageName.equals(installExistingPackageTask.getPackageName())) { 314 return; 315 } 316 } 317 fail("InstallExistingPackageTask for " + packageName + " and userId " + userId 318 + " not executed"); 319 } 320 } 321