blob: 18992ecfd3a46bef43dd8742588fe79b125e20bd [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm;
import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.fail;
import static java.lang.reflect.Modifier.isFinal;
import static java.lang.reflect.Modifier.isPrivate;
import static java.lang.reflect.Modifier.isProtected;
import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isStatic;
import android.annotation.Nullable;
import android.app.AppGlobals;
import android.content.IIntentReceiver;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManagerInternal;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.SparseArray;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.HexDump;
import com.android.server.pm.PerPackageReadTimeouts.Timeouts;
import com.android.server.pm.PerPackageReadTimeouts.VersionCodes;
import com.google.android.collect.Lists;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;
// atest PackageManagerServiceTest
// runtest -c com.android.server.pm.PackageManagerServiceTest frameworks-services
// bit FrameworksServicesTests:com.android.server.pm.PackageManagerServiceTest
@RunWith(AndroidJUnit4.class)
public class PackageManagerServiceTest {
private static final String PACKAGE_NAME = "com.android.frameworks.servicestests";
private static final String TEST_DATA_PATH = "/data/local/tmp/servicestests/";
private static final String TEST_APP_APK = "StubTestApp.apk";
private static final String TEST_PKG_NAME = "com.android.servicestests.apps.stubapp";
private IPackageManager mIPackageManager;
@Before
public void setUp() throws Exception {
mIPackageManager = AppGlobals.getPackageManager();
}
@After
public void tearDown() throws Exception {
}
@Test
public void testPackageRemoval() throws Exception {
class PackageSenderImpl implements PackageSender {
public void sendPackageBroadcast(final String action, final String pkg,
final Bundle extras, final int flags, final String targetPkg,
final IIntentReceiver finishedReceiver, final int[] userIds,
int[] instantUserIds, SparseArray<int[]> broadcastAllowList,
@Nullable Bundle bOptions) {
}
public void sendPackageAddedForNewUsers(String packageName,
boolean sendBootComplete, boolean includeStopped, int appId,
int[] userIds, int[] instantUserIds, int dataLoaderType) {
}
@Override
public void notifyPackageAdded(String packageName, int uid) {
}
@Override
public void notifyPackageChanged(String packageName, int uid) {
}
@Override
public void notifyPackageRemoved(String packageName, int uid) {
}
}
PackageSenderImpl sender = new PackageSenderImpl();
PackageSetting setting = null;
PackageManagerService.PackageRemovedInfo pri =
new PackageManagerService.PackageRemovedInfo(sender);
// Initial conditions: nothing there
Assert.assertNull(pri.removedUsers);
Assert.assertNull(pri.broadcastUsers);
// populateUsers with nothing leaves nothing
pri.populateUsers(null, setting);
Assert.assertNull(pri.broadcastUsers);
// Create a real (non-null) PackageSetting and confirm that the removed
// users are copied properly
setting = new PackageSettingBuilder()
.setName("name")
.setRealName("realName")
.setCodePath("codePath")
.setLegacyNativeLibraryPathString("legacyNativeLibraryPathString")
.setPrimaryCpuAbiString("primaryCpuAbiString")
.setSecondaryCpuAbiString("secondaryCpuAbiString")
.setCpuAbiOverrideString("cpuAbiOverrideString")
.build();
pri.populateUsers(new int[] {
1, 2, 3, 4, 5
}, setting);
Assert.assertNotNull(pri.broadcastUsers);
Assert.assertEquals(5, pri.broadcastUsers.length);
Assert.assertNotNull(pri.instantUserIds);
Assert.assertEquals(0, pri.instantUserIds.length);
// Exclude a user
pri.broadcastUsers = null;
final int EXCLUDED_USER_ID = 4;
setting.setInstantApp(true, EXCLUDED_USER_ID);
pri.populateUsers(new int[] {
1, 2, 3, EXCLUDED_USER_ID, 5
}, setting);
Assert.assertNotNull(pri.broadcastUsers);
Assert.assertEquals(4, pri.broadcastUsers.length);
Assert.assertNotNull(pri.instantUserIds);
Assert.assertEquals(1, pri.instantUserIds.length);
// TODO: test that sendApplicationHiddenForUser() actually fills in
// broadcastUsers
}
@Test
public void testPartitions() throws Exception {
String[] partitions = { "system", "vendor", "odm", "oem", "product", "system_ext" };
String[] appdir = { "app", "priv-app" };
for (int i = 0; i < partitions.length; i++) {
final PackageManagerService.ScanPartition scanPartition =
PackageManagerService.SYSTEM_PARTITIONS.get(i);
for (int j = 0; j < appdir.length; j++) {
File path = new File(String.format("%s/%s/A.apk", partitions[i], appdir[j]));
Assert.assertEquals(j == 1 && i != 3, scanPartition.containsPrivApp(path));
final int scanFlag = scanPartition.scanFlag;
Assert.assertEquals(i == 1, scanFlag == PackageManagerService.SCAN_AS_VENDOR);
Assert.assertEquals(i == 2, scanFlag == PackageManagerService.SCAN_AS_ODM);
Assert.assertEquals(i == 3, scanFlag == PackageManagerService.SCAN_AS_OEM);
Assert.assertEquals(i == 4, scanFlag == PackageManagerService.SCAN_AS_PRODUCT);
Assert.assertEquals(i == 5, scanFlag == PackageManagerService.SCAN_AS_SYSTEM_EXT);
}
}
}
@Test
public void testKnownPackageToString_shouldNotGetUnknown() {
final List<String> packageNames = new ArrayList<>();
for (int i = 0; i <= PackageManagerInternal.LAST_KNOWN_PACKAGE; i++) {
packageNames.add(PackageManagerInternal.knownPackageToString(i));
}
assertWithMessage(
"The Ids of KnownPackage should be continuous and the string representation "
+ "should not be unknown.").that(
packageNames).containsNoneIn(Lists.newArrayList("Unknown"));
}
@Test
public void testKnownPackage_lastKnownPackageIsTheLast() throws Exception {
final List<Integer> knownPackageIds = getKnownPackageIdsList();
assertWithMessage(
"The last KnownPackage Id should be assigned to PackageManagerInternal"
+ ".LAST_KNOWN_PACKAGE.").that(
knownPackageIds.get(knownPackageIds.size() - 1)).isEqualTo(
PackageManagerInternal.LAST_KNOWN_PACKAGE);
}
@Test
public void testKnownPackage_IdsShouldBeUniqueAndContinuous() throws Exception {
final List<Integer> knownPackageIds = getKnownPackageIdsList();
for (int i = 0, size = knownPackageIds.size(); i < size - 1; i++) {
assertWithMessage(
"The KnownPackage Ids should be unique and continuous. KnownPackageIds = "
+ Arrays.toString(knownPackageIds.toArray())).that(
knownPackageIds.get(i) + 1).isEqualTo(knownPackageIds.get(i + 1));
}
}
@Test
public void testTimeouts() {
Timeouts defaults = Timeouts.parse("3600000001:3600000002:3600000003");
Assert.assertEquals(3600000001L, defaults.minTimeUs);
Assert.assertEquals(3600000002L, defaults.minPendingTimeUs);
Assert.assertEquals(3600000003L, defaults.maxPendingTimeUs);
Timeouts empty = Timeouts.parse("");
Assert.assertEquals(3600000000L, empty.minTimeUs);
Assert.assertEquals(3600000000L, empty.minPendingTimeUs);
Assert.assertEquals(3600000000L, empty.maxPendingTimeUs);
Timeouts partial0 = Timeouts.parse("10000::");
Assert.assertEquals(10000L, partial0.minTimeUs);
Assert.assertEquals(3600000000L, partial0.minPendingTimeUs);
Assert.assertEquals(3600000000L, partial0.maxPendingTimeUs);
Timeouts partial1 = Timeouts.parse("10000:10001:");
Assert.assertEquals(10000L, partial1.minTimeUs);
Assert.assertEquals(10001L, partial1.minPendingTimeUs);
Assert.assertEquals(3600000000L, partial1.maxPendingTimeUs);
Timeouts fullDefault = Timeouts.parse("3600000000:3600000000:3600000000");
Assert.assertEquals(3600000000L, fullDefault.minTimeUs);
Assert.assertEquals(3600000000L, fullDefault.minPendingTimeUs);
Assert.assertEquals(3600000000L, fullDefault.maxPendingTimeUs);
Timeouts full = Timeouts.parse("10000:10001:10002");
Assert.assertEquals(10000L, full.minTimeUs);
Assert.assertEquals(10001L, full.minPendingTimeUs);
Assert.assertEquals(10002L, full.maxPendingTimeUs);
Timeouts invalid0 = Timeouts.parse(":10000");
Assert.assertEquals(3600000000L, invalid0.minTimeUs);
Assert.assertEquals(3600000000L, invalid0.minPendingTimeUs);
Assert.assertEquals(3600000000L, invalid0.maxPendingTimeUs);
Timeouts invalid1 = Timeouts.parse(":10000::");
Assert.assertEquals(3600000000L, invalid1.minTimeUs);
Assert.assertEquals(3600000000L, invalid1.minPendingTimeUs);
Assert.assertEquals(3600000000L, invalid1.maxPendingTimeUs);
Timeouts invalid2 = Timeouts.parse("10000:10001:abcd");
Assert.assertEquals(10000L, invalid2.minTimeUs);
Assert.assertEquals(10001L, invalid2.minPendingTimeUs);
Assert.assertEquals(3600000000L, invalid2.maxPendingTimeUs);
Timeouts invalid3 = Timeouts.parse(":10000:");
Assert.assertEquals(3600000000L, invalid3.minTimeUs);
Assert.assertEquals(3600000000L, invalid3.minPendingTimeUs);
Assert.assertEquals(3600000000L, invalid3.maxPendingTimeUs);
Timeouts invalid4 = Timeouts.parse("abcd:10001:10002");
Assert.assertEquals(3600000000L, invalid4.minTimeUs);
Assert.assertEquals(3600000000L, invalid4.minPendingTimeUs);
Assert.assertEquals(3600000000L, invalid4.maxPendingTimeUs);
Timeouts invalid5 = Timeouts.parse("::1000000000000000000000000");
Assert.assertEquals(3600000000L, invalid5.minTimeUs);
Assert.assertEquals(3600000000L, invalid5.minPendingTimeUs);
Assert.assertEquals(3600000000L, invalid5.maxPendingTimeUs);
Timeouts invalid6 = Timeouts.parse("-10000:10001:10002");
Assert.assertEquals(3600000000L, invalid6.minTimeUs);
Assert.assertEquals(3600000000L, invalid6.minPendingTimeUs);
Assert.assertEquals(3600000000L, invalid6.maxPendingTimeUs);
}
@Test
public void testVersionCodes() {
final VersionCodes defaults = VersionCodes.parse("");
Assert.assertEquals(Long.MIN_VALUE, defaults.minVersionCode);
Assert.assertEquals(Long.MAX_VALUE, defaults.maxVersionCode);
VersionCodes single = VersionCodes.parse("191000070");
Assert.assertEquals(191000070, single.minVersionCode);
Assert.assertEquals(191000070, single.maxVersionCode);
VersionCodes single2 = VersionCodes.parse("191000070-191000070");
Assert.assertEquals(191000070, single2.minVersionCode);
Assert.assertEquals(191000070, single2.maxVersionCode);
VersionCodes upto = VersionCodes.parse("-191000070");
Assert.assertEquals(Long.MIN_VALUE, upto.minVersionCode);
Assert.assertEquals(191000070, upto.maxVersionCode);
VersionCodes andabove = VersionCodes.parse("191000070-");
Assert.assertEquals(191000070, andabove.minVersionCode);
Assert.assertEquals(Long.MAX_VALUE, andabove.maxVersionCode);
VersionCodes range = VersionCodes.parse("191000070-201000070");
Assert.assertEquals(191000070, range.minVersionCode);
Assert.assertEquals(201000070, range.maxVersionCode);
VersionCodes invalid0 = VersionCodes.parse("201000070-191000070");
Assert.assertEquals(Long.MIN_VALUE, invalid0.minVersionCode);
Assert.assertEquals(Long.MAX_VALUE, invalid0.maxVersionCode);
VersionCodes invalid1 = VersionCodes.parse("abcd-191000070");
Assert.assertEquals(Long.MIN_VALUE, invalid1.minVersionCode);
Assert.assertEquals(191000070, invalid1.maxVersionCode);
VersionCodes invalid2 = VersionCodes.parse("abcd");
Assert.assertEquals(Long.MIN_VALUE, invalid2.minVersionCode);
Assert.assertEquals(Long.MAX_VALUE, invalid2.maxVersionCode);
VersionCodes invalid3 = VersionCodes.parse("191000070-abcd");
Assert.assertEquals(191000070, invalid3.minVersionCode);
Assert.assertEquals(Long.MAX_VALUE, invalid3.maxVersionCode);
}
@Test
public void testPerPackageReadTimeouts() {
final String sha256 = "336faefc91bb2dddf9b21829106fbc607b862132fecd273e1b6b3ea55f09d4e1";
final VersionCodes defVCs = VersionCodes.parse("");
final Timeouts defTs = Timeouts.parse("3600000001:3600000002:3600000003");
PerPackageReadTimeouts empty = PerPackageReadTimeouts.parse("", defVCs, defTs);
Assert.assertNull(empty);
PerPackageReadTimeouts packageOnly = PerPackageReadTimeouts.parse("package.com", defVCs,
defTs);
Assert.assertEquals("package.com", packageOnly.packageName);
Assert.assertEquals(null, packageOnly.sha256certificate);
Assert.assertEquals(Long.MIN_VALUE, packageOnly.versionCodes.minVersionCode);
Assert.assertEquals(Long.MAX_VALUE, packageOnly.versionCodes.maxVersionCode);
Assert.assertEquals(3600000001L, packageOnly.timeouts.minTimeUs);
Assert.assertEquals(3600000002L, packageOnly.timeouts.minPendingTimeUs);
Assert.assertEquals(3600000003L, packageOnly.timeouts.maxPendingTimeUs);
PerPackageReadTimeouts packageHash = PerPackageReadTimeouts.parse(
"package.com:" + sha256, defVCs, defTs);
Assert.assertEquals("package.com", packageHash.packageName);
Assert.assertEquals(sha256, bytesToHexString(packageHash.sha256certificate));
Assert.assertEquals(Long.MIN_VALUE, packageHash.versionCodes.minVersionCode);
Assert.assertEquals(Long.MAX_VALUE, packageHash.versionCodes.maxVersionCode);
Assert.assertEquals(3600000001L, packageHash.timeouts.minTimeUs);
Assert.assertEquals(3600000002L, packageHash.timeouts.minPendingTimeUs);
Assert.assertEquals(3600000003L, packageHash.timeouts.maxPendingTimeUs);
PerPackageReadTimeouts packageVersionCode = PerPackageReadTimeouts.parse(
"package.com::191000070", defVCs, defTs);
Assert.assertEquals("package.com", packageVersionCode.packageName);
Assert.assertEquals(null, packageVersionCode.sha256certificate);
Assert.assertEquals(191000070, packageVersionCode.versionCodes.minVersionCode);
Assert.assertEquals(191000070, packageVersionCode.versionCodes.maxVersionCode);
Assert.assertEquals(3600000001L, packageVersionCode.timeouts.minTimeUs);
Assert.assertEquals(3600000002L, packageVersionCode.timeouts.minPendingTimeUs);
Assert.assertEquals(3600000003L, packageVersionCode.timeouts.maxPendingTimeUs);
PerPackageReadTimeouts full = PerPackageReadTimeouts.parse(
"package.com:" + sha256 + ":191000070-201000070:10001:10002:10003", defVCs, defTs);
Assert.assertEquals("package.com", full.packageName);
Assert.assertEquals(sha256, bytesToHexString(full.sha256certificate));
Assert.assertEquals(191000070, full.versionCodes.minVersionCode);
Assert.assertEquals(201000070, full.versionCodes.maxVersionCode);
Assert.assertEquals(10001L, full.timeouts.minTimeUs);
Assert.assertEquals(10002L, full.timeouts.minPendingTimeUs);
Assert.assertEquals(10003L, full.timeouts.maxPendingTimeUs);
}
@Test
public void testGetPerPackageReadTimeouts() {
Assert.assertEquals(0, getPerPackageReadTimeouts(null).length);
Assert.assertEquals(0, getPerPackageReadTimeouts("").length);
Assert.assertEquals(0, getPerPackageReadTimeouts(",,,,").length);
final String sha256 = "0fae93f1a7925b4c68bbea80ad3eaa41acfc9bc6f10bf1054f5d93a2bd556093";
PerPackageReadTimeouts[] singlePackage = getPerPackageReadTimeouts(
"package.com:" + sha256 + ":191000070-201000070:10001:10002:10003");
Assert.assertEquals(1, singlePackage.length);
Assert.assertEquals("package.com", singlePackage[0].packageName);
Assert.assertEquals(sha256, bytesToHexString(singlePackage[0].sha256certificate));
Assert.assertEquals(191000070, singlePackage[0].versionCodes.minVersionCode);
Assert.assertEquals(201000070, singlePackage[0].versionCodes.maxVersionCode);
Assert.assertEquals(10001L, singlePackage[0].timeouts.minTimeUs);
Assert.assertEquals(10002L, singlePackage[0].timeouts.minPendingTimeUs);
Assert.assertEquals(10003L, singlePackage[0].timeouts.maxPendingTimeUs);
PerPackageReadTimeouts[] multiPackage = getPerPackageReadTimeouts("package.com:" + sha256
+ ":191000070-201000070:10001:10002:10003,package1.com::123456");
Assert.assertEquals(2, multiPackage.length);
Assert.assertEquals("package.com", multiPackage[0].packageName);
Assert.assertEquals(sha256, bytesToHexString(multiPackage[0].sha256certificate));
Assert.assertEquals(191000070, multiPackage[0].versionCodes.minVersionCode);
Assert.assertEquals(201000070, multiPackage[0].versionCodes.maxVersionCode);
Assert.assertEquals(10001L, multiPackage[0].timeouts.minTimeUs);
Assert.assertEquals(10002L, multiPackage[0].timeouts.minPendingTimeUs);
Assert.assertEquals(10003L, multiPackage[0].timeouts.maxPendingTimeUs);
Assert.assertEquals("package1.com", multiPackage[1].packageName);
Assert.assertEquals(null, multiPackage[1].sha256certificate);
Assert.assertEquals(123456, multiPackage[1].versionCodes.minVersionCode);
Assert.assertEquals(123456, multiPackage[1].versionCodes.maxVersionCode);
Assert.assertEquals(3600000001L, multiPackage[1].timeouts.minTimeUs);
Assert.assertEquals(3600000002L, multiPackage[1].timeouts.minPendingTimeUs);
Assert.assertEquals(3600000003L, multiPackage[1].timeouts.maxPendingTimeUs);
}
// Report an error from the Computer structure validation test.
private void flag(String name, String msg) {
fail(name + " " + msg);
}
// Return a string that identifies a Method. This is not very efficient but it is not
// called very often.
private String displayName(Method m) {
String r = m.getName();
String p = Arrays.toString(m.getGenericParameterTypes())
.replaceAll("([a-zA-Z0-9]+\\.)+", "")
.replace("class ", "")
.replaceAll("^\\[", "(")
.replaceAll("\\]$", ")");
return r + p;
}
// Match a method to an array of Methods. Matching is on method signature: name and
// parameter types. If a method in the declared array matches, return it. Otherwise
// return null.
private Method matchMethod(Method m, Method[] declared) {
String n = m.getName();
Type[] t = m.getGenericParameterTypes();
for (int i = 0; i < declared.length; i++) {
Method l = declared[i];
if (l != null && l.getName().equals(n)
&& Arrays.equals(l.getGenericParameterTypes(), t)) {
Method result = l;
// Set the method to null since it has been visited already.
declared[i] = null;
return result;
}
}
return null;
}
// Return the boolean locked value. A null return means the annotation was not
// found. This method will fail if the annotation is found but is not one of the
// known constants.
private Boolean getOverride(Method m) {
final String name = "Computer." + displayName(m);
final PackageManagerService.Computer.LiveImplementation annotation =
m.getAnnotation(PackageManagerService.Computer.LiveImplementation.class);
if (annotation == null) {
return null;
}
final int override = annotation.override();
if (override == PackageManagerService.Computer.LiveImplementation.MANDATORY) {
return true;
} else if (override == PackageManagerService.Computer.LiveImplementation.NOT_ALLOWED) {
return false;
} else {
flag(name, "invalid Live value: " + override);
return null;
}
}
@Test
public void testComputerStructure() {
// Verify that Copmuter methods are properly annotated and that ComputerLocked is
// properly populated per annotations.
// Call PackageManagerService.validateComputer();
Class base = PackageManagerService.Computer.class;
HashMap<Method, Boolean> methodType = new HashMap<>();
// Verify that all Computer methods are annotated and that the annotation
// parameter locked() is valid.
for (Method m : base.getDeclaredMethods()) {
final String name = "Computer." + displayName(m);
Boolean override = getOverride(m);
if (override == null) {
flag(name, "missing required Live annotation");
}
methodType.put(m, override);
}
Class coreClass = PackageManagerService.ComputerEngine.class;
final Method[] coreMethods = coreClass.getDeclaredMethods();
// Examine every method in the core. If it inherits from a base method it must be
// "public final" if the base is NOT_ALLOWED or "public" if the base is MANDATORY.
// If the core method does not inherit from the base then it must be either
// private or protected.
for (Method m : base.getDeclaredMethods()) {
String name = "Computer." + displayName(m);
final boolean locked = methodType.get(m);
final Method core = matchMethod(m, coreMethods);
if (core == null) {
flag(name, "not overridden in ComputerEngine");
continue;
}
name = "ComputerEngine." + displayName(m);
final int modifiers = core.getModifiers();
if (!locked) {
if (!isPublic(modifiers)) {
flag(name, "is not public");
}
if (!isFinal(modifiers)) {
flag(name, "is not final");
}
}
}
// Any methods left in the coreMethods array must be private or protected.
// Protected methods must be overridden (and final) in the live list.
Method[] coreHelpers = new Method[coreMethods.length];
int coreIndex = 0;
for (Method m : coreMethods) {
if (m != null) {
final String name = "ComputerEngine." + displayName(m);
final int modifiers = m.getModifiers();
if (isPrivate(modifiers)) {
// Okay
} else if (isProtected(modifiers)) {
coreHelpers[coreIndex++] = m;
} else {
flag(name, "is neither private nor protected");
}
}
}
Class liveClass = PackageManagerService.ComputerLocked.class;
final Method[] liveMethods = liveClass.getDeclaredMethods();
// Examine every method in the live list. Every method must be final and must
// inherit either from base or core. If the method inherits from a base method
// then the base must be MANDATORY.
for (Method m : base.getDeclaredMethods()) {
String name = "Computer." + displayName(m);
final boolean locked = methodType.get(m);
final Method live = matchMethod(m, liveMethods);
if (live == null) {
if (locked) {
flag(name, "not overridden in ComputerLocked");
}
continue;
}
if (!locked) {
flag(name, "improperly overridden in ComputerLocked");
continue;
}
name = "ComputerLocked." + displayName(m);
final int modifiers = live.getModifiers();
if (!locked) {
if (!isPublic(modifiers)) {
flag(name, "is not public");
}
if (!isFinal(modifiers)) {
flag(name, "is not final");
}
}
}
for (Method m : coreHelpers) {
if (m == null) {
continue;
}
String name = "ComputerLocked." + displayName(m);
final Method live = matchMethod(m, liveMethods);
if (live == null) {
flag(name, "is not overridden in ComputerLocked");
continue;
}
}
for (Method m : liveMethods) {
if (m != null) {
String name = "ComputerLocked." + displayName(m);
flag(name, "illegal local method");
}
}
}
private static PerPackageReadTimeouts[] getPerPackageReadTimeouts(String knownDigestersList) {
final String defaultTimeouts = "3600000001:3600000002:3600000003";
List<PerPackageReadTimeouts> result = PerPackageReadTimeouts.parseDigestersList(
defaultTimeouts, knownDigestersList);
if (result == null) {
return null;
}
return result.toArray(new PerPackageReadTimeouts[result.size()]);
}
private static String bytesToHexString(byte[] bytes) {
return HexDump.toHexString(bytes, 0, bytes.length, /*upperCase=*/ false);
}
private List<Integer> getKnownPackageIdsList() throws IllegalAccessException {
final ArrayList<Integer> knownPackageIds = new ArrayList<>();
final Field[] allFields = PackageManagerInternal.class.getDeclaredFields();
for (Field field : allFields) {
final int modifier = field.getModifiers();
if (isPublic(modifier) && isStatic(modifier) && isFinal(modifier)
&& Pattern.matches("PACKAGE(_[A-Z]+)+", field.getName())) {
knownPackageIds.add(field.getInt(null));
}
}
Collections.sort(knownPackageIds);
return knownPackageIds;
}
@Test
public void testSetSplashScreenTheme_samePackage_succeeds() throws Exception {
mIPackageManager.setSplashScreenTheme(PACKAGE_NAME, null /* themeName */,
UserHandle.myUserId());
// Invoking setSplashScreenTheme on the same package shouldn't get any exception.
}
@Test
public void testSetSplashScreenTheme_differentPackage_fails() throws Exception {
final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK);
try {
runShellCommand("pm install " + testApk);
mIPackageManager.setSplashScreenTheme(TEST_PKG_NAME, null /* themeName */,
UserHandle.myUserId());
fail("setSplashScreenTheme did not throw SecurityException as expected");
} catch (SecurityException e) {
// expected
} finally {
runShellCommand("pm uninstall " + TEST_PKG_NAME);
}
}
}