1 /* 2 * Copyright (C) 2017 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.server.pm; 18 19 import static com.android.compatibility.common.util.ShellUtils.runShellCommand; 20 21 import static com.google.common.truth.Truth.assertWithMessage; 22 23 import static org.junit.Assert.assertThrows; 24 import static org.junit.Assert.fail; 25 26 import static java.lang.reflect.Modifier.isFinal; 27 import static java.lang.reflect.Modifier.isPublic; 28 import static java.lang.reflect.Modifier.isStatic; 29 30 import android.app.AppGlobals; 31 import android.content.pm.IPackageManager; 32 import android.content.pm.PackageManager; 33 import android.os.UserHandle; 34 import android.os.UserManager; 35 import android.platform.test.annotations.Postsubmit; 36 37 import androidx.test.InstrumentationRegistry; 38 import androidx.test.runner.AndroidJUnit4; 39 40 import com.android.internal.util.HexDump; 41 import com.android.server.pm.PerPackageReadTimeouts.Timeouts; 42 import com.android.server.pm.PerPackageReadTimeouts.VersionCodes; 43 44 import com.google.android.collect.Lists; 45 46 import org.junit.After; 47 import org.junit.Assert; 48 import org.junit.Assume; 49 import org.junit.Before; 50 import org.junit.Test; 51 import org.junit.runner.RunWith; 52 53 import java.io.File; 54 import java.lang.reflect.Field; 55 import java.lang.reflect.Method; 56 import java.lang.reflect.Type; 57 import java.util.ArrayList; 58 import java.util.Arrays; 59 import java.util.Collections; 60 import java.util.List; 61 import java.util.regex.Pattern; 62 63 // atest PackageManagerServiceTest 64 @Postsubmit 65 @RunWith(AndroidJUnit4.class) 66 public class PackageManagerServiceTest { 67 68 private static final String PACKAGE_NAME = "com.android.server.pm.test.service.server"; 69 70 private static final String TEST_DATA_PATH = "/data/local/tmp/servicestests/"; 71 private static final String TEST_APP_APK = "StubTestApp.apk"; 72 private static final String TEST_PKG_NAME = "com.android.servicestests.apps.stubapp"; 73 74 private IPackageManager mIPackageManager; 75 76 @Before setUp()77 public void setUp() throws Exception { 78 mIPackageManager = AppGlobals.getPackageManager(); 79 } 80 81 @After tearDown()82 public void tearDown() throws Exception { 83 } 84 85 @Test testPackageRemoval()86 public void testPackageRemoval() { 87 class PackageSenderImpl implements PackageSender { 88 @Override 89 public void notifyPackageAdded(String packageName, int uid) { 90 } 91 92 @Override 93 public void notifyPackageChanged(String packageName, int uid) { 94 95 } 96 97 @Override 98 public void notifyPackageRemoved(String packageName, int uid) { 99 } 100 } 101 102 PackageSetting setting = null; 103 PackageRemovedInfo pri = new PackageRemovedInfo(); 104 105 // Initial conditions: nothing there 106 Assert.assertNull(pri.mRemovedUsers); 107 Assert.assertNull(pri.mBroadcastUsers); 108 109 // populateUsers with nothing leaves nothing 110 pri.populateBroadcastUsers(setting); 111 Assert.assertNull(pri.mBroadcastUsers); 112 113 // Create a real (non-null) PackageSetting and confirm that the removed 114 // users are copied properly 115 setting = new PackageSettingBuilder() 116 .setName("name") 117 .setRealName("realName") 118 .setCodePath("codePath") 119 .setLegacyNativeLibraryPathString("legacyNativeLibraryPathString") 120 .setPrimaryCpuAbiString("primaryCpuAbiString") 121 .setSecondaryCpuAbiString("secondaryCpuAbiString") 122 .setCpuAbiOverrideString("cpuAbiOverrideString") 123 .build(); 124 pri.mRemovedUsers = new int[]{ 125 1, 2, 3, 4, 5 126 }; 127 pri.populateBroadcastUsers(setting); 128 Assert.assertNotNull(pri.mBroadcastUsers); 129 Assert.assertEquals(5, pri.mBroadcastUsers.length); 130 Assert.assertNotNull(pri.mInstantUserIds); 131 Assert.assertEquals(0, pri.mInstantUserIds.length); 132 133 // Exclude a user 134 pri.mBroadcastUsers = null; 135 final int EXCLUDED_USER_ID = 4; 136 setting.setInstantApp(true, EXCLUDED_USER_ID); 137 pri.mRemovedUsers = new int[]{ 138 1, 2, 3, EXCLUDED_USER_ID, 5 139 }; 140 pri.populateBroadcastUsers(setting); 141 Assert.assertNotNull(pri.mBroadcastUsers); 142 Assert.assertEquals(4, pri.mBroadcastUsers.length); 143 Assert.assertNotNull(pri.mInstantUserIds); 144 Assert.assertEquals(1, pri.mInstantUserIds.length); 145 146 // TODO: test that sendApplicationHiddenForUser() actually fills in 147 // broadcastUsers 148 } 149 150 @Test testPartitions()151 public void testPartitions() { 152 String[] partitions = {"system", "vendor", "odm", "oem", "product", "system_ext"}; 153 String[] appdir = {"app", "priv-app"}; 154 for (int i = 0; i < partitions.length; i++) { 155 final ScanPartition scanPartition = 156 PackageManagerService.SYSTEM_PARTITIONS.get(i); 157 for (int j = 0; j < appdir.length; j++) { 158 File path = new File(String.format("%s/%s/A.apk", partitions[i], appdir[j])); 159 Assert.assertEquals(j == 1 && i != 3, scanPartition.containsPrivApp(path)); 160 161 final int scanFlag = scanPartition.scanFlag; 162 Assert.assertEquals(i == 1, scanFlag == PackageManagerService.SCAN_AS_VENDOR); 163 Assert.assertEquals(i == 2, scanFlag == PackageManagerService.SCAN_AS_ODM); 164 Assert.assertEquals(i == 3, scanFlag == PackageManagerService.SCAN_AS_OEM); 165 Assert.assertEquals(i == 4, scanFlag == PackageManagerService.SCAN_AS_PRODUCT); 166 Assert.assertEquals(i == 5, scanFlag == PackageManagerService.SCAN_AS_SYSTEM_EXT); 167 } 168 } 169 } 170 171 @Test testKnownPackageToString_shouldNotGetUnknown()172 public void testKnownPackageToString_shouldNotGetUnknown() { 173 final List<String> packageNames = new ArrayList<>(); 174 for (int i = 0; i <= KnownPackages.LAST_KNOWN_PACKAGE; i++) { 175 packageNames.add(KnownPackages.knownPackageToString(i)); 176 } 177 assertWithMessage( 178 "The Ids of KnownPackage should be continuous and the string representation " 179 + "should not be unknown.").that( 180 packageNames).containsNoneIn(Lists.newArrayList("Unknown")); 181 } 182 183 @Test testKnownPackage_lastKnownPackageIsTheLast()184 public void testKnownPackage_lastKnownPackageIsTheLast() throws Exception { 185 final List<Integer> knownPackageIds = getKnownPackageIdsList(); 186 assertWithMessage( 187 "The last KnownPackage Id should be assigned to PackageManagerInternal" 188 + ".LAST_KNOWN_PACKAGE.").that( 189 knownPackageIds.get(knownPackageIds.size() - 1)).isEqualTo( 190 KnownPackages.LAST_KNOWN_PACKAGE); 191 } 192 193 @Test testKnownPackage_IdsShouldBeUniqueAndContinuous()194 public void testKnownPackage_IdsShouldBeUniqueAndContinuous() throws Exception { 195 final List<Integer> knownPackageIds = getKnownPackageIdsList(); 196 for (int i = 0, size = knownPackageIds.size(); i < size - 1; i++) { 197 assertWithMessage( 198 "The KnownPackage Ids should be unique and continuous. KnownPackageIds = " 199 + Arrays.toString(knownPackageIds.toArray())).that( 200 knownPackageIds.get(i) + 1).isEqualTo(knownPackageIds.get(i + 1)); 201 } 202 } 203 204 @Test testTimeouts()205 public void testTimeouts() { 206 Timeouts defaults = Timeouts.parse("3600000001:3600000002:3600000003"); 207 Assert.assertEquals(3600000001L, defaults.minTimeUs); 208 Assert.assertEquals(3600000002L, defaults.minPendingTimeUs); 209 Assert.assertEquals(3600000003L, defaults.maxPendingTimeUs); 210 211 Timeouts empty = Timeouts.parse(""); 212 Assert.assertEquals(3600000000L, empty.minTimeUs); 213 Assert.assertEquals(3600000000L, empty.minPendingTimeUs); 214 Assert.assertEquals(3600000000L, empty.maxPendingTimeUs); 215 216 Timeouts partial0 = Timeouts.parse("10000::"); 217 Assert.assertEquals(10000L, partial0.minTimeUs); 218 Assert.assertEquals(3600000000L, partial0.minPendingTimeUs); 219 Assert.assertEquals(3600000000L, partial0.maxPendingTimeUs); 220 221 Timeouts partial1 = Timeouts.parse("10000:10001:"); 222 Assert.assertEquals(10000L, partial1.minTimeUs); 223 Assert.assertEquals(10001L, partial1.minPendingTimeUs); 224 Assert.assertEquals(3600000000L, partial1.maxPendingTimeUs); 225 226 Timeouts fullDefault = Timeouts.parse("3600000000:3600000000:3600000000"); 227 Assert.assertEquals(3600000000L, fullDefault.minTimeUs); 228 Assert.assertEquals(3600000000L, fullDefault.minPendingTimeUs); 229 Assert.assertEquals(3600000000L, fullDefault.maxPendingTimeUs); 230 231 Timeouts full = Timeouts.parse("10000:10001:10002"); 232 Assert.assertEquals(10000L, full.minTimeUs); 233 Assert.assertEquals(10001L, full.minPendingTimeUs); 234 Assert.assertEquals(10002L, full.maxPendingTimeUs); 235 236 Timeouts invalid0 = Timeouts.parse(":10000"); 237 Assert.assertEquals(3600000000L, invalid0.minTimeUs); 238 Assert.assertEquals(3600000000L, invalid0.minPendingTimeUs); 239 Assert.assertEquals(3600000000L, invalid0.maxPendingTimeUs); 240 241 Timeouts invalid1 = Timeouts.parse(":10000::"); 242 Assert.assertEquals(3600000000L, invalid1.minTimeUs); 243 Assert.assertEquals(3600000000L, invalid1.minPendingTimeUs); 244 Assert.assertEquals(3600000000L, invalid1.maxPendingTimeUs); 245 246 Timeouts invalid2 = Timeouts.parse("10000:10001:abcd"); 247 Assert.assertEquals(10000L, invalid2.minTimeUs); 248 Assert.assertEquals(10001L, invalid2.minPendingTimeUs); 249 Assert.assertEquals(3600000000L, invalid2.maxPendingTimeUs); 250 251 Timeouts invalid3 = Timeouts.parse(":10000:"); 252 Assert.assertEquals(3600000000L, invalid3.minTimeUs); 253 Assert.assertEquals(3600000000L, invalid3.minPendingTimeUs); 254 Assert.assertEquals(3600000000L, invalid3.maxPendingTimeUs); 255 256 Timeouts invalid4 = Timeouts.parse("abcd:10001:10002"); 257 Assert.assertEquals(3600000000L, invalid4.minTimeUs); 258 Assert.assertEquals(3600000000L, invalid4.minPendingTimeUs); 259 Assert.assertEquals(3600000000L, invalid4.maxPendingTimeUs); 260 261 Timeouts invalid5 = Timeouts.parse("::1000000000000000000000000"); 262 Assert.assertEquals(3600000000L, invalid5.minTimeUs); 263 Assert.assertEquals(3600000000L, invalid5.minPendingTimeUs); 264 Assert.assertEquals(3600000000L, invalid5.maxPendingTimeUs); 265 266 Timeouts invalid6 = Timeouts.parse("-10000:10001:10002"); 267 Assert.assertEquals(3600000000L, invalid6.minTimeUs); 268 Assert.assertEquals(3600000000L, invalid6.minPendingTimeUs); 269 Assert.assertEquals(3600000000L, invalid6.maxPendingTimeUs); 270 } 271 272 @Test testVersionCodes()273 public void testVersionCodes() { 274 final VersionCodes defaults = VersionCodes.parse(""); 275 Assert.assertEquals(Long.MIN_VALUE, defaults.minVersionCode); 276 Assert.assertEquals(Long.MAX_VALUE, defaults.maxVersionCode); 277 278 VersionCodes single = VersionCodes.parse("191000070"); 279 Assert.assertEquals(191000070, single.minVersionCode); 280 Assert.assertEquals(191000070, single.maxVersionCode); 281 282 VersionCodes single2 = VersionCodes.parse("191000070-191000070"); 283 Assert.assertEquals(191000070, single2.minVersionCode); 284 Assert.assertEquals(191000070, single2.maxVersionCode); 285 286 VersionCodes upto = VersionCodes.parse("-191000070"); 287 Assert.assertEquals(Long.MIN_VALUE, upto.minVersionCode); 288 Assert.assertEquals(191000070, upto.maxVersionCode); 289 290 VersionCodes andabove = VersionCodes.parse("191000070-"); 291 Assert.assertEquals(191000070, andabove.minVersionCode); 292 Assert.assertEquals(Long.MAX_VALUE, andabove.maxVersionCode); 293 294 VersionCodes range = VersionCodes.parse("191000070-201000070"); 295 Assert.assertEquals(191000070, range.minVersionCode); 296 Assert.assertEquals(201000070, range.maxVersionCode); 297 298 VersionCodes invalid0 = VersionCodes.parse("201000070-191000070"); 299 Assert.assertEquals(Long.MIN_VALUE, invalid0.minVersionCode); 300 Assert.assertEquals(Long.MAX_VALUE, invalid0.maxVersionCode); 301 302 VersionCodes invalid1 = VersionCodes.parse("abcd-191000070"); 303 Assert.assertEquals(Long.MIN_VALUE, invalid1.minVersionCode); 304 Assert.assertEquals(191000070, invalid1.maxVersionCode); 305 306 VersionCodes invalid2 = VersionCodes.parse("abcd"); 307 Assert.assertEquals(Long.MIN_VALUE, invalid2.minVersionCode); 308 Assert.assertEquals(Long.MAX_VALUE, invalid2.maxVersionCode); 309 310 VersionCodes invalid3 = VersionCodes.parse("191000070-abcd"); 311 Assert.assertEquals(191000070, invalid3.minVersionCode); 312 Assert.assertEquals(Long.MAX_VALUE, invalid3.maxVersionCode); 313 } 314 315 @Test testPerPackageReadTimeouts()316 public void testPerPackageReadTimeouts() { 317 final String sha256 = "336faefc91bb2dddf9b21829106fbc607b862132fecd273e1b6b3ea55f09d4e1"; 318 final VersionCodes defVCs = VersionCodes.parse(""); 319 final Timeouts defTs = Timeouts.parse("3600000001:3600000002:3600000003"); 320 321 PerPackageReadTimeouts empty = PerPackageReadTimeouts.parse("", defVCs, defTs); 322 Assert.assertNull(empty); 323 324 PerPackageReadTimeouts packageOnly = PerPackageReadTimeouts.parse("package.com", defVCs, 325 defTs); 326 Assert.assertEquals("package.com", packageOnly.packageName); 327 Assert.assertEquals(null, packageOnly.sha256certificate); 328 Assert.assertEquals(Long.MIN_VALUE, packageOnly.versionCodes.minVersionCode); 329 Assert.assertEquals(Long.MAX_VALUE, packageOnly.versionCodes.maxVersionCode); 330 Assert.assertEquals(3600000001L, packageOnly.timeouts.minTimeUs); 331 Assert.assertEquals(3600000002L, packageOnly.timeouts.minPendingTimeUs); 332 Assert.assertEquals(3600000003L, packageOnly.timeouts.maxPendingTimeUs); 333 334 PerPackageReadTimeouts packageHash = PerPackageReadTimeouts.parse( 335 "package.com:" + sha256, defVCs, defTs); 336 Assert.assertEquals("package.com", packageHash.packageName); 337 Assert.assertEquals(sha256, bytesToHexString(packageHash.sha256certificate)); 338 Assert.assertEquals(Long.MIN_VALUE, packageHash.versionCodes.minVersionCode); 339 Assert.assertEquals(Long.MAX_VALUE, packageHash.versionCodes.maxVersionCode); 340 Assert.assertEquals(3600000001L, packageHash.timeouts.minTimeUs); 341 Assert.assertEquals(3600000002L, packageHash.timeouts.minPendingTimeUs); 342 Assert.assertEquals(3600000003L, packageHash.timeouts.maxPendingTimeUs); 343 344 PerPackageReadTimeouts packageVersionCode = PerPackageReadTimeouts.parse( 345 "package.com::191000070", defVCs, defTs); 346 Assert.assertEquals("package.com", packageVersionCode.packageName); 347 Assert.assertEquals(null, packageVersionCode.sha256certificate); 348 Assert.assertEquals(191000070, packageVersionCode.versionCodes.minVersionCode); 349 Assert.assertEquals(191000070, packageVersionCode.versionCodes.maxVersionCode); 350 Assert.assertEquals(3600000001L, packageVersionCode.timeouts.minTimeUs); 351 Assert.assertEquals(3600000002L, packageVersionCode.timeouts.minPendingTimeUs); 352 Assert.assertEquals(3600000003L, packageVersionCode.timeouts.maxPendingTimeUs); 353 354 PerPackageReadTimeouts full = PerPackageReadTimeouts.parse( 355 "package.com:" + sha256 + ":191000070-201000070:10001:10002:10003", defVCs, defTs); 356 Assert.assertEquals("package.com", full.packageName); 357 Assert.assertEquals(sha256, bytesToHexString(full.sha256certificate)); 358 Assert.assertEquals(191000070, full.versionCodes.minVersionCode); 359 Assert.assertEquals(201000070, full.versionCodes.maxVersionCode); 360 Assert.assertEquals(10001L, full.timeouts.minTimeUs); 361 Assert.assertEquals(10002L, full.timeouts.minPendingTimeUs); 362 Assert.assertEquals(10003L, full.timeouts.maxPendingTimeUs); 363 } 364 365 @Test testGetPerPackageReadTimeouts()366 public void testGetPerPackageReadTimeouts() { 367 Assert.assertEquals(0, getPerPackageReadTimeouts(null).length); 368 Assert.assertEquals(0, getPerPackageReadTimeouts("").length); 369 Assert.assertEquals(0, getPerPackageReadTimeouts(",,,,").length); 370 371 final String sha256 = "0fae93f1a7925b4c68bbea80ad3eaa41acfc9bc6f10bf1054f5d93a2bd556093"; 372 373 PerPackageReadTimeouts[] singlePackage = getPerPackageReadTimeouts( 374 "package.com:" + sha256 + ":191000070-201000070:10001:10002:10003"); 375 Assert.assertEquals(1, singlePackage.length); 376 Assert.assertEquals("package.com", singlePackage[0].packageName); 377 Assert.assertEquals(sha256, bytesToHexString(singlePackage[0].sha256certificate)); 378 Assert.assertEquals(191000070, singlePackage[0].versionCodes.minVersionCode); 379 Assert.assertEquals(201000070, singlePackage[0].versionCodes.maxVersionCode); 380 Assert.assertEquals(10001L, singlePackage[0].timeouts.minTimeUs); 381 Assert.assertEquals(10002L, singlePackage[0].timeouts.minPendingTimeUs); 382 Assert.assertEquals(10003L, singlePackage[0].timeouts.maxPendingTimeUs); 383 384 PerPackageReadTimeouts[] multiPackage = getPerPackageReadTimeouts("package.com:" + sha256 385 + ":191000070-201000070:10001:10002:10003,package1.com::123456"); 386 Assert.assertEquals(2, multiPackage.length); 387 Assert.assertEquals("package.com", multiPackage[0].packageName); 388 Assert.assertEquals(sha256, bytesToHexString(multiPackage[0].sha256certificate)); 389 Assert.assertEquals(191000070, multiPackage[0].versionCodes.minVersionCode); 390 Assert.assertEquals(201000070, multiPackage[0].versionCodes.maxVersionCode); 391 Assert.assertEquals(10001L, multiPackage[0].timeouts.minTimeUs); 392 Assert.assertEquals(10002L, multiPackage[0].timeouts.minPendingTimeUs); 393 Assert.assertEquals(10003L, multiPackage[0].timeouts.maxPendingTimeUs); 394 Assert.assertEquals("package1.com", multiPackage[1].packageName); 395 Assert.assertEquals(null, multiPackage[1].sha256certificate); 396 Assert.assertEquals(123456, multiPackage[1].versionCodes.minVersionCode); 397 Assert.assertEquals(123456, multiPackage[1].versionCodes.maxVersionCode); 398 Assert.assertEquals(3600000001L, multiPackage[1].timeouts.minTimeUs); 399 Assert.assertEquals(3600000002L, multiPackage[1].timeouts.minPendingTimeUs); 400 Assert.assertEquals(3600000003L, multiPackage[1].timeouts.maxPendingTimeUs); 401 } 402 403 // Report an error from the Computer structure validation test. flag(String name, String msg)404 private void flag(String name, String msg) { 405 fail(name + " " + msg); 406 } 407 408 // Return a string that identifies a Method. This is not very efficient but it is not 409 // called very often. displayName(Method m)410 private String displayName(Method m) { 411 String r = m.getName(); 412 String p = Arrays.toString(m.getGenericParameterTypes()) 413 .replaceAll("([a-zA-Z0-9]+\\.)+", "") 414 .replace("class ", "") 415 .replaceAll("^\\[", "(") 416 .replaceAll("\\]$", ")"); 417 return r + p; 418 } 419 420 // Match a method to an array of Methods. Matching is on method signature: name and 421 // parameter types. If a method in the declared array matches, return it. Otherwise 422 // return null. matchMethod(Method m, Method[] declared)423 private Method matchMethod(Method m, Method[] declared) { 424 String n = m.getName(); 425 Type[] t = m.getGenericParameterTypes(); 426 for (int i = 0; i < declared.length; i++) { 427 Method l = declared[i]; 428 if (l != null && l.getName().equals(n) 429 && Arrays.equals(l.getGenericParameterTypes(), t)) { 430 Method result = l; 431 // Set the method to null since it has been visited already. 432 declared[i] = null; 433 return result; 434 } 435 } 436 return null; 437 } 438 getPerPackageReadTimeouts(String knownDigestersList)439 private static PerPackageReadTimeouts[] getPerPackageReadTimeouts(String knownDigestersList) { 440 final String defaultTimeouts = "3600000001:3600000002:3600000003"; 441 List<PerPackageReadTimeouts> result = PerPackageReadTimeouts.parseDigestersList( 442 defaultTimeouts, knownDigestersList); 443 if (result == null) { 444 return null; 445 } 446 return result.toArray(new PerPackageReadTimeouts[result.size()]); 447 } 448 bytesToHexString(byte[] bytes)449 private static String bytesToHexString(byte[] bytes) { 450 return HexDump.toHexString(bytes, 0, bytes.length, /*upperCase=*/ false); 451 } 452 getKnownPackageIdsList()453 private List<Integer> getKnownPackageIdsList() throws IllegalAccessException { 454 final ArrayList<Integer> knownPackageIds = new ArrayList<>(); 455 final Field[] allFields = KnownPackages.class.getDeclaredFields(); 456 for (Field field : allFields) { 457 final int modifier = field.getModifiers(); 458 if (isPublic(modifier) && isStatic(modifier) && isFinal(modifier) 459 && Pattern.matches("PACKAGE(_[A-Z]+)+", field.getName())) { 460 knownPackageIds.add(field.getInt(null)); 461 } 462 } 463 Collections.sort(knownPackageIds); 464 return knownPackageIds; 465 } 466 467 @Test testInstallReason_afterUpdate_keepUnchanged()468 public void testInstallReason_afterUpdate_keepUnchanged() throws Exception { 469 final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK); 470 try { 471 // Try to install test APK with reason INSTALL_REASON_DEVICE_SETUP 472 runShellCommand("pm install --install-reason 3 " + testApk); 473 assertWithMessage("The install reason of test APK is incorrect.").that( 474 mIPackageManager.getInstallReason(TEST_PKG_NAME, 475 UserHandle.myUserId())).isEqualTo( 476 PackageManager.INSTALL_REASON_DEVICE_SETUP); 477 478 // Try to update test APK with different reason INSTALL_REASON_USER 479 runShellCommand("pm install --install-reason 4 " + testApk); 480 assertWithMessage("The install reason should keep unchanged after update.").that( 481 mIPackageManager.getInstallReason(TEST_PKG_NAME, 482 UserHandle.myUserId())).isEqualTo( 483 PackageManager.INSTALL_REASON_DEVICE_SETUP); 484 } finally { 485 runShellCommand("pm uninstall " + TEST_PKG_NAME); 486 } 487 } 488 489 @Test testInstallReason_userRemainsUninstalled_keepUnknown()490 public void testInstallReason_userRemainsUninstalled_keepUnknown() throws Exception { 491 Assume.assumeTrue(UserManager.supportsMultipleUsers()); 492 final UserManager um = UserManager.get( 493 InstrumentationRegistry.getInstrumentation().getContext()); 494 final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK); 495 int userId = UserHandle.USER_NULL; 496 try { 497 // Try to install test APK with reason INSTALL_REASON_DEVICE_SETUP 498 runShellCommand("pm install --install-reason 3 " + testApk); 499 assertWithMessage("The install reason of test APK is incorrect.").that( 500 mIPackageManager.getInstallReason(TEST_PKG_NAME, 501 UserHandle.myUserId())).isEqualTo( 502 PackageManager.INSTALL_REASON_DEVICE_SETUP); 503 504 // Create and start the 2nd user. 505 userId = um.createUser("Test User", 0 /* flags */).getUserHandle().getIdentifier(); 506 runShellCommand("am start-user -w " + userId); 507 // Since the test APK isn't installed on the 2nd user, the reason should be unknown. 508 assertWithMessage("The test APK should not be installed in the 2nd user").that( 509 mIPackageManager.getPackageInfo(TEST_PKG_NAME, 0 /* flags */, userId)).isNull(); 510 assertWithMessage("The install reason in 2nd user should be unknown.").that( 511 mIPackageManager.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo( 512 PackageManager.INSTALL_REASON_UNKNOWN); 513 } finally { 514 runShellCommand("pm uninstall " + TEST_PKG_NAME); 515 if (userId != UserHandle.USER_NULL) { 516 um.removeUser(userId); 517 } 518 } 519 } 520 521 @Test testInstallReason_installForAllUsers_sameReason()522 public void testInstallReason_installForAllUsers_sameReason() throws Exception { 523 Assume.assumeTrue(UserManager.supportsMultipleUsers()); 524 final UserManager um = UserManager.get( 525 InstrumentationRegistry.getInstrumentation().getContext()); 526 final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK); 527 int userId = UserHandle.USER_NULL; 528 try { 529 // Create and start the 2nd user. 530 userId = um.createUser("Test User", 0 /* flags */).getUserHandle().getIdentifier(); 531 runShellCommand("am start-user -w " + userId); 532 533 // Try to install test APK to all users with reason INSTALL_REASON_DEVICE_SETUP 534 runShellCommand("pm install --install-reason 3 " + testApk); 535 assertWithMessage("The install reason is inconsistent across users.").that( 536 mIPackageManager.getInstallReason(TEST_PKG_NAME, 537 UserHandle.myUserId())).isEqualTo( 538 mIPackageManager.getInstallReason(TEST_PKG_NAME, userId)); 539 } finally { 540 runShellCommand("pm uninstall " + TEST_PKG_NAME); 541 if (userId != UserHandle.USER_NULL) { 542 um.removeUser(userId); 543 } 544 } 545 } 546 547 @Test testInstallReason_installSeparately_withSeparatedReason()548 public void testInstallReason_installSeparately_withSeparatedReason() throws Exception { 549 Assume.assumeTrue(UserManager.supportsMultipleUsers()); 550 final UserManager um = UserManager.get( 551 InstrumentationRegistry.getInstrumentation().getContext()); 552 final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK); 553 int userId = UserHandle.USER_NULL; 554 try { 555 // Create and start the 2nd user. 556 userId = um.createUser("Test User", 0 /* flags */).getUserHandle().getIdentifier(); 557 runShellCommand("am start-user -w " + userId); 558 559 // Try to install test APK on the current user with reason INSTALL_REASON_DEVICE_SETUP 560 runShellCommand("pm install --user cur --install-reason 3 " + testApk); 561 assertWithMessage("The install reason on the current user is incorrect.").that( 562 mIPackageManager.getInstallReason(TEST_PKG_NAME, 563 UserHandle.myUserId())).isEqualTo( 564 PackageManager.INSTALL_REASON_DEVICE_SETUP); 565 566 // Try to install test APK on the 2nd user with reason INSTALL_REASON_USER 567 runShellCommand("pm install --user " + userId + " --install-reason 4 " + testApk); 568 assertWithMessage("The install reason on the 2nd user is incorrect.").that( 569 mIPackageManager.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo( 570 PackageManager.INSTALL_REASON_USER); 571 } finally { 572 runShellCommand("pm uninstall " + TEST_PKG_NAME); 573 if (userId != UserHandle.USER_NULL) { 574 um.removeUser(userId); 575 } 576 } 577 } 578 579 @Test testSetSplashScreenTheme_samePackage_succeeds()580 public void testSetSplashScreenTheme_samePackage_succeeds() throws Exception { 581 mIPackageManager.setSplashScreenTheme(PACKAGE_NAME, null /* themeName */, 582 UserHandle.myUserId()); 583 // Invoking setSplashScreenTheme on the same package shouldn't get any exception. 584 } 585 586 @Test testSetSplashScreenTheme_differentPackage_fails()587 public void testSetSplashScreenTheme_differentPackage_fails() throws Exception { 588 final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK); 589 try { 590 runShellCommand("pm install " + testApk); 591 mIPackageManager.setSplashScreenTheme(TEST_PKG_NAME, null /* themeName */, 592 UserHandle.myUserId()); 593 fail("setSplashScreenTheme did not throw SecurityException as expected"); 594 } catch (SecurityException e) { 595 // expected 596 } finally { 597 runShellCommand("pm uninstall " + TEST_PKG_NAME); 598 } 599 } 600 601 @Test testSetUserMinAspectRatio_samePackage_succeeds()602 public void testSetUserMinAspectRatio_samePackage_succeeds() throws Exception { 603 mIPackageManager.setUserMinAspectRatio(PACKAGE_NAME, UserHandle.myUserId(), 604 PackageManager.USER_MIN_ASPECT_RATIO_UNSET); 605 // Invoking setUserMinAspectRatio on the same package shouldn't get any exception. 606 } 607 608 @Test testSetUserMinAspectRatio_differentPackage_fails()609 public void testSetUserMinAspectRatio_differentPackage_fails() { 610 final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK); 611 runShellCommand("pm install " + testApk); 612 assertThrows(SecurityException.class, () -> { 613 mIPackageManager.setUserMinAspectRatio(TEST_PKG_NAME, UserHandle.myUserId(), 614 PackageManager.USER_MIN_ASPECT_RATIO_UNSET); 615 }); 616 runShellCommand("pm uninstall " + TEST_PKG_NAME); 617 } 618 } 619