• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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