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.google.common.truth.Truth.assertWithMessage; 20 21 import static org.junit.Assert.fail; 22 23 import static java.lang.reflect.Modifier.isFinal; 24 import static java.lang.reflect.Modifier.isPrivate; 25 import static java.lang.reflect.Modifier.isProtected; 26 import static java.lang.reflect.Modifier.isPublic; 27 import static java.lang.reflect.Modifier.isStatic; 28 29 import android.annotation.Nullable; 30 import android.content.IIntentReceiver; 31 import android.content.pm.PackageManagerInternal; 32 import android.os.Bundle; 33 import android.util.SparseArray; 34 35 import androidx.test.runner.AndroidJUnit4; 36 37 import com.android.internal.util.HexDump; 38 import com.android.server.pm.PerPackageReadTimeouts.Timeouts; 39 import com.android.server.pm.PerPackageReadTimeouts.VersionCodes; 40 41 import com.google.android.collect.Lists; 42 43 import org.junit.After; 44 import org.junit.Assert; 45 import org.junit.Before; 46 import org.junit.Test; 47 import org.junit.runner.RunWith; 48 49 import java.io.File; 50 import java.lang.reflect.Field; 51 import java.lang.reflect.Method; 52 import java.lang.reflect.Type; 53 import java.util.ArrayList; 54 import java.util.Arrays; 55 import java.util.Collections; 56 import java.util.HashMap; 57 import java.util.List; 58 import java.util.regex.Pattern; 59 60 // atest PackageManagerServiceTest 61 // runtest -c com.android.server.pm.PackageManagerServiceTest frameworks-services 62 // bit FrameworksServicesTests:com.android.server.pm.PackageManagerServiceTest 63 @RunWith(AndroidJUnit4.class) 64 public class PackageManagerServiceTest { 65 @Before setUp()66 public void setUp() throws Exception { 67 } 68 69 @After tearDown()70 public void tearDown() throws Exception { 71 } 72 73 @Test testPackageRemoval()74 public void testPackageRemoval() throws Exception { 75 class PackageSenderImpl implements PackageSender { 76 public void sendPackageBroadcast(final String action, final String pkg, 77 final Bundle extras, final int flags, final String targetPkg, 78 final IIntentReceiver finishedReceiver, final int[] userIds, 79 int[] instantUserIds, SparseArray<int[]> broadcastAllowList, 80 @Nullable Bundle bOptions) { 81 } 82 83 public void sendPackageAddedForNewUsers(String packageName, 84 boolean sendBootComplete, boolean includeStopped, int appId, 85 int[] userIds, int[] instantUserIds, int dataLoaderType) { 86 } 87 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 PackageSenderImpl sender = new PackageSenderImpl(); 103 PackageSetting setting = null; 104 PackageManagerService.PackageRemovedInfo pri = 105 new PackageManagerService.PackageRemovedInfo(sender); 106 107 // Initial conditions: nothing there 108 Assert.assertNull(pri.removedUsers); 109 Assert.assertNull(pri.broadcastUsers); 110 111 // populateUsers with nothing leaves nothing 112 pri.populateUsers(null, setting); 113 Assert.assertNull(pri.broadcastUsers); 114 115 // Create a real (non-null) PackageSetting and confirm that the removed 116 // users are copied properly 117 setting = new PackageSettingBuilder() 118 .setName("name") 119 .setRealName("realName") 120 .setCodePath("codePath") 121 .setLegacyNativeLibraryPathString("legacyNativeLibraryPathString") 122 .setPrimaryCpuAbiString("primaryCpuAbiString") 123 .setSecondaryCpuAbiString("secondaryCpuAbiString") 124 .setCpuAbiOverrideString("cpuAbiOverrideString") 125 .build(); 126 pri.populateUsers(new int[] { 127 1, 2, 3, 4, 5 128 }, setting); 129 Assert.assertNotNull(pri.broadcastUsers); 130 Assert.assertEquals(5, pri.broadcastUsers.length); 131 Assert.assertNotNull(pri.instantUserIds); 132 Assert.assertEquals(0, pri.instantUserIds.length); 133 134 // Exclude a user 135 pri.broadcastUsers = null; 136 final int EXCLUDED_USER_ID = 4; 137 setting.setInstantApp(true, EXCLUDED_USER_ID); 138 pri.populateUsers(new int[] { 139 1, 2, 3, EXCLUDED_USER_ID, 5 140 }, setting); 141 Assert.assertNotNull(pri.broadcastUsers); 142 Assert.assertEquals(4, pri.broadcastUsers.length); 143 Assert.assertNotNull(pri.instantUserIds); 144 Assert.assertEquals(1, pri.instantUserIds.length); 145 146 // TODO: test that sendApplicationHiddenForUser() actually fills in 147 // broadcastUsers 148 } 149 150 @Test testPartitions()151 public void testPartitions() throws Exception { 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 PackageManagerService.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 <= PackageManagerInternal.LAST_KNOWN_PACKAGE; i++) { 175 packageNames.add(PackageManagerInternal.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 PackageManagerInternal.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 439 // Return the boolean locked value. A null return means the annotation was not 440 // found. This method will fail if the annotation is found but is not one of the 441 // known constants. getOverride(Method m)442 private Boolean getOverride(Method m) { 443 final String name = "Computer." + displayName(m); 444 final PackageManagerService.Computer.LiveImplementation annotation = 445 m.getAnnotation(PackageManagerService.Computer.LiveImplementation.class); 446 if (annotation == null) { 447 return null; 448 } 449 final int override = annotation.override(); 450 if (override == PackageManagerService.Computer.LiveImplementation.MANDATORY) { 451 return true; 452 } else if (override == PackageManagerService.Computer.LiveImplementation.NOT_ALLOWED) { 453 return false; 454 } else { 455 flag(name, "invalid Live value: " + override); 456 return null; 457 } 458 } 459 460 @Test testComputerStructure()461 public void testComputerStructure() { 462 // Verify that Copmuter methods are properly annotated and that ComputerLocked is 463 // properly populated per annotations. 464 // Call PackageManagerService.validateComputer(); 465 Class base = PackageManagerService.Computer.class; 466 467 HashMap<Method, Boolean> methodType = new HashMap<>(); 468 469 // Verify that all Computer methods are annotated and that the annotation 470 // parameter locked() is valid. 471 for (Method m : base.getDeclaredMethods()) { 472 final String name = "Computer." + displayName(m); 473 Boolean override = getOverride(m); 474 if (override == null) { 475 flag(name, "missing required Live annotation"); 476 } 477 methodType.put(m, override); 478 } 479 480 Class coreClass = PackageManagerService.ComputerEngine.class; 481 final Method[] coreMethods = coreClass.getDeclaredMethods(); 482 483 // Examine every method in the core. If it inherits from a base method it must be 484 // "public final" if the base is NOT_ALLOWED or "public" if the base is MANDATORY. 485 // If the core method does not inherit from the base then it must be either 486 // private or protected. 487 for (Method m : base.getDeclaredMethods()) { 488 String name = "Computer." + displayName(m); 489 final boolean locked = methodType.get(m); 490 final Method core = matchMethod(m, coreMethods); 491 if (core == null) { 492 flag(name, "not overridden in ComputerEngine"); 493 continue; 494 } 495 name = "ComputerEngine." + displayName(m); 496 final int modifiers = core.getModifiers(); 497 if (!locked) { 498 if (!isPublic(modifiers)) { 499 flag(name, "is not public"); 500 } 501 if (!isFinal(modifiers)) { 502 flag(name, "is not final"); 503 } 504 } 505 } 506 // Any methods left in the coreMethods array must be private or protected. 507 // Protected methods must be overridden (and final) in the live list. 508 Method[] coreHelpers = new Method[coreMethods.length]; 509 int coreIndex = 0; 510 for (Method m : coreMethods) { 511 if (m != null) { 512 final String name = "ComputerEngine." + displayName(m); 513 final int modifiers = m.getModifiers(); 514 if (isPrivate(modifiers)) { 515 // Okay 516 } else if (isProtected(modifiers)) { 517 coreHelpers[coreIndex++] = m; 518 } else { 519 flag(name, "is neither private nor protected"); 520 } 521 } 522 } 523 524 Class liveClass = PackageManagerService.ComputerLocked.class; 525 final Method[] liveMethods = liveClass.getDeclaredMethods(); 526 527 // Examine every method in the live list. Every method must be final and must 528 // inherit either from base or core. If the method inherits from a base method 529 // then the base must be MANDATORY. 530 for (Method m : base.getDeclaredMethods()) { 531 String name = "Computer." + displayName(m); 532 final boolean locked = methodType.get(m); 533 final Method live = matchMethod(m, liveMethods); 534 if (live == null) { 535 if (locked) { 536 flag(name, "not overridden in ComputerLocked"); 537 } 538 continue; 539 } 540 if (!locked) { 541 flag(name, "improperly overridden in ComputerLocked"); 542 continue; 543 } 544 545 name = "ComputerLocked." + displayName(m); 546 final int modifiers = live.getModifiers(); 547 if (!locked) { 548 if (!isPublic(modifiers)) { 549 flag(name, "is not public"); 550 } 551 if (!isFinal(modifiers)) { 552 flag(name, "is not final"); 553 } 554 } 555 } 556 for (Method m : coreHelpers) { 557 if (m == null) { 558 continue; 559 } 560 String name = "ComputerLocked." + displayName(m); 561 final Method live = matchMethod(m, liveMethods); 562 if (live == null) { 563 flag(name, "is not overridden in ComputerLocked"); 564 continue; 565 } 566 } 567 for (Method m : liveMethods) { 568 if (m != null) { 569 String name = "ComputerLocked." + displayName(m); 570 flag(name, "illegal local method"); 571 } 572 } 573 } 574 getPerPackageReadTimeouts(String knownDigestersList)575 private static PerPackageReadTimeouts[] getPerPackageReadTimeouts(String knownDigestersList) { 576 final String defaultTimeouts = "3600000001:3600000002:3600000003"; 577 List<PerPackageReadTimeouts> result = PerPackageReadTimeouts.parseDigestersList( 578 defaultTimeouts, knownDigestersList); 579 if (result == null) { 580 return null; 581 } 582 return result.toArray(new PerPackageReadTimeouts[result.size()]); 583 } 584 bytesToHexString(byte[] bytes)585 private static String bytesToHexString(byte[] bytes) { 586 return HexDump.toHexString(bytes, 0, bytes.length, /*upperCase=*/ false); 587 } 588 getKnownPackageIdsList()589 private List<Integer> getKnownPackageIdsList() throws IllegalAccessException { 590 final ArrayList<Integer> knownPackageIds = new ArrayList<>(); 591 final Field[] allFields = PackageManagerInternal.class.getDeclaredFields(); 592 for (Field field : allFields) { 593 final int modifier = field.getModifiers(); 594 if (isPublic(modifier) && isStatic(modifier) && isFinal(modifier) 595 && Pattern.matches("PACKAGE(_[A-Z]+)+", field.getName())) { 596 knownPackageIds.add(field.getInt(null)); 597 } 598 } 599 Collections.sort(knownPackageIds); 600 return knownPackageIds; 601 } 602 } 603