blob: 836f8581e8eb4910bd1fd00f1a3468c31709a1bf [file] [log] [blame]
/*
* 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 android.content.pm.SuspendDialogInfo.BUTTON_ACTION_MORE_DETAILS;
import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND;
import static android.content.pm.parsing.FrameworkParsingPackageUtils.parsePublicKey;
import static android.content.res.Resources.ID_NULL;
import static com.android.server.pm.PackageManagerService.WRITE_USER_PACKAGE_RESTRICTIONS;
import static org.hamcrest.CoreMatchers.equalTo;
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.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.app.PropertyInvalidatedCache;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.SuspendDialogInfo;
import android.content.pm.UserInfo;
import android.os.BaseBundle;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.LongSparseArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.permission.persistence.RuntimePermissionsPersistence;
import com.android.server.LocalServices;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.permission.LegacyPermissionDataProvider;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageUserState;
import com.android.server.pm.pkg.PackageUserStateInternal;
import com.android.server.pm.pkg.SuspendParams;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.testutils.TestHandler;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchableTester;
import com.android.server.utils.WatchedArrayMap;
import com.android.server.utils.WatchedArraySet;
import com.android.server.utils.Watcher;
import com.google.common.truth.Truth;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
@Presubmit
@RunWith(AndroidJUnit4.class)
@SmallTest
public class PackageManagerSettingsTests {
private static final String PACKAGE_NAME_1 = "com.android.app1";
private static final String PACKAGE_NAME_2 = "com.android.app2";
private static final String PACKAGE_NAME_3 = "com.android.app3";
private static final int TEST_RESOURCE_ID = 2131231283;
@Mock
RuntimePermissionsPersistence mRuntimePermissionsPersistence;
@Mock
LegacyPermissionDataProvider mPermissionDataProvider;
@Mock
DomainVerificationManagerInternal mDomainVerificationManager;
@Mock
Computer computer;
final ArrayMap<String, Long> mOrigFirstInstallTimes = new ArrayMap<>();
final TestHandler mHandler = new TestHandler((@NonNull Message msg) -> {
return true;
});
@Before
public void initializeMocks() {
MockitoAnnotations.initMocks(this);
when(mDomainVerificationManager.generateNewId())
.thenAnswer(invocation -> UUID.randomUUID());
}
@Before
public void setup() {
// Disable binder caches in this process.
PropertyInvalidatedCache.disableForTestMode();
}
@Before
public void createUserManagerServiceRef() throws ReflectiveOperationException {
InstrumentationRegistry.getInstrumentation().runOnMainSync((Runnable) () -> {
try {
// unregister the user manager from the local service
LocalServices.removeServiceForTest(UserManagerInternal.class);
new UserManagerService(InstrumentationRegistry.getContext());
} catch (Exception e) {
e.printStackTrace();
fail("Could not create user manager service; " + e);
}
});
}
@After
public void tearDown() throws Exception {
deleteFolder(InstrumentationRegistry.getContext().getFilesDir());
}
/** make sure our initialized KeySetManagerService metadata matches packages.xml */
@Test
public void testReadKeySetSettings() throws Exception {
/* write out files and read */
writeOldFiles();
Settings settings = makeSettings();
assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
verifyKeySetMetaData(settings);
}
// Same as above but use the reserve copy.
@Test
public void testReadReserveCopyKeySetSettings() throws Exception {
/* write out files and read */
writeReserveCopyOldFiles();
Settings settings = makeSettings();
assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
verifyKeySetMetaData(settings);
}
// Same as above but packages.xml is malformed.
@Test
public void testReadMalformedPackagesXmlKeySetSettings() throws Exception {
// write out files
writeReserveCopyOldFiles();
// write corrupted packages.xml
writeCorruptedPackagesXml();
Settings settings = makeSettings();
assertThat(settings.readLPw(computer, 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 = makeSettings();
assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
// write out, read back in and verify the same
settings.writeLPr(computer, /*sync=*/true);
assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
verifyKeySetMetaData(settings);
}
// Same as above, but corrupt the primary.xml in process.
@Test
public void testWriteCorruptReadKeySetSettings() throws Exception {
// write out files and read
writeOldFiles();
Settings settings = makeSettings();
assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
// write out
settings.writeLPr(computer, /*sync=*/true);
File filesDir = InstrumentationRegistry.getContext().getFilesDir();
File packageXml = new File(filesDir, "system/packages.xml");
File packagesReserveCopyXml = new File(filesDir, "system/packages.xml.reservecopy");
// Primary.
assertTrue(packageXml.exists());
// Reserve copy.
assertTrue(packagesReserveCopyXml.exists());
// Temporary backup.
assertFalse(new File(filesDir, "packages-backup.xml").exists());
// compare two copies, make sure they are the same
assertTrue(Arrays.equals(Files.readAllBytes(Path.of(packageXml.getAbsolutePath())),
Files.readAllBytes(Path.of(packagesReserveCopyXml.getAbsolutePath()))));
// write corrupted packages.xml
writeCorruptedPackagesXml();
// read back in and verify the same
assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
verifyKeySetMetaData(settings);
}
@Test
public void testSettingsReadOld() {
// Write delegateshellthe package files and make sure they're parsed properly the first time
writeOldFiles();
Settings settings = makeSettings();
assertThat(settings.readLPw(computer, 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 = makeSettings();
assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
settings.writeLPr(computer, /*sync=*/true);
// Create Settings again to make it read from the new files
settings = makeSettings();
assertThat(settings.readLPw(computer, 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));
// Verify that the snapshot passes the same test
Settings snapshot = settings.snapshot();
ps = snapshot.getPackageLPr(PACKAGE_NAME_2);
assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED_USER));
assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_DEFAULT));
}
private static PersistableBundle createPersistableBundle(String packageName, long longVal,
double doubleVal, boolean boolVal, String textVal) {
final PersistableBundle bundle = new PersistableBundle();
bundle.putString(packageName + ".TEXT_VALUE", textVal);
bundle.putLong(packageName + ".LONG_VALUE", longVal);
bundle.putBoolean(packageName + ".BOOL_VALUE", boolVal);
bundle.putDouble(packageName + ".DOUBLE_VALUE", doubleVal);
return bundle;
}
@Test
public void testReadPackageRestrictions_noSuspendingPackage() {
writePackageRestrictions_noSuspendingPackageXml(0);
Settings settingsUnderTest = makeSettings();
final WatchableTester watcher =
new WatchableTester(settingsUnderTest, "noSuspendingPackage");
watcher.register();
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
settingsUnderTest.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
watcher.verifyChangeReported("put package 1");
// Collect a snapshot at the midway point (package 2 has not been added)
final Settings snapshot = settingsUnderTest.snapshot();
watcher.verifyNoChangeReported("snapshot");
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
watcher.verifyChangeReported("put package 2");
settingsUnderTest.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
PackageSetting ps1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1);
PackageUserStateInternal packageUserState1 = ps1.readUserState(0);
assertThat(packageUserState1.isSuspended(), is(true));
assertThat(packageUserState1.getSuspendParams().size(), is(1));
assertThat(packageUserState1.getSuspendParams().keyAt(0), is("android"));
assertThat(packageUserState1.getSuspendParams().valueAt(0).getAppExtras(), is(nullValue()));
assertThat(packageUserState1.getSuspendParams().valueAt(0).getDialogInfo(),
is(nullValue()));
assertThat(packageUserState1.getSuspendParams().valueAt(0).getLauncherExtras(),
is(nullValue()));
// Verify that the snapshot returns the same answers
ps1 = snapshot.mPackages.get(PACKAGE_NAME_1);
packageUserState1 = ps1.readUserState(0);
assertThat(packageUserState1.isSuspended(), is(true));
assertThat(packageUserState1.getSuspendParams().size(), is(1));
assertThat(packageUserState1.getSuspendParams().keyAt(0), is("android"));
assertThat(packageUserState1.getSuspendParams().valueAt(0).getAppExtras(), is(nullValue()));
assertThat(packageUserState1.getSuspendParams().valueAt(0).getDialogInfo(),
is(nullValue()));
assertThat(packageUserState1.getSuspendParams().valueAt(0).getLauncherExtras(),
is(nullValue()));
PackageSetting ps2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2);
PackageUserStateInternal packageUserState2 = ps2.readUserState(0);
assertThat(packageUserState2.isSuspended(), is(false));
assertThat(packageUserState2.getSuspendParams(), is(nullValue()));
// Verify that the snapshot returns different answers
ps2 = snapshot.mPackages.get(PACKAGE_NAME_2);
assertTrue(ps2 == null);
}
@Test
public void testReadPackageRestrictions_noSuspendParamsMap() {
writePackageRestrictions_noSuspendParamsMapXml(0);
final Settings settingsUnderTest = makeSettings();
final WatchableTester watcher =
new WatchableTester(settingsUnderTest, "noSuspendParamsMap");
watcher.register();
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
watcher.verifyChangeReported("put package 1");
settingsUnderTest.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
watcher.verifyChangeReported("readPackageRestrictions");
final PackageSetting ps1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1);
watcher.verifyNoChangeReported("get package 1");
final PackageUserStateInternal packageUserState1 = ps1.readUserState(0);
watcher.verifyNoChangeReported("readUserState");
assertThat(packageUserState1.isSuspended(), is(true));
assertThat(packageUserState1.getSuspendParams().size(), is(1));
assertThat(packageUserState1.getSuspendParams().keyAt(0), is(PACKAGE_NAME_3));
final SuspendParams params = packageUserState1.getSuspendParams().valueAt(0);
watcher.verifyNoChangeReported("fetch user state");
assertThat(params, is(notNullValue()));
assertThat(params.getAppExtras().size(), is(1));
assertThat(params.getAppExtras().getString("app_extra_string"), is("value"));
assertThat(params.getLauncherExtras().size(), is(1));
assertThat(params.getLauncherExtras().getLong("launcher_extra_long"), is(4L));
assertThat(params.getDialogInfo(), is(notNullValue()));
assertThat(params.getDialogInfo().getDialogMessage(), is("Dialog Message"));
assertThat(params.getDialogInfo().getTitleResId(), is(ID_NULL));
assertThat(params.getDialogInfo().getIconResId(), is(TEST_RESOURCE_ID));
assertThat(params.getDialogInfo().getNeutralButtonTextResId(), is(ID_NULL));
assertThat(params.getDialogInfo().getNeutralButtonAction(), is(BUTTON_ACTION_MORE_DETAILS));
assertThat(params.getDialogInfo().getDialogMessageResId(), is(ID_NULL));
}
@Test
public void testReadWritePackageRestrictions_suspendInfo() {
final Settings settingsUnderTest = makeSettings();
final WatchableTester watcher = new WatchableTester(settingsUnderTest, "suspendInfo");
watcher.register();
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
final PackageSetting ps3 = createPackageSetting(PACKAGE_NAME_3);
final PersistableBundle appExtras1 = createPersistableBundle(
PACKAGE_NAME_1, 1L, 0.01, true, "appString1");
final PersistableBundle appExtras2 = createPersistableBundle(
PACKAGE_NAME_2, 2L, 0.02, true, "appString2");
final PersistableBundle launcherExtras1 = createPersistableBundle(
PACKAGE_NAME_1, 10L, 0.1, false, "launcherString1");
final PersistableBundle launcherExtras2 = createPersistableBundle(
PACKAGE_NAME_2, 20L, 0.2, false, "launcherString2");
final SuspendDialogInfo dialogInfo1 = new SuspendDialogInfo.Builder()
.setIcon(0x11220001)
.setTitle("String Title")
.setMessage("1st message")
.setNeutralButtonText(0x11220003)
.setNeutralButtonAction(BUTTON_ACTION_MORE_DETAILS)
.build();
final SuspendDialogInfo dialogInfo2 = new SuspendDialogInfo.Builder()
.setIcon(0x22220001)
.setTitle(0x22220002)
.setMessage("2nd message")
.setNeutralButtonText("String button text")
.setNeutralButtonAction(BUTTON_ACTION_UNSUSPEND)
.build();
ps1.modifyUserState(0).putSuspendParams("suspendingPackage1",
new SuspendParams(dialogInfo1, appExtras1, launcherExtras1));
ps1.modifyUserState(0).putSuspendParams("suspendingPackage2",
new SuspendParams(dialogInfo2, appExtras2, launcherExtras2));
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
watcher.verifyChangeReported("put package 1");
ps2.modifyUserState(0).putSuspendParams("suspendingPackage3",
new SuspendParams(null, appExtras1, null));
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
watcher.verifyChangeReported("put package 2");
ps3.modifyUserState(0).removeSuspension("irrelevant");
settingsUnderTest.mPackages.put(PACKAGE_NAME_3, ps3);
watcher.verifyChangeReported("put package 3");
settingsUnderTest.writePackageRestrictionsLPr(0, /*sync=*/true);
watcher.verifyChangeReported("writePackageRestrictions");
settingsUnderTest.mPackages.clear();
watcher.verifyChangeReported("clear packages");
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
watcher.verifyChangeReported("put package 1");
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
watcher.verifyChangeReported("put package 2");
settingsUnderTest.mPackages.put(PACKAGE_NAME_3, createPackageSetting(PACKAGE_NAME_3));
watcher.verifyChangeReported("put package 3");
// now read and verify
settingsUnderTest.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
watcher.verifyChangeReported("readPackageRestrictions");
final PackageUserStateInternal readPus1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1)
.readUserState(0);
watcher.verifyNoChangeReported("package get 1");
assertThat(readPus1.isSuspended(), is(true));
assertThat(readPus1.getSuspendParams().size(), is(2));
watcher.verifyNoChangeReported("read package param");
assertThat(readPus1.getSuspendParams().keyAt(0), is("suspendingPackage1"));
final SuspendParams params11 = readPus1.getSuspendParams().valueAt(0);
watcher.verifyNoChangeReported("read package param");
assertThat(params11, is(notNullValue()));
assertThat(params11.getDialogInfo(), is(dialogInfo1));
assertThat(BaseBundle.kindofEquals(params11.getAppExtras(), appExtras1), is(true));
assertThat(BaseBundle.kindofEquals(params11.getLauncherExtras(), launcherExtras1),
is(true));
watcher.verifyNoChangeReported("read package param");
assertThat(readPus1.getSuspendParams().keyAt(1), is("suspendingPackage2"));
final SuspendParams params12 = readPus1.getSuspendParams().valueAt(1);
assertThat(params12, is(notNullValue()));
assertThat(params12.getDialogInfo(), is(dialogInfo2));
assertThat(BaseBundle.kindofEquals(params12.getAppExtras(), appExtras2), is(true));
assertThat(BaseBundle.kindofEquals(params12.getLauncherExtras(), launcherExtras2),
is(true));
watcher.verifyNoChangeReported("read package param");
final PackageUserStateInternal readPus2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2)
.readUserState(0);
assertThat(readPus2.isSuspended(), is(true));
assertThat(readPus2.getSuspendParams().size(), is(1));
assertThat(readPus2.getSuspendParams().keyAt(0), is("suspendingPackage3"));
final SuspendParams params21 = readPus2.getSuspendParams().valueAt(0);
assertThat(params21, is(notNullValue()));
assertThat(params21.getDialogInfo(), is(nullValue()));
assertThat(BaseBundle.kindofEquals(params21.getAppExtras(), appExtras1), is(true));
assertThat(params21.getLauncherExtras(), is(nullValue()));
watcher.verifyNoChangeReported("read package param");
final PackageUserStateInternal readPus3 = settingsUnderTest.mPackages.get(PACKAGE_NAME_3)
.readUserState(0);
assertThat(readPus3.isSuspended(), is(false));
assertThat(readPus3.getSuspendParams(), is(nullValue()));
watcher.verifyNoChangeReported("package get 3");
}
@Test
public void testPackageRestrictionsSuspendedDefault() {
final PackageSetting defaultSetting = createPackageSetting(PACKAGE_NAME_1);
assertThat(defaultSetting.getUserStateOrDefault(0).isSuspended(), is(false));
}
private void populateDefaultSettings(Settings settings) {
settings.mPackages.clear();
settings.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
settings.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
settings.mPackages.put(PACKAGE_NAME_3, createPackageSetting(PACKAGE_NAME_3));
}
private void verifyDefaultDistractionFlags(Settings settings) {
final PackageUserState readPus1 = settings.mPackages.get(PACKAGE_NAME_1)
.readUserState(0);
assertThat(readPus1.getDistractionFlags(), is(0));
final PackageUserState readPus2 = settings.mPackages.get(PACKAGE_NAME_2)
.readUserState(0);
assertThat(readPus2.getDistractionFlags(), is(0));
final PackageUserState readPus3 = settings.mPackages.get(PACKAGE_NAME_3)
.readUserState(0);
assertThat(readPus3.getDistractionFlags(), is(0));
}
private void populateDistractionFlags(Settings settings) {
settings.mPackages.clear();
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
final PackageSetting ps3 = createPackageSetting(PACKAGE_NAME_3);
final int distractionFlags1 = PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
ps1.setDistractionFlags(distractionFlags1, 0);
settings.mPackages.put(PACKAGE_NAME_1, ps1);
final int distractionFlags2 = PackageManager.RESTRICTION_HIDE_NOTIFICATIONS
| PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
ps2.setDistractionFlags(distractionFlags2, 0);
settings.mPackages.put(PACKAGE_NAME_2, ps2);
final int distractionFlags3 = PackageManager.RESTRICTION_NONE;
ps3.setDistractionFlags(distractionFlags3, 0);
settings.mPackages.put(PACKAGE_NAME_3, ps3);
}
private void verifyDistractionFlags(Settings settings) {
final int distractionFlags1 = PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
final int distractionFlags2 = PackageManager.RESTRICTION_HIDE_NOTIFICATIONS
| PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
final int distractionFlags3 = PackageManager.RESTRICTION_NONE;
final PackageUserState readPus1 = settings.mPackages.get(PACKAGE_NAME_1)
.readUserState(0);
assertThat(readPus1.getDistractionFlags(), is(distractionFlags1));
final PackageUserState readPus2 = settings.mPackages.get(PACKAGE_NAME_2)
.readUserState(0);
assertThat(readPus2.getDistractionFlags(), is(distractionFlags2));
final PackageUserState readPus3 = settings.mPackages.get(PACKAGE_NAME_3)
.readUserState(0);
assertThat(readPus3.getDistractionFlags(), is(distractionFlags3));
}
@Test
public void testReadWritePackageRestrictions_distractionFlags() {
final Settings settingsUnderTest = makeSettings();
populateDistractionFlags(settingsUnderTest);
settingsUnderTest.writePackageRestrictionsLPr(0, /*sync=*/true);
// now read and verify
populateDefaultSettings(settingsUnderTest);
settingsUnderTest.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsUnderTest);
}
@Test
public void testWriteCorruptReadPackageRestrictions() {
final Settings settingsUnderTest = makeSettings();
populateDistractionFlags(settingsUnderTest);
settingsUnderTest.writePackageRestrictionsLPr(0, /*sync=*/true);
// Corrupt primary file.
writeCorruptedPackageRestrictions(0);
// now read and verify
populateDefaultSettings(settingsUnderTest);
settingsUnderTest.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsUnderTest);
}
@Test
public void testReadWritePackageRestrictionsAsync() {
final Settings settingsWrite = makeSettings();
final Settings settingsRead = makeSettings();
mHandler.clear();
// Initial empty state.
settingsWrite.removeUserLPw(0);
// Schedule 3 async writes.
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
PriorityQueue<TestHandler.MsgInfo> messages = mHandler.getPendingMessages();
assertEquals(3, messages.size());
final Runnable asyncWrite1 = (Runnable) messages.poll().message.obj;
final Runnable asyncWrite2 = (Runnable) messages.poll().message.obj;
final Runnable asyncWrite3 = (Runnable) messages.poll().message.obj;
mHandler.clear();
// First read should read old data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDefaultDistractionFlags(settingsRead);
// 1st write: with flags.
populateDistractionFlags(settingsWrite);
asyncWrite1.run();
// New data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
// 2nd write: without.
populateDefaultSettings(settingsWrite);
asyncWrite2.run();
// Default data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDefaultDistractionFlags(settingsRead);
// 3rd write: with flags.
populateDistractionFlags(settingsWrite);
asyncWrite3.run();
// New data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
}
@Test
public void testReadWritePackageRestrictionsAsyncUserRemoval() {
final Settings settingsWrite = makeSettings();
final Settings settingsRead = makeSettings();
mHandler.clear();
// Initial empty state.
settingsWrite.removeUserLPw(0);
// 2 async writes.
populateDistractionFlags(settingsWrite);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
PriorityQueue<TestHandler.MsgInfo> messages = mHandler.getPendingMessages();
assertEquals(2, messages.size());
final Runnable asyncWrite1 = (Runnable) messages.poll().message.obj;
final Runnable asyncWrite2 = (Runnable) messages.poll().message.obj;
mHandler.clear();
// First read should not read anything.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDefaultDistractionFlags(settingsRead);
// 1st write.
asyncWrite1.run();
// Second read should read new data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
// Now remove the user.
settingsWrite.removeUserLPw(0);
// 2nd write.
asyncWrite2.run();
// Re-read and verify that nothing was read.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDefaultDistractionFlags(settingsRead);
}
@Test
public void testReadWritePackageRestrictionsSyncAfterAsync() {
final Settings settingsWrite = makeSettings();
final Settings settingsRead = makeSettings();
mHandler.clear();
// Initial state, distraction flags populated.
populateDistractionFlags(settingsWrite);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/true);
// 2 async writes of empty distraction flags.
populateDefaultSettings(settingsWrite);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
PriorityQueue<TestHandler.MsgInfo> messages = mHandler.getPendingMessages();
assertEquals(2, messages.size());
final Runnable asyncWrite1 = (Runnable) messages.poll().message.obj;
final Runnable asyncWrite2 = (Runnable) messages.poll().message.obj;
// First read should use read initial data (with flags).
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
// 1st write.
asyncWrite1.run();
// Second read should read updated data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDefaultDistractionFlags(settingsRead);
// Sync write with flags - overrides all async writes.
populateDistractionFlags(settingsWrite);
settingsWrite.writeAllUsersPackageRestrictionsLPr(/*sync=*/true);
// Expect removeMessages call.
assertFalse(mHandler.hasMessages(WRITE_USER_PACKAGE_RESTRICTIONS));
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
// 2nd write.
asyncWrite2.run();
// Re-read and verify.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
}
@Test
public void testWriteReadUsesStaticLibraries() {
final Settings settingsUnderTest = makeSettings();
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
ps1.setAppId(Process.FIRST_APPLICATION_UID);
ps1.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_1).hideAsParsed())
.setUid(ps1.getAppId())
.setSystem(true)
.hideAsFinal());
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
ps2.setAppId(Process.FIRST_APPLICATION_UID + 1);
ps2.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_2).hideAsParsed())
.setUid(ps2.getAppId())
.hideAsFinal());
ps1.setUsesStaticLibraries(new String[] { "com.example.shared.one" });
ps1.setUsesStaticLibrariesVersions(new long[] { 12 });
ps1.setFlags(ps1.getFlags() | ApplicationInfo.FLAG_SYSTEM);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
assertThat(settingsUnderTest.disableSystemPackageLPw(PACKAGE_NAME_1, false), is(true));
ps2.setUsesStaticLibraries(new String[] { "com.example.shared.two" });
ps2.setUsesStaticLibrariesVersions(new long[] { 34 });
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
settingsUnderTest.writeLPr(computer, /*sync=*/true);
settingsUnderTest.mPackages.clear();
settingsUnderTest.mDisabledSysPackages.clear();
assertThat(settingsUnderTest.readLPw(computer, createFakeUsers()), is(true));
PackageSetting readPs1 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_1);
PackageSetting readPs2 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_2);
Truth.assertThat(readPs1).isNotNull();
Truth.assertThat(readPs1.getUsesStaticLibraries()).isNotNull();
Truth.assertThat(readPs1.getUsesStaticLibrariesVersions()).isNotNull();
Truth.assertThat(readPs2).isNotNull();
Truth.assertThat(readPs2.getUsesStaticLibraries()).isNotNull();
Truth.assertThat(readPs2.getUsesStaticLibrariesVersions()).isNotNull();
List<Long> ps1VersionsAsList = new ArrayList<>();
for (long version : ps1.getUsesStaticLibrariesVersions()) {
ps1VersionsAsList.add(version);
}
List<Long> ps2VersionsAsList = new ArrayList<>();
for (long version : ps2.getUsesStaticLibrariesVersions()) {
ps2VersionsAsList.add(version);
}
Truth.assertThat(readPs1.getUsesStaticLibraries()).asList()
.containsExactlyElementsIn(ps1.getUsesStaticLibraries()).inOrder();
Truth.assertThat(readPs1.getUsesStaticLibrariesVersions()).asList()
.containsExactlyElementsIn(ps1VersionsAsList).inOrder();
Truth.assertThat(readPs2.getUsesStaticLibraries()).asList()
.containsExactlyElementsIn(ps2.getUsesStaticLibraries()).inOrder();
Truth.assertThat(readPs2.getUsesStaticLibrariesVersions()).asList()
.containsExactlyElementsIn(ps2VersionsAsList).inOrder();
}
@Test
public void testWriteReadUsesSdkLibraries() {
final Settings settingsUnderTest = makeSettings();
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
ps1.setAppId(Process.FIRST_APPLICATION_UID);
ps1.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_1).hideAsParsed())
.setUid(ps1.getAppId())
.setSystem(true)
.hideAsFinal());
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
ps2.setAppId(Process.FIRST_APPLICATION_UID + 1);
ps2.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_2).hideAsParsed())
.setUid(ps2.getAppId())
.hideAsFinal());
ps1.setUsesSdkLibraries(new String[] { "com.example.sdk.one" });
ps1.setUsesSdkLibrariesVersionsMajor(new long[] { 12 });
ps1.setFlags(ps1.getFlags() | ApplicationInfo.FLAG_SYSTEM);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
assertThat(settingsUnderTest.disableSystemPackageLPw(PACKAGE_NAME_1, false), is(true));
ps2.setUsesSdkLibraries(new String[] { "com.example.sdk.two" });
ps2.setUsesSdkLibrariesVersionsMajor(new long[] { 34 });
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
settingsUnderTest.writeLPr(computer, /*sync=*/true);
settingsUnderTest.mPackages.clear();
settingsUnderTest.mDisabledSysPackages.clear();
assertThat(settingsUnderTest.readLPw(computer, createFakeUsers()), is(true));
PackageSetting readPs1 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_1);
PackageSetting readPs2 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_2);
Truth.assertThat(readPs1).isNotNull();
Truth.assertThat(readPs1.getUsesSdkLibraries()).isNotNull();
Truth.assertThat(readPs1.getUsesSdkLibrariesVersionsMajor()).isNotNull();
Truth.assertThat(readPs2).isNotNull();
Truth.assertThat(readPs2.getUsesSdkLibraries()).isNotNull();
Truth.assertThat(readPs2.getUsesSdkLibrariesVersionsMajor()).isNotNull();
List<Long> ps1VersionsAsList = new ArrayList<>();
for (long version : ps1.getUsesSdkLibrariesVersionsMajor()) {
ps1VersionsAsList.add(version);
}
List<Long> ps2VersionsAsList = new ArrayList<>();
for (long version : ps2.getUsesSdkLibrariesVersionsMajor()) {
ps2VersionsAsList.add(version);
}
Truth.assertThat(readPs1.getUsesSdkLibraries()).asList()
.containsExactlyElementsIn(ps1.getUsesSdkLibraries()).inOrder();
Truth.assertThat(readPs1.getUsesSdkLibrariesVersionsMajor()).asList()
.containsExactlyElementsIn(ps1VersionsAsList).inOrder();
Truth.assertThat(readPs2.getUsesSdkLibraries()).asList()
.containsExactlyElementsIn(ps2.getUsesSdkLibraries()).inOrder();
Truth.assertThat(readPs2.getUsesSdkLibrariesVersionsMajor()).asList()
.containsExactlyElementsIn(ps2VersionsAsList).inOrder();
}
@Test
public void testPackageRestrictionsDistractionFlagsDefault() {
final PackageSetting defaultSetting = createPackageSetting(PACKAGE_NAME_1);
assertThat(defaultSetting.getDistractionFlags(0), is(PackageManager.RESTRICTION_NONE));
}
@Test
public void testEnableDisable() {
// Write the package files and make sure they're parsed properly the first time
writeOldFiles();
Settings settings = makeSettings();
final WatchableTester watcher = new WatchableTester(settings, "testEnableDisable");
watcher.register();
assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
watcher.verifyChangeReported("readLPw");
// Enable/Disable a package
PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_1);
watcher.verifyNoChangeReported("getPackageLPr");
assertThat(ps.getEnabled(0), is(not(COMPONENT_ENABLED_STATE_DISABLED)));
assertThat(ps.getEnabled(1), is(not(COMPONENT_ENABLED_STATE_ENABLED)));
ps.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0, null);
watcher.verifyChangeReported("setEnabled DISABLED");
ps.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 1, null);
watcher.verifyChangeReported("setEnabled ENABLED");
assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED));
assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_ENABLED));
watcher.verifyNoChangeReported("getEnabled");
// Enable/Disable a component
WatchedArraySet<String> components = new WatchedArraySet<String>();
String component1 = PACKAGE_NAME_1 + "/.Component1";
components.add(component1);
ps.setDisabledComponents(components, 0);
WatchedArraySet<String> componentsDisabled = ps.getDisabledComponents(0);
assertThat(componentsDisabled.size(), is(1));
assertThat(componentsDisabled.untrackedStorage().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 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 long INITIAL_VERSION_CODE = 10023L;
private static final long UPDATED_VERSION_CODE = 10025L;
@Test
public void testPackageStateCopy01() {
final PackageSetting origPkgSetting01 = new PackageSetting(
PACKAGE_NAME,
REAL_PACKAGE_NAME,
INITIAL_CODE_PATH /*codePath*/,
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,
0,
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
origPkgSetting01.setPkg(mockAndroidPackage(origPkgSetting01));
final PackageSetting testPkgSetting01 = new PackageSetting(origPkgSetting01);
verifySettingCopy(origPkgSetting01, testPkgSetting01);
}
@Test
public void testPackageStateCopy02() {
final PackageSetting origPkgSetting01 = new PackageSetting(
PACKAGE_NAME /*pkgName*/,
REAL_PACKAGE_NAME /*realPkgName*/,
INITIAL_CODE_PATH /*codePath*/,
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,
0,
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
origPkgSetting01.setUserState(0, 100, 1, true, false, false, false, 0, null, false,
false, "lastDisabledCaller", new ArraySet<>(new String[]{"enabledComponent1"}),
new ArraySet<>(new String[]{"disabledComponent1"}), 0, 0, "harmfulAppWarning",
"splashScreenTheme", 1000L);
final PersistableBundle appExtras1 = createPersistableBundle(
PACKAGE_NAME_1, 1L, 0.01, true, "appString1");
final PersistableBundle launcherExtras1 = createPersistableBundle(
PACKAGE_NAME_1, 10L, 0.1, false, "launcherString1");
final SuspendDialogInfo dialogInfo1 = new SuspendDialogInfo.Builder()
.setIcon(0x11220001)
.setTitle("String Title")
.setMessage("1st message")
.setNeutralButtonText(0x11220003)
.setNeutralButtonAction(BUTTON_ACTION_MORE_DETAILS)
.build();
origPkgSetting01.modifyUserState(0).putSuspendParams("suspendingPackage1",
new SuspendParams(dialogInfo1, appExtras1, launcherExtras1));
origPkgSetting01.setPkg(mockAndroidPackage(origPkgSetting01));
final PackageSetting testPkgSetting01 = new PackageSetting(
PACKAGE_NAME /*pkgName*/,
REAL_PACKAGE_NAME /*realPkgName*/,
UPDATED_CODE_PATH /*codePath*/,
null /*legacyNativeLibraryPathString*/,
null /*primaryCpuAbiString*/,
null /*secondaryCpuAbiString*/,
null /*cpuAbiOverrideString*/,
UPDATED_VERSION_CODE,
0 /*pkgFlags*/,
0 /*pkgPrivateFlags*/,
0,
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
testPkgSetting01.copyPackageSetting(origPkgSetting01, true);
verifySettingCopy(origPkgSetting01, testPkgSetting01);
verifyUserStatesCopy(origPkgSetting01.readUserState(0),
origPkgSetting01.getStateForUser(UserHandle.of(0)));
verifyUserStatesCopy(origPkgSetting01.readUserState(0),
testPkgSetting01.readUserState(0));
}
/** Update package */
@Test
public void testUpdatePackageSetting01() throws PackageManagerException {
final PackageSetting testPkgSetting01 =
createPackageSetting(0 /*sharedUserId*/, 0 /*pkgFlags*/);
testPkgSetting01.setInstalled(false /*installed*/, 0 /*userId*/);
assertThat(testPkgSetting01.getFlags(), is(0));
assertThat(testPkgSetting01.getPrivateFlags(), is(0));
final PackageSetting oldPkgSetting01 = new PackageSetting(testPkgSetting01);
Settings.updatePackageSetting(
testPkgSetting01,
null /*disabledPkg*/,
null /*existingSharedUserSetting*/,
null /*sharedUser*/,
UPDATED_CODE_PATH /*codePath*/,
null /*legacyNativeLibraryPath*/,
"arm64-v8a" /*primaryCpuAbi*/,
"armeabi" /*secondaryCpuAbi*/,
0 /*pkgFlags*/,
0 /*pkgPrivateFlags*/,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("arm64-v8a"));
assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("arm64-v8a"));
assertThat(testPkgSetting01.getSecondaryCpuAbi(), is("armeabi"));
assertThat(testPkgSetting01.getSecondaryCpuAbiLegacy(), is("armeabi"));
assertThat(testPkgSetting01.getFlags(), is(0));
assertThat(testPkgSetting01.getPrivateFlags(), is(0));
final PackageUserState userState = testPkgSetting01.readUserState(0);
verifyUserState(userState, 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.getFlags(), is(0));
assertThat(testPkgSetting01.getPrivateFlags(), is(0));
final PackageSetting oldPkgSetting01 = new PackageSetting(testPkgSetting01);
Settings.updatePackageSetting(
testPkgSetting01,
null /*disabledPkg*/,
null /*existingSharedUserSetting*/,
null /*sharedUser*/,
UPDATED_CODE_PATH /*codePath*/,
null /*legacyNativeLibraryPath*/,
"arm64-v8a" /*primaryCpuAbi*/,
"armeabi" /*secondaryCpuAbi*/,
ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/,
ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("arm64-v8a"));
assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("arm64-v8a"));
assertThat(testPkgSetting01.getSecondaryCpuAbi(), is("armeabi"));
assertThat(testPkgSetting01.getSecondaryCpuAbiLegacy(), is("armeabi"));
assertThat(testPkgSetting01.getFlags(), is(ApplicationInfo.FLAG_SYSTEM));
assertThat(testPkgSetting01.isSystem(), is(true));
assertThat(testPkgSetting01.getPrivateFlags(), is(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED));
assertThat(testPkgSetting01.isPrivileged(), is(true));
final PackageUserState userState = testPkgSetting01.readUserState(0);
verifyUserState(userState, false /*notLaunched*/,
false /*stopped*/, true /*installed*/);
}
/** Update package; changing shared user throws exception */
@Test
public void testUpdatePackageSetting03() {
Settings settings = makeSettings();
final SharedUserSetting testUserSetting01 = createSharedUserSetting(
settings, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
final PackageSetting testPkgSetting01 =
createPackageSetting(0 /*sharedUserId*/, 0 /*pkgFlags*/);
try {
Settings.updatePackageSetting(
testPkgSetting01,
null /*disabledPkg*/,
null /*existingSharedUserSetting*/,
testUserSetting01 /*sharedUser*/,
UPDATED_CODE_PATH /*codePath*/,
null /*legacyNativeLibraryPath*/,
"arm64-v8a" /*primaryCpuAbi*/,
"armeabi" /*secondaryCpuAbi*/,
0 /*pkgFlags*/,
0 /*pkgPrivateFlags*/,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
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.getSignatures();
final PackageSetting testPkgSetting01 = Settings.createNewSetting(
REAL_PACKAGE_NAME,
originalPkgSetting01 /*originalPkg*/,
null /*disabledPkg*/,
null /*realPkgName*/,
null /*sharedUser*/,
UPDATED_CODE_PATH /*codePath*/,
null /*legacyNativeLibraryPath*/,
"arm64-v8a" /*primaryCpuAbi*/,
"armeabi" /*secondaryCpuAbi*/,
UPDATED_VERSION_CODE /*versionCode*/,
ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/,
ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/,
null /*installUser*/,
false /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
false /* stopped */,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
assertThat(testPkgSetting01.getPath(), is(UPDATED_CODE_PATH));
assertThat(testPkgSetting01.getPackageName(), is(PACKAGE_NAME));
assertThat(testPkgSetting01.getFlags(), is(ApplicationInfo.FLAG_SYSTEM));
assertThat(testPkgSetting01.isSystem(), is(true));
assertThat(testPkgSetting01.getPrivateFlags(), is(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED));
assertThat(testPkgSetting01.isPrivileged(), is(true));
assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("arm64-v8a"));
assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("arm64-v8a"));
assertThat(testPkgSetting01.getSecondaryCpuAbi(), is("armeabi"));
assertThat(testPkgSetting01.getSecondaryCpuAbiLegacy(), is("armeabi"));
// signatures object must be different
assertNotSame(testPkgSetting01.getSignatures(), originalSignatures);
assertThat(testPkgSetting01.getVersionCode(), is(UPDATED_VERSION_CODE));
final PackageUserState userState = testPkgSetting01.readUserState(0);
verifyUserState(userState, 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*/,
null /*legacyNativeLibraryPath*/,
"x86_64" /*primaryCpuAbiString*/,
"x86" /*secondaryCpuAbiString*/,
INITIAL_VERSION_CODE /*versionCode*/,
0 /*pkgFlags*/,
0 /*pkgPrivateFlags*/,
UserHandle.SYSTEM /*installUser*/,
true /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
false /* stopped */,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
assertThat(testPkgSetting01.getAppId(), is(0));
assertThat(testPkgSetting01.getPath(), is(INITIAL_CODE_PATH));
assertThat(testPkgSetting01.getPackageName(), is(PACKAGE_NAME));
assertThat(testPkgSetting01.getFlags(), is(0));
assertThat(testPkgSetting01.getPrivateFlags(), is(0));
assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("x86_64"));
assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("x86_64"));
assertThat(testPkgSetting01.getSecondaryCpuAbiLegacy(), is("x86"));
assertThat(testPkgSetting01.getVersionCode(), is(INITIAL_VERSION_CODE));
// by default, the package is considered stopped
final PackageUserState userState = testPkgSetting01.readUserState(0);
verifyUserState(userState, true /*notLaunched*/, true /*stopped*/, true /*installed*/);
}
/** Create PackageSetting for a shared user */
@Test
public void testCreateNewSetting03() {
Settings settings = makeSettings();
final SharedUserSetting testUserSetting01 = createSharedUserSetting(
settings, "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*/,
null /*legacyNativeLibraryPath*/,
"x86_64" /*primaryCpuAbiString*/,
"x86" /*secondaryCpuAbiString*/,
INITIAL_VERSION_CODE /*versionCode*/,
0 /*pkgFlags*/,
0 /*pkgPrivateFlags*/,
null /*installUser*/,
false /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
false /* stopped */,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
assertThat(testPkgSetting01.getAppId(), is(10064));
assertThat(testPkgSetting01.getPath(), is(INITIAL_CODE_PATH));
assertThat(testPkgSetting01.getPackageName(), is(PACKAGE_NAME));
assertThat(testPkgSetting01.getFlags(), is(0));
assertThat(testPkgSetting01.getPrivateFlags(), is(0));
assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("x86_64"));
assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("x86_64"));
assertThat(testPkgSetting01.getSecondaryCpuAbi(), is("x86"));
assertThat(testPkgSetting01.getSecondaryCpuAbiLegacy(), is("x86"));
assertThat(testPkgSetting01.getVersionCode(), is(INITIAL_VERSION_CODE));
final PackageUserState userState = testPkgSetting01.readUserState(0);
verifyUserState(userState, 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.setAppId(10064);
final PackageSignatures disabledSignatures = disabledPkgSetting01.getSignatures();
final PackageSetting testPkgSetting01 = Settings.createNewSetting(
PACKAGE_NAME,
null /*originalPkg*/,
disabledPkgSetting01 /*disabledPkg*/,
null /*realPkgName*/,
null /*sharedUser*/,
UPDATED_CODE_PATH /*codePath*/,
null /*legacyNativeLibraryPath*/,
"arm64-v8a" /*primaryCpuAbi*/,
"armeabi" /*secondaryCpuAbi*/,
UPDATED_VERSION_CODE /*versionCode*/,
0 /*pkgFlags*/,
0 /*pkgPrivateFlags*/,
null /*installUser*/,
false /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
false /* stopped */,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
assertThat(testPkgSetting01.getAppId(), is(10064));
assertThat(testPkgSetting01.getPath(), is(UPDATED_CODE_PATH));
assertThat(testPkgSetting01.getPackageName(), is(PACKAGE_NAME));
assertThat(testPkgSetting01.getFlags(), is(0));
assertThat(testPkgSetting01.getPrivateFlags(), is(0));
assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("arm64-v8a"));
assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("arm64-v8a"));
assertThat(testPkgSetting01.getSecondaryCpuAbi(), is("armeabi"));
assertThat(testPkgSetting01.getSecondaryCpuAbiLegacy(), is("armeabi"));
assertNotSame(testPkgSetting01.getSignatures(), disabledSignatures);
assertThat(testPkgSetting01.getVersionCode(), is(UPDATED_VERSION_CODE));
final PackageUserState userState = testPkgSetting01.readUserState(0);
verifyUserState(userState, false /*notLaunched*/, false /*stopped*/, true /*installed*/);
}
/** Create a new stopped system PackageSetting */
@Test
public void testCreateNewSetting05() {
final PackageSetting testPkgSetting01 = Settings.createNewSetting(
PACKAGE_NAME,
null /*originalPkg*/,
null /*disabledPkg*/,
null /*realPkgName*/,
null /*sharedUser*/,
UPDATED_CODE_PATH /*codePath*/,
null /*legacyNativeLibraryPath*/,
"arm64-v8a" /*primaryCpuAbi*/,
"armeabi" /*secondaryCpuAbi*/,
UPDATED_VERSION_CODE /*versionCode*/,
ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/,
0 /*pkgPrivateFlags*/,
UserHandle.SYSTEM /*installUser*/,
false /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
true /* stopped */,
UserManagerService.getInstance(),
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
assertThat(testPkgSetting01.getAppId(), is(0));
assertThat(testPkgSetting01.getPath(), is(UPDATED_CODE_PATH));
assertThat(testPkgSetting01.getPackageName(), is(PACKAGE_NAME));
assertThat(testPkgSetting01.getFlags(), is(ApplicationInfo.FLAG_SYSTEM));
assertThat(testPkgSetting01.getPrivateFlags(), is(0));
assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("arm64-v8a"));
assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("arm64-v8a"));
assertThat(testPkgSetting01.getSecondaryCpuAbi(), is("armeabi"));
assertThat(testPkgSetting01.getSecondaryCpuAbiLegacy(), is("armeabi"));
assertThat(testPkgSetting01.getVersionCode(), is(UPDATED_VERSION_CODE));
final PackageUserState userState = testPkgSetting01.readUserState(0);
verifyUserState(userState, false /*notLaunched*/, true /*stopped*/, true /*installed*/);
}
@Test
public void testSetPkgStateLibraryFiles_addNewFiles() {
final PackageSetting packageSetting = createPackageSetting("com.foo");
final CountDownLatch countDownLatch = new CountDownLatch(1);
packageSetting.registerObserver(new Watcher() {
@Override
public void onChange(Watchable what) {
countDownLatch.countDown();
}
});
final List<String> newUsesLibraryFiles = new ArrayList<>();
newUsesLibraryFiles.add("code/path/A.apk");
newUsesLibraryFiles.add("code/path/B.apk");
packageSetting.setPkgStateLibraryFiles(newUsesLibraryFiles);
assertThat(countDownLatch.getCount(), is(0L));
}
@Test
public void testSetPkgStateLibraryFiles_removeOneExistingFile() {
final PackageSetting packageSetting = createPackageSetting("com.foo");
final List<String> oldUsesLibraryFiles = new ArrayList<>();
oldUsesLibraryFiles.add("code/path/A.apk");
oldUsesLibraryFiles.add("code/path/B.apk");
oldUsesLibraryFiles.add("code/path/C.apk");
packageSetting.setPkgStateLibraryFiles(oldUsesLibraryFiles);
final CountDownLatch countDownLatch = new CountDownLatch(1);
packageSetting.registerObserver(new Watcher() {
@Override
public void onChange(Watchable what) {
countDownLatch.countDown();
}
});
final List<String> newUsesLibraryFiles = new ArrayList<>();
oldUsesLibraryFiles.add("code/path/A.apk");
oldUsesLibraryFiles.add("code/path/B.apk");
packageSetting.setPkgStateLibraryFiles(newUsesLibraryFiles);
assertThat(countDownLatch.getCount(), is(0L));
}
@Test
public void testSetPkgStateLibraryFiles_changeOneOfFile() {
final PackageSetting packageSetting = createPackageSetting("com.foo");
final List<String> oldUsesLibraryFiles = new ArrayList<>();
oldUsesLibraryFiles.add("code/path/A.apk");
oldUsesLibraryFiles.add("code/path/B.apk");
packageSetting.setPkgStateLibraryFiles(oldUsesLibraryFiles);
final CountDownLatch countDownLatch = new CountDownLatch(1);
packageSetting.registerObserver(new Watcher() {
@Override
public void onChange(Watchable what) {
countDownLatch.countDown();
}
});
final List<String> newUsesLibraryFiles = new ArrayList<>();
newUsesLibraryFiles.add("code/path/A.apk");
newUsesLibraryFiles.add("code/path/B-1.apk");
packageSetting.setPkgStateLibraryFiles(newUsesLibraryFiles);
assertThat(countDownLatch.getCount(), is(0L));
}
@Test
public void testSetPkgStateLibraryFiles_nothingChanged() {
final PackageSetting packageSetting = createPackageSetting("com.foo");
final List<String> oldUsesLibraryFiles = new ArrayList<>();
oldUsesLibraryFiles.add("code/path/A.apk");
oldUsesLibraryFiles.add("code/path/B.apk");
packageSetting.setPkgStateLibraryFiles(oldUsesLibraryFiles);
final CountDownLatch countDownLatch = new CountDownLatch(1);
packageSetting.registerObserver(new Watcher() {
@Override
public void onChange(Watchable what) {
countDownLatch.countDown();
}
});
final List<String> newUsesLibraryFiles = new ArrayList<>();
newUsesLibraryFiles.add("code/path/A.apk");
newUsesLibraryFiles.add("code/path/B.apk");
packageSetting.setPkgStateLibraryFiles(newUsesLibraryFiles);
assertThat(countDownLatch.getCount(), is(1L));
}
@Test
public void testSetPkgStateLibraryFiles_addNewSdks() {
final PackageSetting packageSetting = createPackageSetting("com.foo");
final CountDownLatch countDownLatch = new CountDownLatch(1);
packageSetting.registerObserver(new Watcher() {
@Override
public void onChange(Watchable what) {
countDownLatch.countDown();
}
});
final List<String> files = new ArrayList<>();
files.add("com.sdk1_123");
files.add("com.sdk9_876");
packageSetting.setUsesSdkLibraries(files.toArray(new String[files.size()]));
assertThat(countDownLatch.getCount(), is(0L));
}
@Test
public void testRegisterAndRemoveAppId() throws PackageManagerException {
// Test that the first new app UID should start from FIRST_APPLICATION_UID
final Settings settings = makeSettings();
final PackageSetting ps = createPackageSetting("com.foo");
assertTrue(settings.registerAppIdLPw(ps, false));
assertEquals(10000, ps.getAppId());
// Set up existing app IDs: 10000, 10001, 10003
final PackageSetting ps1 = createPackageSetting("com.foo1");
ps1.setAppId(10001);
final PackageSetting ps2 = createPackageSetting("com.foo2");
ps2.setAppId(10003);
final PackageSetting ps3 = createPackageSetting("com.foo3");
assertEquals(0, ps3.getAppId());
assertTrue(settings.registerAppIdLPw(ps1, false));
assertTrue(settings.registerAppIdLPw(ps2, false));
assertTrue(settings.registerAppIdLPw(ps3, false));
assertEquals(10001, ps1.getAppId());
assertEquals(10003, ps2.getAppId());
// Expecting the new one to start with the next available uid
assertEquals(10002, ps3.getAppId());
// Remove and insert a new one and the new one should not reuse the same uid
settings.removeAppIdLPw(10002);
final PackageSetting ps4 = createPackageSetting("com.foo4");
assertTrue(settings.registerAppIdLPw(ps4, false));
assertEquals(10004, ps4.getAppId());
// Keep adding more
final PackageSetting ps5 = createPackageSetting("com.foo5");
assertTrue(settings.registerAppIdLPw(ps5, false));
assertEquals(10005, ps5.getAppId());
// Remove the last one and the new one should use incremented uid
settings.removeAppIdLPw(10005);
final PackageSetting ps6 = createPackageSetting("com.foo6");
assertTrue(settings.registerAppIdLPw(ps6, false));
assertEquals(10006, ps6.getAppId());
}
/**
* Test replacing a PackageSetting with a SharedUserSetting in mAppIds
*/
@Test
public void testAddPackageSetting() throws PackageManagerException {
final Settings settings = makeSettings();
final SharedUserSetting sus1 = new SharedUserSetting(
"TestUser", 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
sus1.mAppId = 10001;
final PackageSetting ps1 = createPackageSetting("com.foo");
ps1.setAppId(10001);
assertTrue(settings.registerAppIdLPw(ps1, false));
settings.addPackageSettingLPw(ps1, sus1);
assertSame(sus1, settings.getSharedUserSettingLPr(ps1));
}
private void verifyUserState(PackageUserState userState,
boolean notLaunched, boolean stopped, boolean installed) {
assertThat(userState.getEnabledState(), is(0));
assertThat(userState.isHidden(), is(false));
assertThat(userState.isInstalled(), is(installed));
assertThat(userState.isNotLaunched(), is(notLaunched));
assertThat(userState.isStopped(), is(stopped));
assertThat(userState.isSuspended(), is(false));
assertThat(userState.getDistractionFlags(), is(0));
}
private void verifyKeySetData(PackageKeySetData originalData, PackageKeySetData testData) {
assertThat(originalData.getProperSigningKeySet(),
equalTo(testData.getProperSigningKeySet()));
assertThat(originalData.getUpgradeKeySets(), is(testData.getUpgradeKeySets()));
assertThat(originalData.getAliases(), is(testData.getAliases()));
}
private void verifySettingCopy(PackageSetting origPkgSetting, PackageSetting testPkgSetting) {
assertThat(origPkgSetting, is(not(testPkgSetting)));
assertThat(origPkgSetting.getAppId(), is(testPkgSetting.getAppId()));
assertSame(origPkgSetting.getPath(), testPkgSetting.getPath());
assertThat(origPkgSetting.getPath(), is(testPkgSetting.getPath()));
assertSame(origPkgSetting.getPathString(), testPkgSetting.getPathString());
assertThat(origPkgSetting.getPathString(), is(testPkgSetting.getPathString()));
assertSame(origPkgSetting.getCpuAbiOverride(), testPkgSetting.getCpuAbiOverride());
assertThat(origPkgSetting.getCpuAbiOverride(), is(testPkgSetting.getCpuAbiOverride()));
assertThat(origPkgSetting.getDomainSetId(), is(testPkgSetting.getDomainSetId()));
assertSame(origPkgSetting.getInstallSource(), testPkgSetting.getInstallSource());
assertThat(origPkgSetting.isInstallPermissionsFixed(),
is(testPkgSetting.isInstallPermissionsFixed()));
verifyKeySetData(origPkgSetting.getKeySetData(), testPkgSetting.getKeySetData());
assertThat(origPkgSetting.getLastUpdateTime(), is(testPkgSetting.getLastUpdateTime()));
assertSame(origPkgSetting.getLegacyNativeLibraryPath(),
testPkgSetting.getLegacyNativeLibraryPath());
assertThat(origPkgSetting.getLegacyNativeLibraryPath(),
is(testPkgSetting.getLegacyNativeLibraryPath()));
if (origPkgSetting.getMimeGroups() != null
&& origPkgSetting.getMimeGroups() != Collections.<String, Set<String>>emptyMap()) {
assertNotSame(origPkgSetting.getMimeGroups(), testPkgSetting.getMimeGroups());
}
assertThat(origPkgSetting.getMimeGroups(), is(testPkgSetting.getMimeGroups()));
assertNotSame(origPkgSetting.mLegacyPermissionsState,
testPkgSetting.mLegacyPermissionsState);
assertThat(origPkgSetting.mLegacyPermissionsState,
is(testPkgSetting.mLegacyPermissionsState));
assertThat(origPkgSetting.getPackageName(), is(testPkgSetting.getPackageName()));
// mOldCodePaths is _not_ copied
// assertNotSame(origPkgSetting.mOldCodePaths, testPkgSetting.mOldCodePaths);
// assertThat(origPkgSetting.mOldCodePaths, is(not(testPkgSetting.mOldCodePaths)));
assertSame(origPkgSetting.getPkg(), testPkgSetting.getPkg());
assertSame(origPkgSetting.getAndroidPackage(), origPkgSetting.getPkg());
assertThat(origPkgSetting.getAndroidPackage().getPackageName(),
is(origPkgSetting.getPackageName()));
// No equals() method for this object
// assertThat(origPkgSetting.pkg, is(testPkgSetting.pkg));
assertThat(origPkgSetting.getFlags(), is(testPkgSetting.getFlags()));
assertThat(origPkgSetting.getPrivateFlags(), is(testPkgSetting.getPrivateFlags()));
assertSame(origPkgSetting.getPrimaryCpuAbi(), testPkgSetting.getPrimaryCpuAbi());
assertThat(origPkgSetting.getPrimaryCpuAbi(), is(testPkgSetting.getPrimaryCpuAbi()));
assertSame(origPkgSetting.getPrimaryCpuAbiLegacy(), testPkgSetting.getPrimaryCpuAbiLegacy());
assertThat(origPkgSetting.getPrimaryCpuAbiLegacy(), is(testPkgSetting.getPrimaryCpuAbiLegacy()));
assertThat(origPkgSetting.getRealName(), is(testPkgSetting.getRealName()));
assertSame(origPkgSetting.getSecondaryCpuAbi(), testPkgSetting.getSecondaryCpuAbi());
assertThat(origPkgSetting.getSecondaryCpuAbi(), is(testPkgSetting.getSecondaryCpuAbi()));
assertSame(origPkgSetting.getSecondaryCpuAbiLegacy(), testPkgSetting.getSecondaryCpuAbiLegacy());
assertThat(origPkgSetting.getSecondaryCpuAbiLegacy(), is(testPkgSetting.getSecondaryCpuAbiLegacy()));
assertSame(origPkgSetting.getSignatures(), testPkgSetting.getSignatures());
assertThat(origPkgSetting.getSignatures(), is(testPkgSetting.getSignatures()));
assertThat(origPkgSetting.getLastModifiedTime(), is(testPkgSetting.getLastModifiedTime()));
assertNotSame(origPkgSetting.getUserStates(), is(testPkgSetting.getUserStates()));
// No equals() method for SparseArray object
// assertThat(origPkgSetting.getUserState(), is(testPkgSetting.getUserState()));
assertThat(origPkgSetting.getVersionCode(), is(testPkgSetting.getVersionCode()));
assertSame(origPkgSetting.getVolumeUuid(), testPkgSetting.getVolumeUuid());
assertThat(origPkgSetting.getVolumeUuid(), is(testPkgSetting.getVolumeUuid()));
}
private void verifyUserStatesCopy(PackageUserStateInternal origPus,
PackageUserStateInternal testPus) {
assertThat(userStateEquals(origPus, testPus), is(true));
// Verify suspendParams are copied over
assertThat(origPus.getSuspendParams(), is(notNullValue()));
assertThat(testPus.getSuspendParams(), is(notNullValue()));
SuspendParams origSuspendParams = origPus.getSuspendParams().valueAt(0);
SuspendParams testSuspendParams = testPus.getSuspendParams().valueAt(0);
assertThat(origSuspendParams.getDialogInfo().equals(testSuspendParams.getDialogInfo()),
is(true));
assertThat(BaseBundle.kindofEquals(
origSuspendParams.getAppExtras(), testSuspendParams.getAppExtras()), is(true));
assertThat(BaseBundle.kindofEquals(origSuspendParams.getLauncherExtras(),
testSuspendParams.getLauncherExtras()), is(true));
}
private void verifyUserStatesCopy(PackageUserState origPus,
PackageUserState testPus) {
assertThat(userStateEquals(origPus, testPus), is(true));
// Verify that disabledComponents and enabledComponents are copied
assertThat(origPus.getDisabledComponents(), is(notNullValue()));
assertThat(origPus.getDisabledComponents().equals(testPus.getDisabledComponents()),
is(true));
assertThat(origPus.getEnabledComponents(), is(notNullValue()));
assertThat(origPus.getEnabledComponents().equals(testPus.getEnabledComponents()),
is(true));
}
private boolean userStateEquals(PackageUserState userState, PackageUserState oldUserState) {
return userState.isHidden() == oldUserState.isHidden()
&& userState.isStopped() == oldUserState.isStopped()
&& userState.isInstalled() == oldUserState.isInstalled()
&& userState.isSuspended() == oldUserState.isSuspended()
&& userState.isNotLaunched() == oldUserState.isNotLaunched()
&& userState.isInstantApp() == oldUserState.isInstantApp()
&& userState.isVirtualPreload() == oldUserState.isVirtualPreload()
&& (userState.getAllOverlayPaths() != null
? userState.getAllOverlayPaths().equals(oldUserState.getAllOverlayPaths())
: oldUserState.getOverlayPaths() == null)
&& userState.getCeDataInode() == oldUserState.getCeDataInode()
&& userState.getDistractionFlags() == oldUserState.getDistractionFlags()
&& userState.getFirstInstallTimeMillis() == oldUserState.getFirstInstallTimeMillis()
&& userState.getEnabledState() == oldUserState.getEnabledState()
&& userState.getHarmfulAppWarning().equals(oldUserState.getHarmfulAppWarning())
&& userState.getInstallReason() == oldUserState.getInstallReason()
&& userState.getLastDisableAppCaller().equals(
oldUserState.getLastDisableAppCaller())
&& (userState.getSharedLibraryOverlayPaths() != null
? userState.getSharedLibraryOverlayPaths().equals(
oldUserState.getSharedLibraryOverlayPaths())
: oldUserState.getSharedLibraryOverlayPaths() == null)
&& userState.getSplashScreenTheme().equals(
oldUserState.getSplashScreenTheme())
&& userState.getUninstallReason() == oldUserState.getUninstallReason();
}
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*/,
null /*legacyNativeLibraryPathString*/,
"x86_64" /*primaryCpuAbiString*/,
"x86" /*secondaryCpuAbiString*/,
null /*cpuAbiOverrideString*/,
INITIAL_VERSION_CODE,
pkgFlags,
0 /*privateFlags*/,
sharedUserId,
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
}
private PackageSetting createPackageSetting(String packageName) {
return new PackageSetting(
packageName,
packageName,
INITIAL_CODE_PATH /*codePath*/,
null /*legacyNativeLibraryPathString*/,
"x86_64" /*primaryCpuAbiString*/,
"x86" /*secondaryCpuAbiString*/,
null /*cpuAbiOverrideString*/,
INITIAL_VERSION_CODE,
0,
0 /*privateFlags*/,
0,
null /*usesSdkLibraries*/,
null /*usesSdkLibrariesVersions*/,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
}
static @NonNull List<UserInfo> createFakeUsers() {
ArrayList<UserInfo> users = new ArrayList<>();
users.add(new UserInfo(UserHandle.USER_SYSTEM, "test user", UserInfo.FLAG_INITIALIZED));
return users;
}
private static 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) {
throw new RuntimeException("Cannot write file " + file.getPath(), ioe);
}
}
private void writeCorruptedPackagesXml() {
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/packages.xml"),
("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
+ "<packages>"
+ "<last-platform-version internal=\"15\" external=\"0\" />"
+ "<permission-trees>"
+ "<item name=\"com.google.android.permtree\""
).getBytes());
}
static void writePackagesXml(String fileName) {
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), fileName),
("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
+ "<packages>"
+ "<last-platform-version internal=\"15\" external=\"0\" fingerprint=\"foo\" />"
+ "<permission-trees>"
+ "<item name=\"com.google.android.permtree\" package=\"com.google.android.permpackage\" />"
+ "</permission-trees>"
+ "<permissions>"
+ "<item name=\"android.permission.WRITE_CALL_LOG\" package=\"android\" protection=\"1\" />"
+ "<item name=\"android.permission.ASEC_ACCESS\" package=\"android\" protection=\"2\" />"
+ "<item name=\"android.permission.REBOOT\" package=\"android\" protection=\"18\" />"
+ "</permissions>"
+ "<package name=\"com.android.app1\" codePath=\"/system/app/app1.apk\" nativeLibraryPath=\"/data/data/com.android.app1/lib\" flags=\"1\" ft=\"1360e2caa70\" it=\"135f2f80d08\" ut=\"1360e2caa70\" version=\"1109\" sharedUserId=\"11000\">"
+ "<sigs count=\"1\">"
+ "<cert index=\"0\" key=\"" + KeySetStrings.ctsKeySetCertA + "\" />"
+ "</sigs>"
+ "<proper-signing-keyset identifier=\"1\" />"
+ "</package>"
+ "<package name=\"com.android.app2\" codePath=\"/system/app/app2.apk\" nativeLibraryPath=\"/data/data/com.android.app2/lib\" flags=\"1\" ft=\"1360e578718\" it=\"135f2f80d08\" ut=\"1360e578718\" version=\"15\" enabled=\"3\" userId=\"11001\">"
+ "<sigs count=\"1\">"
+ "<cert index=\"0\" />"
+ "</sigs>"
+ "<proper-signing-keyset identifier=\"1\" />"
+ "<defined-keyset alias=\"AB\" identifier=\"4\" />"
+ "</package>"
+ "<package name=\"com.android.app3\" codePath=\"/system/app/app3.apk\" nativeLibraryPath=\"/data/data/com.android.app3/lib\" flags=\"1\" ft=\"1360e577b60\" it=\"135f2f80d08\" ut=\"1360e577b60\" version=\"15\" userId=\"11030\">"
+ "<sigs count=\"1\">"
+ "<cert index=\"1\" key=\"" + KeySetStrings.ctsKeySetCertB + "\" />"
+ "</sigs>"
+ "<proper-signing-keyset identifier=\"2\" />"
+ "<upgrade-keyset identifier=\"3\" />"
+ "<defined-keyset alias=\"C\" identifier=\"3\" />"
+ "</package>"
+ "<shared-user name=\"com.android.shared1\" userId=\"11000\">"
+ "<sigs count=\"1\">"
+ "<cert index=\"1\" />"
+ "</sigs>"
+ "<perms>"
+ "<item name=\"android.permission.REBOOT\" />"
+ "</perms>"
+ "</shared-user>"
+ "<keyset-settings version=\"1\">"
+ "<keys>"
+ "<public-key identifier=\"1\" value=\"" + KeySetStrings.ctsKeySetPublicKeyA + "\" />"
+ "<public-key identifier=\"2\" value=\"" + KeySetStrings.ctsKeySetPublicKeyB + "\" />"
+ "<public-key identifier=\"3\" value=\"" + KeySetStrings.ctsKeySetPublicKeyC + "\" />"
+ "</keys>"
+ "<keysets>"
+ "<keyset identifier=\"1\">"
+ "<key-id identifier=\"1\" />"
+ "</keyset>"
+ "<keyset identifier=\"2\">"
+ "<key-id identifier=\"2\" />"
+ "</keyset>"
+ "<keyset identifier=\"3\">"
+ "<key-id identifier=\"3\" />"
+ "</keyset>"
+ "<keyset identifier=\"4\">"
+ "<key-id identifier=\"1\" />"
+ "<key-id identifier=\"2\" />"
+ "</keyset>"
+ "</keysets>"
+ "<lastIssuedKeyId value=\"3\" />"
+ "<lastIssuedKeySetId value=\"4\" />"
+ "</keyset-settings>"
+ "</packages>").getBytes());
}
private void writePackageRestrictions_noSuspendingPackageXml(final int userId) {
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/users/"
+ userId + "/package-restrictions.xml"),
("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ "<package-restrictions>\n"
+ " <pkg name=\"" + PACKAGE_NAME_1 + "\" suspended=\"true\" />"
+ " <pkg name=\"" + PACKAGE_NAME_2 + "\" suspended=\"false\" />"
+ " <preferred-activities />\n"
+ " <persistent-preferred-activities />\n"
+ " <crossProfile-intent-filters />\n"
+ " <default-apps />\n"
+ "</package-restrictions>\n")
.getBytes());
}
private void writePackageRestrictions_noSuspendParamsMapXml(final int userId) {
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/users/"
+ userId + "/package-restrictions.xml"),
("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ "<package-restrictions>\n"
+ " <pkg name=\"" + PACKAGE_NAME_1 + "\" "
+ " suspended=\"true\" suspending-package=\"" + PACKAGE_NAME_3 + "\">\n"
+ " <suspended-dialog-info dialogMessage=\"Dialog Message\""
+ " iconResId=\"" + TEST_RESOURCE_ID + "\"/>\n"
+ " <suspended-app-extras>\n"
+ " <string name=\"app_extra_string\">value</string>\n"
+ " </suspended-app-extras>\n"
+ " <suspended-launcher-extras>\n"
+ " <long name=\"launcher_extra_long\" value=\"4\" />\n"
+ " </suspended-launcher-extras>\n"
+ " </pkg>\n"
+ " <preferred-activities />\n"
+ " <persistent-preferred-activities />\n"
+ " <crossProfile-intent-filters />\n"
+ " <default-apps />\n"
+ "</package-restrictions>\n")
.getBytes());
}
private void writeCorruptedPackageRestrictions(final int userId) {
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/users/"
+ userId + "/package-restrictions.xml"),
("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ "<package-restrictions>\n"
+ " <pkg name=\"" + PACKAGE_NAME_1 + "\" ").getBytes());
}
private static void writeStoppedPackagesXml() {
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/packages-stopped.xml"),
( "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
+ "<stopped-packages>"
+ "<pkg name=\"com.android.app1\" nl=\"1\" />"
+ "<pkg name=\"com.android.app3\" nl=\"1\" />"
+ "</stopped-packages>")
.getBytes());
}
private static void writePackagesList() {
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/packages.list"),
( "com.android.app1 11000 0 /data/data/com.android.app1 seinfo1"
+ "com.android.app2 11001 0 /data/data/com.android.app2 seinfo2"
+ "com.android.app3 11030 0 /data/data/com.android.app3 seinfo3")
.getBytes());
}
private static 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();
}
static void writeOldFiles() {
deleteSystemFolder();
writePackagesXml("system/packages.xml");
writeStoppedPackagesXml();
writePackagesList();
}
private void writeReserveCopyOldFiles() {
deleteSystemFolder();
writePackagesXml("system/packages.xml.reservecopy");
writeStoppedPackagesXml();
writePackagesList();
}
private Settings makeSettings() {
return new Settings(InstrumentationRegistry.getContext().getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider,
mDomainVerificationManager, mHandler,
new PackageManagerTracedLock());
}
static void verifyKeySetMetaData(Settings settings)
throws ReflectiveOperationException, IllegalAccessException {
WatchedArrayMap<String, PackageSetting> packages = settings.mPackages;
KeySetManagerService ksms = settings.getKeySetManagerService();
/* 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 = parsePublicKey(KeySetStrings.ctsKeySetPublicKeyA);
PublicKey keyB = parsePublicKey(KeySetStrings.ctsKeySetPublicKeyB);
PublicKey keyC = 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<ArraySet<Long>> ksMapping = KeySetUtils.getKeySetMapping(ksms);
ArraySet<Long> 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.android.app1");
assertThat(ps.getKeySetData().getProperSigningKeySet(), is(1L));
ps = packages.get("com.android.app2");
assertThat(ps.getKeySetData().getProperSigningKeySet(), is(1L));
assertThat(ps.getKeySetData().getAliases().get("AB"), is(4L));
ps = packages.get("com.android.app3");
assertThat(ps.getKeySetData().getProperSigningKeySet(), is(2L));
assertThat(ps.getKeySetData().getAliases().get("C"), is(3L));
assertThat(ps.getKeySetData().getUpgradeKeySets().length, is(1));
assertThat(ps.getKeySetData().getUpgradeKeySets()[0], is(3L));
}
@NonNull
private AndroidPackage mockAndroidPackage(PackageSetting pkgSetting) {
return PackageImpl.forTesting(pkgSetting.getPackageName()).hideAsParsed().hideAsFinal();
}
}