1 /* 2 * Copyright (C) 2015 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.task; 18 19 import android.content.pm.ActivityInfo; 20 import android.content.pm.ApplicationInfo; 21 import android.content.pm.IPackageDeleteObserver; 22 import android.content.pm.IPackageManager; 23 import android.content.pm.PackageInfo; 24 import android.content.pm.PackageManager; 25 import android.content.pm.PackageManager.NameNotFoundException; 26 import android.content.pm.ParceledListSlice; 27 import android.content.pm.ResolveInfo; 28 import android.content.pm.ServiceInfo; 29 import android.content.res.Resources; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.os.RemoteException; 33 import android.test.AndroidTestCase; 34 import android.test.mock.MockPackageManager; 35 import android.test.suitebuilder.annotation.SmallTest; 36 import android.view.inputmethod.InputMethodInfo; 37 38 import com.android.internal.view.IInputMethodManager; 39 40 import java.io.File; 41 import java.util.Arrays; 42 import java.util.ArrayList; 43 import java.util.Collections; 44 import java.util.HashSet; 45 import java.util.List; 46 import java.util.Set; 47 48 import static org.mockito.Mockito.any; 49 import static org.mockito.Mockito.anyInt; 50 import static org.mockito.Mockito.anyString; 51 import static org.mockito.Mockito.doAnswer; 52 import static org.mockito.Mockito.eq; 53 import static org.mockito.Mockito.mock; 54 import static org.mockito.Mockito.times; 55 import static org.mockito.Mockito.verify; 56 import static org.mockito.Mockito.when; 57 58 import org.mockito.invocation.InvocationOnMock; 59 import org.mockito.stubbing.Answer; 60 import org.mockito.Mock; 61 import org.mockito.MockitoAnnotations; 62 63 public class DeleteNonRequiredAppsTaskTest extends AndroidTestCase { 64 65 private @Mock Resources mResources; 66 private @Mock IPackageManager mIPackageManager; 67 private @Mock IInputMethodManager mIInputMethodManager; 68 private @Mock DeleteNonRequiredAppsTask.Callback mCallback; 69 private @Mock Context mTestContext; 70 71 private FakePackageManager mPackageManager; 72 73 private static final String TEST_MDM_PACKAGE_NAME = "mdm.package.name"; 74 private static final int TEST_USER_ID = 0; 75 private Set<String> mDeletedApps; 76 private String[] mSystemAppsWithLauncher; 77 private Set<String> mInstalledApplications; 78 79 @Override setUp()80 protected void setUp() throws Exception { 81 // this is necessary for mockito to work 82 System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString()); 83 84 MockitoAnnotations.initMocks(this); 85 86 mPackageManager = new FakePackageManager(); 87 88 when(mTestContext.getResources()).thenReturn(mResources); 89 when(mTestContext.getPackageManager()).thenReturn(mPackageManager); 90 when(mTestContext.getFilesDir()).thenReturn(getContext().getFilesDir()); 91 92 mDeletedApps = new HashSet<String>(); 93 94 setSystemInputMethods(); 95 setRequiredAppsManagedDevice(); 96 setVendorRequiredAppsManagedDevice(); 97 setDisallowedAppsManagedDevice(); 98 setVendorDisallowedAppsManagedDevice(); 99 setRequiredAppsManagedProfile(); 100 setVendorRequiredAppsManagedProfile(); 101 setDisallowedAppsManagedProfile(); 102 setVendorDisallowedAppsManagedProfile(); 103 setRequiredAppsManagedUser(); 104 setVendorRequiredAppsManagedUser(); 105 setDisallowedAppsManagedUser(); 106 setVendorDisallowedAppsManagedUser(); 107 } 108 109 // We run most methods for device owner only, and we'll assume they also work for profile owner. 110 @SmallTest testOnlyAppsWithLauncherDeletedByDefault()111 public void testOnlyAppsWithLauncherDeletedByDefault() { 112 setSystemAppsWithLauncher("app.a"); 113 setInstalledSystemApps( "app.a", "app.b"); 114 115 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, true, false); 116 117 assertDeletedApps("app.a"); 118 verify(mCallback, times(1)).onSuccess(); 119 } 120 121 @SmallTest testDeviceOwnerRequiredAppsNotDeleted()122 public void testDeviceOwnerRequiredAppsNotDeleted() { 123 setSystemAppsWithLauncher("app.a", "app.b", "app.c"); 124 setInstalledSystemApps("app.a", "app.b", "app.c"); 125 setRequiredAppsManagedDevice("app.a"); 126 setVendorRequiredAppsManagedDevice("app.b"); 127 128 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, true, false); 129 130 assertDeletedApps("app.c"); 131 verify(mCallback, times(1)).onSuccess(); 132 } 133 134 @SmallTest testProfileOwnerRequiredAppsNotDeleted()135 public void testProfileOwnerRequiredAppsNotDeleted() { 136 setSystemAppsWithLauncher("app.a", "app.b", "app.c"); 137 setInstalledSystemApps("app.a", "app.b", "app.c"); 138 setRequiredAppsManagedProfile("app.a"); 139 setVendorRequiredAppsManagedProfile("app.b"); 140 141 runTask(DeleteNonRequiredAppsTask.PROFILE_OWNER, true, false); 142 143 assertDeletedApps("app.c"); 144 verify(mCallback, times(1)).onSuccess(); 145 } 146 147 @SmallTest testManagedUserRequiredAppsNotDeleted()148 public void testManagedUserRequiredAppsNotDeleted() { 149 setSystemAppsWithLauncher("app.a", "app.b", "app.c"); 150 setInstalledSystemApps("app.a", "app.b", "app.c"); 151 setRequiredAppsManagedUser("app.a"); 152 setVendorRequiredAppsManagedUser("app.b"); 153 154 runTask(DeleteNonRequiredAppsTask.MANAGED_USER, true, false); 155 156 assertDeletedApps("app.c"); 157 verify(mCallback, times(1)).onSuccess(); 158 } 159 160 @SmallTest testMdmNotDeleted()161 public void testMdmNotDeleted() { 162 setSystemAppsWithLauncher(TEST_MDM_PACKAGE_NAME); 163 setInstalledSystemApps(TEST_MDM_PACKAGE_NAME); 164 165 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, true, false); 166 167 assertDeletedApps(); 168 verify(mCallback, times(1)).onSuccess(); 169 } 170 171 @SmallTest testDisallowedAppsDeletedEvenIfNoLauncher()172 public void testDisallowedAppsDeletedEvenIfNoLauncher() { 173 setSystemAppsWithLauncher(); 174 setInstalledSystemApps("app.a", "app.b", "app.c"); 175 setDisallowedAppsManagedDevice("app.a"); 176 setVendorDisallowedAppsManagedDevice("app.b"); 177 178 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, true, false); 179 180 assertDeletedApps("app.a", "app.b"); 181 verify(mCallback, times(1)).onSuccess(); 182 } 183 184 @SmallTest testDeviceOwnerImesNotDeleted()185 public void testDeviceOwnerImesNotDeleted() { 186 setSystemAppsWithLauncher("app.a", "app.b"); 187 setInstalledSystemApps("app.a", "app.b"); 188 setSystemInputMethods("app.a"); 189 190 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, true, false); 191 192 assertDeletedApps("app.b"); 193 verify(mCallback, times(1)).onSuccess(); 194 } 195 196 @SmallTest testProfileOwnerImesStillDeleted()197 public void testProfileOwnerImesStillDeleted() { 198 setSystemAppsWithLauncher("app.a", "app.b"); 199 setInstalledSystemApps("app.a", "app.b"); 200 setSystemInputMethods("app.a"); 201 202 runTask(DeleteNonRequiredAppsTask.PROFILE_OWNER, true, false); 203 204 assertDeletedApps("app.a", "app.b"); 205 verify(mCallback, times(1)).onSuccess(); 206 } 207 208 @SmallTest testManagedUserImesNotDeleted()209 public void testManagedUserImesNotDeleted() { 210 setSystemAppsWithLauncher("app.a", "app.b"); 211 setInstalledSystemApps("app.a", "app.b"); 212 setSystemInputMethods("app.a"); 213 214 runTask(DeleteNonRequiredAppsTask.MANAGED_USER, true, false); 215 216 assertDeletedApps("app.b"); 217 verify(mCallback, times(1)).onSuccess(); 218 } 219 220 @SmallTest testLeaveAllAppsEnabled()221 public void testLeaveAllAppsEnabled() { 222 setSystemAppsWithLauncher("app.a"); 223 setInstalledSystemApps("app.a"); 224 225 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, true, true); 226 227 assertDeletedApps(); //assert that no app has been deleted. 228 verify(mCallback, times(1)).onSuccess(); 229 } 230 231 @SmallTest testNewAppsDeletedAfterOta()232 public void testNewAppsDeletedAfterOta() { 233 setSystemAppsWithLauncher(); 234 setInstalledSystemApps("app.a"); 235 236 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, true, false); 237 238 verify(mCallback, times(1)).onSuccess(); 239 assertDeletedApps(); //assert that no app has been deleted. 240 241 // Now, an OTA happens and installs app.b with a launcher 242 setSystemAppsWithLauncher("app.b"); 243 setInstalledSystemApps("app.a", "app.b"); 244 245 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, false, false); 246 247 assertDeletedApps("app.b"); 248 verify(mCallback, times(2)).onSuccess(); 249 } 250 251 @SmallTest testExistingAppsNotDeletedAgainAfterOta()252 public void testExistingAppsNotDeletedAgainAfterOta() { 253 setSystemAppsWithLauncher("app.a"); 254 setInstalledSystemApps("app.a"); 255 256 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, true, false); 257 258 verify(mCallback, times(1)).onSuccess(); 259 assertDeletedApps("app.a"); 260 mDeletedApps.clear(); 261 262 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, false, false); 263 264 assertDeletedApps(); 265 verify(mCallback, times(2)).onSuccess(); 266 } 267 268 @SmallTest testWhenNoSystemAppsFileFound()269 public void testWhenNoSystemAppsFileFound() { 270 setSystemAppsWithLauncher("app.a"); 271 setInstalledSystemApps("app.a"); 272 273 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, true, false); 274 275 verify(mCallback, times(1)).onSuccess(); 276 assertDeletedApps("app.a"); 277 mDeletedApps.clear(); 278 279 setSystemAppsWithLauncher("app.a", "app.b"); 280 setInstalledSystemApps("app.a", "app.b"); 281 282 // Now, we set a wrong value to mTestContext.getFilesDir. So it should not find the system apps 283 // file. So it should not delete any app, but call onError(). 284 when(mTestContext.getFilesDir()).thenReturn(new File("")); 285 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, false, false); 286 287 assertDeletedApps(); 288 verify(mCallback, times(1)).onError(); 289 } 290 291 @SmallTest testWhenDeletionFails()292 public void testWhenDeletionFails() { 293 setSystemAppsWithLauncher("app.a"); 294 setInstalledSystemApps("app.a"); 295 mPackageManager.setDeletionSucceeds(false); 296 runTask(DeleteNonRequiredAppsTask.DEVICE_OWNER, true, false); 297 verify(mCallback, times(1)).onError(); 298 } 299 setRequiredAppsManagedDevice(String... apps)300 private void setRequiredAppsManagedDevice(String... apps) { 301 setStringArray(com.android.managedprovisioning.R.array.required_apps_managed_device, 302 apps); 303 } 304 setVendorRequiredAppsManagedDevice(String... apps)305 private void setVendorRequiredAppsManagedDevice(String... apps) { 306 setStringArray(com.android.managedprovisioning.R.array.vendor_required_apps_managed_device, 307 apps); 308 } 309 setDisallowedAppsManagedDevice(String... apps)310 private void setDisallowedAppsManagedDevice(String... apps) { 311 setStringArray(com.android.managedprovisioning.R.array.disallowed_apps_managed_device, 312 apps); 313 } 314 setVendorDisallowedAppsManagedDevice(String... apps)315 private void setVendorDisallowedAppsManagedDevice(String... apps) { 316 setStringArray( 317 com.android.managedprovisioning.R.array.vendor_disallowed_apps_managed_device, 318 apps); 319 } 320 setRequiredAppsManagedProfile(String... apps)321 private void setRequiredAppsManagedProfile(String... apps) { 322 setStringArray(com.android.managedprovisioning.R.array.required_apps_managed_profile, 323 apps); 324 } 325 setVendorRequiredAppsManagedProfile(String... apps)326 private void setVendorRequiredAppsManagedProfile(String... apps) { 327 setStringArray(com.android.managedprovisioning.R.array.vendor_required_apps_managed_profile, 328 apps); 329 } 330 setDisallowedAppsManagedProfile(String... apps)331 private void setDisallowedAppsManagedProfile(String... apps) { 332 setStringArray(com.android.managedprovisioning.R.array.disallowed_apps_managed_profile, 333 apps); 334 } 335 setVendorDisallowedAppsManagedProfile(String... apps)336 private void setVendorDisallowedAppsManagedProfile(String... apps) { 337 setStringArray( 338 com.android.managedprovisioning.R.array.vendor_disallowed_apps_managed_profile, 339 apps); 340 } 341 setRequiredAppsManagedUser(String... apps)342 private void setRequiredAppsManagedUser(String... apps) { 343 setStringArray(com.android.managedprovisioning.R.array.required_apps_managed_user, 344 apps); 345 } 346 setVendorRequiredAppsManagedUser(String... apps)347 private void setVendorRequiredAppsManagedUser(String... apps) { 348 setStringArray(com.android.managedprovisioning.R.array.vendor_required_apps_managed_user, 349 apps); 350 } 351 setDisallowedAppsManagedUser(String... apps)352 private void setDisallowedAppsManagedUser(String... apps) { 353 setStringArray(com.android.managedprovisioning.R.array.disallowed_apps_managed_user, 354 apps); 355 } 356 setVendorDisallowedAppsManagedUser(String... apps)357 private void setVendorDisallowedAppsManagedUser(String... apps) { 358 setStringArray( 359 com.android.managedprovisioning.R.array.vendor_disallowed_apps_managed_user, 360 apps); 361 } 362 runTask(int type, boolean newProfile, boolean leaveAllSystemAppsEnabled)363 private void runTask(int type, boolean newProfile, boolean leaveAllSystemAppsEnabled) { 364 DeleteNonRequiredAppsTask task = new DeleteNonRequiredAppsTask(mTestContext, 365 mIPackageManager, mIInputMethodManager, TEST_MDM_PACKAGE_NAME, type, newProfile, 366 TEST_USER_ID, leaveAllSystemAppsEnabled, mCallback); 367 task.run(); 368 } 369 setStringArray(int resourceId, String[] strs)370 private void setStringArray(int resourceId, String[] strs) { 371 when(mResources.getStringArray(eq(resourceId))) 372 .thenReturn(strs); 373 } 374 assertDeletedApps(String... appArray)375 private void assertDeletedApps(String... appArray) { 376 assertEquals(setFromArray(appArray), mDeletedApps); 377 } 378 setInstalledSystemApps(String... installedApps)379 private void setInstalledSystemApps(String... installedApps) { 380 List<ApplicationInfo> applications = new ArrayList<ApplicationInfo>(); 381 for (String app : installedApps) { 382 ApplicationInfo aInfo = new ApplicationInfo(); 383 aInfo.flags = ApplicationInfo.FLAG_SYSTEM; 384 aInfo.packageName = app; 385 applications.add(aInfo); 386 } 387 try { 388 when(mIPackageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES, 389 TEST_USER_ID)).thenReturn(new ParceledListSlice(applications)); 390 } catch (RemoteException e) { 391 fail(e.toString()); 392 } 393 mInstalledApplications = setFromArray(installedApps); 394 } 395 setSystemInputMethods(String... packageNames)396 private void setSystemInputMethods(String... packageNames) { 397 List<InputMethodInfo> inputMethods = new ArrayList<InputMethodInfo>(); 398 for (String packageName : packageNames) { 399 ApplicationInfo aInfo = new ApplicationInfo(); 400 aInfo.flags = ApplicationInfo.FLAG_SYSTEM; 401 ServiceInfo serviceInfo = new ServiceInfo(); 402 serviceInfo.applicationInfo = aInfo; 403 serviceInfo.packageName = packageName; 404 serviceInfo.name = ""; 405 ResolveInfo ri = new ResolveInfo(); 406 ri.serviceInfo = serviceInfo; 407 InputMethodInfo inputMethodInfo = new InputMethodInfo(ri, false, null, null, 0, false); 408 inputMethods.add(inputMethodInfo); 409 } 410 try { 411 when(mIInputMethodManager.getInputMethodList()).thenReturn(inputMethods); 412 } catch (RemoteException e) { 413 fail(e.toString()); 414 } 415 } 416 setSystemAppsWithLauncher(String... apps)417 private void setSystemAppsWithLauncher(String... apps) { 418 mSystemAppsWithLauncher = apps; 419 } 420 setFromArray(T[] array)421 private <T> Set<T> setFromArray(T[] array) { 422 return new HashSet<T>(Arrays.asList(array)); 423 } 424 425 class FakePackageManager extends MockPackageManager { 426 private boolean mDeletionSucceeds = true; 427 setDeletionSucceeds(boolean deletionSucceeds)428 void setDeletionSucceeds(boolean deletionSucceeds) { 429 mDeletionSucceeds = deletionSucceeds; 430 } 431 432 @Override deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int flags, int userId)433 public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, 434 int flags, int userId) { 435 if (mDeletionSucceeds) { 436 mDeletedApps.add(packageName); 437 } 438 assertTrue((flags & PackageManager.DELETE_SYSTEM_APP) != 0); 439 assertEquals(TEST_USER_ID, userId); 440 441 int resultCode; 442 if (mDeletionSucceeds) { 443 resultCode = PackageManager.DELETE_SUCCEEDED; 444 } else { 445 resultCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR; 446 } 447 448 try { 449 observer.packageDeleted(packageName, resultCode); 450 } catch (RemoteException e) { 451 fail(e.toString()); 452 } 453 } 454 455 @Override queryIntentActivitiesAsUser(Intent intent, int flags, int userId)456 public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) { 457 assertTrue("Expected an intent with action ACTION_MAIN and category CATEGORY_LAUNCHER", 458 intent.filterEquals( 459 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER))); 460 assertTrue("Expected the flag MATCH_UNINSTALLED_PACKAGES", 461 (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0); 462 assertTrue("Expected the flag MATCH_DISABLED_COMPONENTS", 463 (flags & PackageManager.MATCH_DISABLED_COMPONENTS) != 0); 464 assertTrue("Expected the flag MATCH_ENCRYPTION_AWARE_AND_UNAWARE", 465 (flags & PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE) != 0); 466 assertEquals(userId, TEST_USER_ID); 467 List<ResolveInfo> result = new ArrayList<ResolveInfo>(); 468 for (String packageName : mSystemAppsWithLauncher) { 469 ActivityInfo ai = new ActivityInfo(); 470 ai.packageName = packageName; 471 ResolveInfo ri = new ResolveInfo(); 472 ri.activityInfo = ai; 473 result.add(ri); 474 } 475 return result; 476 } 477 478 @Override getPackageInfoAsUser(String packageName, int flags, int userId)479 public PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId) 480 throws NameNotFoundException { 481 if (mInstalledApplications.contains(packageName)) { 482 return new PackageInfo(); 483 } 484 throw new NameNotFoundException(); 485 } 486 } 487 } 488 489