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