/* * Copyright (C) 2012 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 android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageParser; import android.content.pm.PackageUserState; import android.content.pm.UserInfo; import android.os.Process; import android.os.UserHandle; import android.os.UserManagerInternal; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.LongSparseArray; import com.android.internal.os.AtomicFile; import com.android.internal.util.FastPrintWriter; import com.android.server.LocalServices; import org.hamcrest.core.IsNot; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.security.PublicKey; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @RunWith(AndroidJUnit4.class) @SmallTest public class PackageManagerSettingsTests { private static final String PACKAGE_NAME_2 = "com.google.app2"; private static final String PACKAGE_NAME_3 = "com.android.app3"; private static final String PACKAGE_NAME_1 = "com.google.app1"; public static final String TAG = "PackageManagerSettingsTests"; protected final String PREFIX = "android.content.pm"; /** make sure our initialized KeySetManagerService metadata matches packages.xml */ @Test public void testReadKeySetSettings() throws ReflectiveOperationException, IllegalAccessException { /* write out files and read */ writeOldFiles(); Settings settings = new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object()); assertThat(settings.readLPw(createFakeUsers()), is(true)); verifyKeySetMetaData(settings); } /** read in data, write it out, and read it back in. Verify same. */ @Test public void testWriteKeySetSettings() throws ReflectiveOperationException, IllegalAccessException { // write out files and read writeOldFiles(); Settings settings = new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object()); assertThat(settings.readLPw(createFakeUsers()), is(true)); // write out, read back in and verify the same settings.writeLPr(); assertThat(settings.readLPw(createFakeUsers()), is(true)); verifyKeySetMetaData(settings); } @Test public void testSettingsReadOld() { // Write the package files and make sure they're parsed properly the first time writeOldFiles(); Settings settings = new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object()); assertThat(settings.readLPw(createFakeUsers()), is(true)); assertThat(settings.getPackageLPr(PACKAGE_NAME_3), is(notNullValue())); assertThat(settings.getPackageLPr(PACKAGE_NAME_1), is(notNullValue())); PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_1); assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DEFAULT)); assertThat(ps.getNotLaunched(0), is(true)); ps = settings.getPackageLPr(PACKAGE_NAME_2); assertThat(ps.getStopped(0), is(false)); assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED_USER)); assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_DEFAULT)); } @Test public void testNewPackageRestrictionsFile() throws ReflectiveOperationException { // Write the package files and make sure they're parsed properly the first time writeOldFiles(); Settings settings = new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object()); assertThat(settings.readLPw(createFakeUsers()), is(true)); settings.writeLPr(); // Create Settings again to make it read from the new files settings = new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object()); assertThat(settings.readLPw(createFakeUsers()), is(true)); PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_2); assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED_USER)); assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_DEFAULT)); } @Test public void testEnableDisable() { // Write the package files and make sure they're parsed properly the first time writeOldFiles(); Settings settings = new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object()); assertThat(settings.readLPw(createFakeUsers()), is(true)); // Enable/Disable a package PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_1); ps.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0, null); ps.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 1, null); assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED)); assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_ENABLED)); // Enable/Disable a component ArraySet components = new ArraySet(); String component1 = PACKAGE_NAME_1 + "/.Component1"; components.add(component1); ps.setDisabledComponents(components, 0); ArraySet componentsDisabled = ps.getDisabledComponents(0); assertThat(componentsDisabled.size(), is(1)); assertThat(componentsDisabled.toArray()[0], is(component1)); boolean hasEnabled = ps.getEnabledComponents(0) != null && ps.getEnabledComponents(1).size() > 0; assertThat(hasEnabled, is(false)); // User 1 should not have any disabled components boolean hasDisabled = ps.getDisabledComponents(1) != null && ps.getDisabledComponents(1).size() > 0; assertThat(hasDisabled, is(false)); ps.setEnabledComponents(components, 1); assertThat(ps.getEnabledComponents(1).size(), is(1)); hasEnabled = ps.getEnabledComponents(0) != null && ps.getEnabledComponents(0).size() > 0; assertThat(hasEnabled, is(false)); } private static final String PACKAGE_NAME = "com.android.bar"; private static final String REAL_PACKAGE_NAME = "com.android.foo"; private static final String PARENT_PACKAGE_NAME = "com.android.bar.parent"; private static final String CHILD_PACKAGE_NAME_01 = "com.android.bar.child01"; private static final String CHILD_PACKAGE_NAME_02 = "com.android.bar.child02"; private static final String CHILD_PACKAGE_NAME_03 = "com.android.bar.child03"; private static final File INITIAL_CODE_PATH = new File(InstrumentationRegistry.getContext().getFilesDir(), "com.android.bar-1"); private static final File UPDATED_CODE_PATH = new File(InstrumentationRegistry.getContext().getFilesDir(), "com.android.bar-2"); private static final int INITIAL_VERSION_CODE = 10023; private static final int UPDATED_VERSION_CODE = 10025; @Test public void testPackageStateCopy01() { final List childPackageNames = new ArrayList<>(); childPackageNames.add(CHILD_PACKAGE_NAME_01); childPackageNames.add(CHILD_PACKAGE_NAME_02); childPackageNames.add(CHILD_PACKAGE_NAME_03); final PackageSetting origPkgSetting01 = new PackageSetting( PACKAGE_NAME, REAL_PACKAGE_NAME, INITIAL_CODE_PATH /*codePath*/, INITIAL_CODE_PATH /*resourcePath*/, null /*legacyNativeLibraryPathString*/, "x86_64" /*primaryCpuAbiString*/, "x86" /*secondaryCpuAbiString*/, null /*cpuAbiOverrideString*/, INITIAL_VERSION_CODE, ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_HAS_CODE, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN, PARENT_PACKAGE_NAME, childPackageNames, 0, null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); final PackageSetting testPkgSetting01 = new PackageSetting(origPkgSetting01); verifySettingCopy(origPkgSetting01, testPkgSetting01); } @Test public void testPackageStateCopy02() { final List childPackageNames = new ArrayList<>(); childPackageNames.add(CHILD_PACKAGE_NAME_01); childPackageNames.add(CHILD_PACKAGE_NAME_02); childPackageNames.add(CHILD_PACKAGE_NAME_03); final PackageSetting origPkgSetting01 = new PackageSetting( PACKAGE_NAME /*pkgName*/, REAL_PACKAGE_NAME /*realPkgName*/, INITIAL_CODE_PATH /*codePath*/, INITIAL_CODE_PATH /*resourcePath*/, null /*legacyNativeLibraryPathString*/, "x86_64" /*primaryCpuAbiString*/, "x86" /*secondaryCpuAbiString*/, null /*cpuAbiOverrideString*/, INITIAL_VERSION_CODE, ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_HAS_CODE, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN, PARENT_PACKAGE_NAME, childPackageNames, 0, null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); final PackageSetting testPkgSetting01 = new PackageSetting( PACKAGE_NAME /*pkgName*/, REAL_PACKAGE_NAME /*realPkgName*/, UPDATED_CODE_PATH /*codePath*/, UPDATED_CODE_PATH /*resourcePath*/, null /*legacyNativeLibraryPathString*/, null /*primaryCpuAbiString*/, null /*secondaryCpuAbiString*/, null /*cpuAbiOverrideString*/, UPDATED_VERSION_CODE, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, null /*parentPkgName*/, null /*childPkgNames*/, 0, null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); testPkgSetting01.copyFrom(origPkgSetting01); verifySettingCopy(origPkgSetting01, testPkgSetting01); } /** Update package */ @Test public void testUpdatePackageSetting01() throws PackageManagerException { final PackageSetting testPkgSetting01 = createPackageSetting(0 /*sharedUserId*/, 0 /*pkgFlags*/); testPkgSetting01.setInstalled(false /*installed*/, 0 /*userId*/); assertThat(testPkgSetting01.pkgFlags, is(0)); assertThat(testPkgSetting01.pkgPrivateFlags, is(0)); final PackageSetting oldPkgSetting01 = new PackageSetting(testPkgSetting01); Settings.updatePackageSetting( testPkgSetting01, null /*disabledPkg*/, null /*sharedUser*/, UPDATED_CODE_PATH /*codePath*/, null /*legacyNativeLibraryPath*/, "arm64-v8a" /*primaryCpuAbi*/, "armeabi" /*secondaryCpuAbi*/, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a")); assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi")); assertThat(testPkgSetting01.origPackage, is(nullValue())); assertThat(testPkgSetting01.pkgFlags, is(0)); assertThat(testPkgSetting01.pkgPrivateFlags, is(0)); final PackageUserState userState = testPkgSetting01.readUserState(0); final PackageUserState oldUserState = oldPkgSetting01.readUserState(0); verifyUserState(userState, oldUserState, false /*userStateChanged*/, false /*notLaunched*/, false /*stopped*/, false /*installed*/); } /** Update package; package now on /system, install for user '0' */ @Test public void testUpdatePackageSetting02() throws PackageManagerException { final PackageSetting testPkgSetting01 = createPackageSetting(0 /*sharedUserId*/, 0 /*pkgFlags*/); testPkgSetting01.setInstalled(false /*installed*/, 0 /*userId*/); assertThat(testPkgSetting01.pkgFlags, is(0)); assertThat(testPkgSetting01.pkgPrivateFlags, is(0)); final PackageSetting oldPkgSetting01 = new PackageSetting(testPkgSetting01); Settings.updatePackageSetting( testPkgSetting01, null /*disabledPkg*/, null /*sharedUser*/, UPDATED_CODE_PATH /*codePath*/, null /*legacyNativeLibraryPath*/, "arm64-v8a" /*primaryCpuAbi*/, "armeabi" /*secondaryCpuAbi*/, ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/, null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a")); assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi")); assertThat(testPkgSetting01.origPackage, is(nullValue())); assertThat(testPkgSetting01.pkgFlags, is(ApplicationInfo.FLAG_SYSTEM)); assertThat(testPkgSetting01.pkgPrivateFlags, is(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)); final PackageUserState userState = testPkgSetting01.readUserState(0); final PackageUserState oldUserState = oldPkgSetting01.readUserState(0); // WARNING: When creating a shallow copy of the PackageSetting we do NOT create // new contained objects. For example, this means that changes to the user state // in testPkgSetting01 will also change the user state in its copy. verifyUserState(userState, oldUserState, false /*userStateChanged*/, false /*notLaunched*/, false /*stopped*/, true /*installed*/); } /** Update package; changing shared user throws exception */ @Test public void testUpdatePackageSetting03() { final Settings testSettings01 = new Settings(new Object() /*lock*/); final SharedUserSetting testUserSetting01 = createSharedUserSetting( testSettings01, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/); final PackageSetting testPkgSetting01 = createPackageSetting(0 /*sharedUserId*/, 0 /*pkgFlags*/); try { Settings.updatePackageSetting( testPkgSetting01, null /*disabledPkg*/, testUserSetting01 /*sharedUser*/, UPDATED_CODE_PATH /*codePath*/, null /*legacyNativeLibraryPath*/, "arm64-v8a" /*primaryCpuAbi*/, "armeabi" /*secondaryCpuAbi*/, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); fail("Expected a PackageManagerException"); } catch (PackageManagerException expected) { } } /** Create a new PackageSetting based on an original package setting */ @Test public void testCreateNewSetting01() { final PackageSetting originalPkgSetting01 = createPackageSetting(0 /*sharedUserId*/, 0 /*pkgFlags*/); final PackageSignatures originalSignatures = originalPkgSetting01.signatures; final PackageSetting testPkgSetting01 = Settings.createNewSetting( REAL_PACKAGE_NAME, originalPkgSetting01 /*originalPkg*/, null /*disabledPkg*/, null /*realPkgName*/, null /*sharedUser*/, UPDATED_CODE_PATH /*codePath*/, UPDATED_CODE_PATH /*resourcePath*/, null /*legacyNativeLibraryPath*/, "arm64-v8a" /*primaryCpuAbi*/, "armeabi" /*secondaryCpuAbi*/, UPDATED_VERSION_CODE /*versionCode*/, ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/, null /*installUser*/, false /*allowInstall*/, null /*parentPkgName*/, null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); assertThat(testPkgSetting01.codePath, is(UPDATED_CODE_PATH)); assertThat(testPkgSetting01.name, is(PACKAGE_NAME)); assertThat(testPkgSetting01.pkgFlags, is(ApplicationInfo.FLAG_SYSTEM)); assertThat(testPkgSetting01.pkgPrivateFlags, is(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)); assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a")); assertThat(testPkgSetting01.resourcePath, is(UPDATED_CODE_PATH)); assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi")); assertSame(testPkgSetting01.origPackage, originalPkgSetting01); // signatures object must be different assertNotSame(testPkgSetting01.signatures, originalSignatures); assertThat(testPkgSetting01.versionCode, is(UPDATED_VERSION_CODE)); final PackageUserState userState = testPkgSetting01.readUserState(0); verifyUserState(userState, null /*oldUserState*/, false /*userStateChanged*/, false /*notLaunched*/, false /*stopped*/, true /*installed*/); } /** Create a new non-system PackageSetting */ @Test public void testCreateNewSetting02() { final PackageSetting testPkgSetting01 = Settings.createNewSetting( PACKAGE_NAME, null /*originalPkg*/, null /*disabledPkg*/, null /*realPkgName*/, null /*sharedUser*/, INITIAL_CODE_PATH /*codePath*/, INITIAL_CODE_PATH /*resourcePath*/, null /*legacyNativeLibraryPath*/, "x86_64" /*primaryCpuAbiString*/, "x86" /*secondaryCpuAbiString*/, INITIAL_VERSION_CODE /*versionCode*/, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, UserHandle.SYSTEM /*installUser*/, true /*allowInstall*/, null /*parentPkgName*/, null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); assertThat(testPkgSetting01.appId, is(0)); assertThat(testPkgSetting01.codePath, is(INITIAL_CODE_PATH)); assertThat(testPkgSetting01.name, is(PACKAGE_NAME)); assertThat(testPkgSetting01.origPackage, is(nullValue())); assertThat(testPkgSetting01.pkgFlags, is(0)); assertThat(testPkgSetting01.pkgPrivateFlags, is(0)); assertThat(testPkgSetting01.primaryCpuAbiString, is("x86_64")); assertThat(testPkgSetting01.resourcePath, is(INITIAL_CODE_PATH)); assertThat(testPkgSetting01.secondaryCpuAbiString, is("x86")); assertThat(testPkgSetting01.versionCode, is(INITIAL_VERSION_CODE)); // by default, the package is considered stopped final PackageUserState userState = testPkgSetting01.readUserState(0); verifyUserState(userState, null /*oldUserState*/, false /*userStateChanged*/, true /*notLaunched*/, true /*stopped*/, true /*installed*/); } /** Create PackageSetting for a shared user */ @Test public void testCreateNewSetting03() { final Settings testSettings01 = new Settings(new Object() /*lock*/); final SharedUserSetting testUserSetting01 = createSharedUserSetting( testSettings01, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/); final PackageSetting testPkgSetting01 = Settings.createNewSetting( PACKAGE_NAME, null /*originalPkg*/, null /*disabledPkg*/, null /*realPkgName*/, testUserSetting01 /*sharedUser*/, INITIAL_CODE_PATH /*codePath*/, INITIAL_CODE_PATH /*resourcePath*/, null /*legacyNativeLibraryPath*/, "x86_64" /*primaryCpuAbiString*/, "x86" /*secondaryCpuAbiString*/, INITIAL_VERSION_CODE /*versionCode*/, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, null /*installUser*/, false /*allowInstall*/, null /*parentPkgName*/, null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); assertThat(testPkgSetting01.appId, is(10064)); assertThat(testPkgSetting01.codePath, is(INITIAL_CODE_PATH)); assertThat(testPkgSetting01.name, is(PACKAGE_NAME)); assertThat(testPkgSetting01.origPackage, is(nullValue())); assertThat(testPkgSetting01.pkgFlags, is(0)); assertThat(testPkgSetting01.pkgPrivateFlags, is(0)); assertThat(testPkgSetting01.primaryCpuAbiString, is("x86_64")); assertThat(testPkgSetting01.resourcePath, is(INITIAL_CODE_PATH)); assertThat(testPkgSetting01.secondaryCpuAbiString, is("x86")); assertThat(testPkgSetting01.versionCode, is(INITIAL_VERSION_CODE)); final PackageUserState userState = testPkgSetting01.readUserState(0); verifyUserState(userState, null /*oldUserState*/, false /*userStateChanged*/, false /*notLaunched*/, false /*stopped*/, true /*installed*/); } /** Create a new PackageSetting based on a disabled package setting */ @Test public void testCreateNewSetting04() { final PackageSetting disabledPkgSetting01 = createPackageSetting(0 /*sharedUserId*/, 0 /*pkgFlags*/); disabledPkgSetting01.appId = 10064; final PackageSignatures disabledSignatures = disabledPkgSetting01.signatures; final PackageSetting testPkgSetting01 = Settings.createNewSetting( PACKAGE_NAME, null /*originalPkg*/, disabledPkgSetting01 /*disabledPkg*/, null /*realPkgName*/, null /*sharedUser*/, UPDATED_CODE_PATH /*codePath*/, UPDATED_CODE_PATH /*resourcePath*/, null /*legacyNativeLibraryPath*/, "arm64-v8a" /*primaryCpuAbi*/, "armeabi" /*secondaryCpuAbi*/, UPDATED_VERSION_CODE /*versionCode*/, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, null /*installUser*/, false /*allowInstall*/, null /*parentPkgName*/, null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); assertThat(testPkgSetting01.appId, is(10064)); assertThat(testPkgSetting01.codePath, is(UPDATED_CODE_PATH)); assertThat(testPkgSetting01.name, is(PACKAGE_NAME)); assertThat(testPkgSetting01.origPackage, is(nullValue())); assertThat(testPkgSetting01.pkgFlags, is(0)); assertThat(testPkgSetting01.pkgPrivateFlags, is(0)); assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a")); assertThat(testPkgSetting01.resourcePath, is(UPDATED_CODE_PATH)); assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi")); assertNotSame(testPkgSetting01.signatures, disabledSignatures); assertThat(testPkgSetting01.versionCode, is(UPDATED_VERSION_CODE)); final PackageUserState userState = testPkgSetting01.readUserState(0); verifyUserState(userState, null /*oldUserState*/, false /*userStateChanged*/, false /*notLaunched*/, false /*stopped*/, true /*installed*/); } private void verifyUserState(PackageUserState userState, PackageUserState oldUserState, boolean userStateChanged) { verifyUserState(userState, oldUserState, userStateChanged, false /*notLaunched*/, false /*stopped*/, true /*installed*/); } private void verifyUserState(PackageUserState userState, PackageUserState oldUserState, boolean userStateChanged, boolean notLaunched, boolean stopped, boolean installed) { assertThat(userState.blockUninstall, is(false)); assertThat(userState.enabled, is(0)); assertThat(userState.hidden, is(false)); assertThat(userState.installed, is(installed)); assertThat(userState.notLaunched, is(notLaunched)); assertThat(userState.stopped, is(stopped)); assertThat(userState.suspended, is(false)); if (oldUserState != null) { assertThat(userState.equals(oldUserState), is(not(userStateChanged))); } } private void verifySettingCopy(PackageSetting origPkgSetting, PackageSetting testPkgSetting) { assertThat(origPkgSetting, is(not(testPkgSetting))); assertThat(origPkgSetting.appId, is(testPkgSetting.appId)); // different but equal objects assertNotSame(origPkgSetting.childPackageNames, testPkgSetting.childPackageNames); assertThat(origPkgSetting.childPackageNames, is(testPkgSetting.childPackageNames)); assertSame(origPkgSetting.codePath, testPkgSetting.codePath); assertThat(origPkgSetting.codePath, is(testPkgSetting.codePath)); assertSame(origPkgSetting.codePathString, testPkgSetting.codePathString); assertThat(origPkgSetting.codePathString, is(testPkgSetting.codePathString)); assertSame(origPkgSetting.cpuAbiOverrideString, testPkgSetting.cpuAbiOverrideString); assertThat(origPkgSetting.cpuAbiOverrideString, is(testPkgSetting.cpuAbiOverrideString)); assertThat(origPkgSetting.firstInstallTime, is(testPkgSetting.firstInstallTime)); assertSame(origPkgSetting.installerPackageName, testPkgSetting.installerPackageName); assertThat(origPkgSetting.installerPackageName, is(testPkgSetting.installerPackageName)); assertThat(origPkgSetting.installPermissionsFixed, is(testPkgSetting.installPermissionsFixed)); assertThat(origPkgSetting.installStatus, is(testPkgSetting.installStatus)); assertThat(origPkgSetting.isOrphaned, is(testPkgSetting.isOrphaned)); assertSame(origPkgSetting.keySetData, testPkgSetting.keySetData); assertThat(origPkgSetting.keySetData, is(testPkgSetting.keySetData)); assertThat(origPkgSetting.lastUpdateTime, is(testPkgSetting.lastUpdateTime)); assertSame(origPkgSetting.legacyNativeLibraryPathString, testPkgSetting.legacyNativeLibraryPathString); assertThat(origPkgSetting.legacyNativeLibraryPathString, is(testPkgSetting.legacyNativeLibraryPathString)); assertNotSame(origPkgSetting.mPermissionsState, testPkgSetting.mPermissionsState); assertThat(origPkgSetting.mPermissionsState, is(testPkgSetting.mPermissionsState)); assertThat(origPkgSetting.name, is(testPkgSetting.name)); // oldCodePaths is _not_ copied // assertNotSame(origPkgSetting.oldCodePaths, testPkgSetting.oldCodePaths); // assertThat(origPkgSetting.oldCodePaths, is(not(testPkgSetting.oldCodePaths))); assertSame(origPkgSetting.origPackage, testPkgSetting.origPackage); assertThat(origPkgSetting.origPackage, is(testPkgSetting.origPackage)); assertSame(origPkgSetting.parentPackageName, testPkgSetting.parentPackageName); assertThat(origPkgSetting.parentPackageName, is(testPkgSetting.parentPackageName)); assertSame(origPkgSetting.pkg, testPkgSetting.pkg); // No equals() method for this object // assertThat(origPkgSetting.pkg, is(testPkgSetting.pkg)); assertThat(origPkgSetting.pkgFlags, is(testPkgSetting.pkgFlags)); assertThat(origPkgSetting.pkgPrivateFlags, is(testPkgSetting.pkgPrivateFlags)); assertSame(origPkgSetting.primaryCpuAbiString, testPkgSetting.primaryCpuAbiString); assertThat(origPkgSetting.primaryCpuAbiString, is(testPkgSetting.primaryCpuAbiString)); assertThat(origPkgSetting.realName, is(testPkgSetting.realName)); assertSame(origPkgSetting.resourcePath, testPkgSetting.resourcePath); assertThat(origPkgSetting.resourcePath, is(testPkgSetting.resourcePath)); assertSame(origPkgSetting.resourcePathString, testPkgSetting.resourcePathString); assertThat(origPkgSetting.resourcePathString, is(testPkgSetting.resourcePathString)); assertSame(origPkgSetting.secondaryCpuAbiString, testPkgSetting.secondaryCpuAbiString); assertThat(origPkgSetting.secondaryCpuAbiString, is(testPkgSetting.secondaryCpuAbiString)); assertSame(origPkgSetting.sharedUser, testPkgSetting.sharedUser); assertThat(origPkgSetting.sharedUser, is(testPkgSetting.sharedUser)); assertSame(origPkgSetting.signatures, testPkgSetting.signatures); assertThat(origPkgSetting.signatures, is(testPkgSetting.signatures)); assertThat(origPkgSetting.timeStamp, is(testPkgSetting.timeStamp)); assertThat(origPkgSetting.uidError, is(testPkgSetting.uidError)); assertNotSame(origPkgSetting.getUserState(), is(testPkgSetting.getUserState())); // No equals() method for SparseArray object // assertThat(origPkgSetting.getUserState(), is(testPkgSetting.getUserState())); assertSame(origPkgSetting.verificationInfo, testPkgSetting.verificationInfo); assertThat(origPkgSetting.verificationInfo, is(testPkgSetting.verificationInfo)); assertThat(origPkgSetting.versionCode, is(testPkgSetting.versionCode)); assertSame(origPkgSetting.volumeUuid, testPkgSetting.volumeUuid); assertThat(origPkgSetting.volumeUuid, is(testPkgSetting.volumeUuid)); } private SharedUserSetting createSharedUserSetting(Settings settings, String userName, int sharedUserId, int pkgFlags, int pkgPrivateFlags) { return settings.addSharedUserLPw( userName, sharedUserId, pkgFlags, pkgPrivateFlags); } private PackageSetting createPackageSetting(int sharedUserId, int pkgFlags) { return new PackageSetting( PACKAGE_NAME, REAL_PACKAGE_NAME, INITIAL_CODE_PATH /*codePath*/, INITIAL_CODE_PATH /*resourcePath*/, null /*legacyNativeLibraryPathString*/, "x86_64" /*primaryCpuAbiString*/, "x86" /*secondaryCpuAbiString*/, null /*cpuAbiOverrideString*/, INITIAL_VERSION_CODE, pkgFlags, 0 /*privateFlags*/, null /*parentPackageName*/, null /*childPackageNames*/, sharedUserId, null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); } private @NonNull List createFakeUsers() { ArrayList users = new ArrayList<>(); users.add(new UserInfo(UserHandle.USER_SYSTEM, "test user", UserInfo.FLAG_INITIALIZED)); return users; } private void writeFile(File file, byte[] data) { file.mkdirs(); try { AtomicFile aFile = new AtomicFile(file); FileOutputStream fos = aFile.startWrite(); fos.write(data); aFile.finishWrite(fos); } catch (IOException ioe) { Log.e(TAG, "Cannot write file " + file.getPath()); } } private void writePackagesXml() { writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/packages.xml"), ("" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "").getBytes()); } private void writeStoppedPackagesXml() { writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/packages-stopped.xml"), ( "" + "" + "" + "" + "") .getBytes()); } private void writePackagesList() { writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/packages.list"), ( "com.google.app1 11000 0 /data/data/com.google.app1 seinfo1" + "com.google.app2 11001 0 /data/data/com.google.app2 seinfo2" + "com.android.app3 11030 0 /data/data/com.android.app3 seinfo3") .getBytes()); } private void deleteSystemFolder() { File systemFolder = new File(InstrumentationRegistry.getContext().getFilesDir(), "system"); deleteFolder(systemFolder); } private static void deleteFolder(File folder) { File[] files = folder.listFiles(); if (files != null) { for (File file : files) { deleteFolder(file); } } folder.delete(); } private void writeOldFiles() { deleteSystemFolder(); writePackagesXml(); writeStoppedPackagesXml(); writePackagesList(); } @Before public void createUserManagerServiceRef() throws ReflectiveOperationException { InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { Constructor umsc; try { // unregister the user manager from the local service Method removeServiceForTest = LocalServices.class.getDeclaredMethod( "removeServiceForTest", Class.class); removeServiceForTest.invoke(null, UserManagerInternal.class); // now create a new user manager [which registers again with the local service] umsc = UserManagerService.class.getDeclaredConstructor( Context.class, PackageManagerService.class, Object.class, File.class); umsc.setAccessible(true); UserManagerService ums = umsc.newInstance(InstrumentationRegistry.getContext(), null /*PackageManagerService*/, new Object() /*packagesLock*/, new File(InstrumentationRegistry.getContext().getFilesDir(), "user")); } catch (SecurityException | ReflectiveOperationException | IllegalArgumentException e) { fail("Could not create user manager service; " + e); } } }); } private void verifyKeySetMetaData(Settings settings) throws ReflectiveOperationException, IllegalAccessException { ArrayMap packages = settings.mPackages; KeySetManagerService ksms = settings.mKeySetManagerService; /* verify keyset and public key ref counts */ assertThat(KeySetUtils.getKeySetRefCount(ksms, 1), is(2)); assertThat(KeySetUtils.getKeySetRefCount(ksms, 2), is(1)); assertThat(KeySetUtils.getKeySetRefCount(ksms, 3), is(1)); assertThat(KeySetUtils.getKeySetRefCount(ksms, 4), is(1)); assertThat(KeySetUtils.getPubKeyRefCount(ksms, 1), is(2)); assertThat(KeySetUtils.getPubKeyRefCount(ksms, 2), is(2)); assertThat(KeySetUtils.getPubKeyRefCount(ksms, 3), is(1)); /* verify public keys properly read */ PublicKey keyA = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA); PublicKey keyB = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB); PublicKey keyC = PackageParser.parsePublicKey(KeySetStrings.ctsKeySetPublicKeyC); assertThat(KeySetUtils.getPubKey(ksms, 1), is(keyA)); assertThat(KeySetUtils.getPubKey(ksms, 2), is(keyB)); assertThat(KeySetUtils.getPubKey(ksms, 3), is(keyC)); /* verify mapping is correct (ks -> pub keys) */ LongSparseArray> ksMapping = KeySetUtils.getKeySetMapping(ksms); ArraySet mapping = ksMapping.get(1); assertThat(mapping.size(), is(1)); assertThat(mapping.contains(new Long(1)), is(true)); mapping = ksMapping.get(2); assertThat(mapping.size(), is(1)); assertThat(mapping.contains(new Long(2)), is(true)); mapping = ksMapping.get(3); assertThat(mapping.size(), is(1)); assertThat(mapping.contains(new Long(3)), is(true)); mapping = ksMapping.get(4); assertThat(mapping.size(), is(2)); assertThat(mapping.contains(new Long(1)), is(true)); assertThat(mapping.contains(new Long(2)), is(true)); /* verify lastIssuedIds are consistent */ assertThat(KeySetUtils.getLastIssuedKeyId(ksms), is(3L)); assertThat(KeySetUtils.getLastIssuedKeySetId(ksms), is(4L)); /* verify packages have been given the appropriate information */ PackageSetting ps = packages.get("com.google.app1"); assertThat(ps.keySetData.getProperSigningKeySet(), is(1L)); ps = packages.get("com.google.app2"); assertThat(ps.keySetData.getProperSigningKeySet(), is(1L)); assertThat(ps.keySetData.getAliases().get("AB"), is(4L)); ps = packages.get("com.android.app3"); assertThat(ps.keySetData.getProperSigningKeySet(), is(2L)); assertThat(ps.keySetData.getAliases().get("C"), is(3L)); assertThat(ps.keySetData.getUpgradeKeySets().length, is(1)); assertThat(ps.keySetData.getUpgradeKeySets()[0], is(3L)); } }