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