Loading services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -1452,6 +1452,13 @@ public class PackageManagerServiceUtils { } } if (!ArrayUtils.isEmpty(after.splitNames)) { if (!ArrayUtils.isEmpty(after.splitNames)) { if (beforeSplitNames.length != beforeSplitRevisionCodes.length) { throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE, "Current split names and the split revision codes are not 1:1 mapping." + "This indicates that the package info data has been" + " corrupted."); } for (int i = 0; i < after.splitNames.length; i++) { for (int i = 0; i < after.splitNames.length; i++) { final String splitName = after.splitNames[i]; final String splitName = after.splitNames[i]; final int j = ArrayUtils.indexOf(beforeSplitNames, splitName); final int j = ArrayUtils.indexOf(beforeSplitNames, splitName); Loading services/core/java/com/android/server/pm/Settings.java +16 −2 Original line number Original line Diff line number Diff line Loading @@ -4489,10 +4489,24 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile String splitName = parser.getAttributeValue(null, ATTR_NAME); String splitName = parser.getAttributeValue(null, ATTR_NAME); int splitRevision = parser.getAttributeInt(null, ATTR_VERSION, -1); int splitRevision = parser.getAttributeInt(null, ATTR_VERSION, -1); if (splitName != null && splitRevision >= 0) { if (splitName != null && splitRevision >= 0) { final int beforeSplitNamesLength = outPs.getSplitNames().length; // If the split name already exists in the outPs#getSplitNames, don't add it // into the array and update its revision code below outPs.setSplitNames(ArrayUtils.appendElement(String.class, outPs.setSplitNames(ArrayUtils.appendElement(String.class, outPs.getSplitNames(), splitName)); outPs.getSplitNames(), splitName)); // If the same split name has already been added before, update the latest // revision code final int afterSplitNamesLength = outPs.getSplitNames().length; if (beforeSplitNamesLength == afterSplitNamesLength) { final int index = ArrayUtils.indexOf(outPs.getSplitNames(), splitName); final int[] splitRevisionCodes = outPs.getSplitRevisionCodes(); splitRevisionCodes[index] = splitRevision; outPs.setSplitRevisionCodes(splitRevisionCodes); } else { outPs.setSplitRevisionCodes(ArrayUtils.appendInt( outPs.setSplitRevisionCodes(ArrayUtils.appendInt( outPs.getSplitRevisionCodes(), splitRevision)); outPs.getSplitRevisionCodes(), splitRevision, /* allowDuplicates= */ true)); } } } XmlUtils.skipCurrentTag(parser); XmlUtils.skipCurrentTag(parser); Loading services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceUtilsTest.java 0 → 100644 +341 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2024 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 org.testng.Assert.assertThrows; import android.content.pm.PackageInfoLite; import android.platform.test.annotations.Presubmit; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.pm.parsing.pkg.PackageImpl; import com.android.server.pm.pkg.AndroidPackage; import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; import java.util.UUID; @Presubmit @RunWith(AndroidJUnit4.class) @SmallTest public class PackageManagerServiceUtilsTest { private static final String PACKAGE_NAME = "com.android.app"; private static final File CODE_PATH = InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(); @Test public void testCheckDowngrade_packageSetting_versionCodeSmaller_throwException() throws Exception { final PackageSetting before = createPackageSetting(); before.setLongVersionCode(2); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_packageSetting_baseRevisionCodeSmaller_throwException() throws Exception { final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setBaseRevisionCode(2); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.baseRevisionCode = 1; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_packageSetting_splitArraySizeIsDifferent_throwException() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne }; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setSplitNames(splitNames); before.setSplitRevisionCodes(beforeSplitRevisionCodes); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_packageSetting_splitRevisionCodeSmaller_throwException() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionTwo, revisionThree}; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setSplitNames(splitNames); before.setSplitRevisionCodes(beforeSplitRevisionCodes); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_packageSetting_sameSplitNameRevisionsBigger() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionThree }; final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setSplitNames(splitNames); before.setSplitRevisionCodes(beforeSplitRevisionCodes); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } @Test public void testCheckDowngrade_packageSetting_hasDifferentSplitNames() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] beforeSplitNames = new String[] { splitOne, splitTwo }; final String[] afterSplitNames = new String[] { splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; final int[] afterSplitRevisionCodes = new int[] { revisionThree }; final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setSplitNames(beforeSplitNames); before.setSplitRevisionCodes(beforeSplitRevisionCodes); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = afterSplitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } @Test public void testCheckDowngrade_packageSetting_newSplitName() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final String[] beforeSplitNames = new String[] { splitOne }; final String[] afterSplitNames = new String[] { splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionTwo }; final int[] afterSplitRevisionCodes = new int[] { revisionOne }; final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setSplitNames(beforeSplitNames); before.setSplitRevisionCodes(beforeSplitRevisionCodes); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = afterSplitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } @Test public void testCheckDowngrade_androidPackage_versionCodeSmaller_throwException() throws Exception { final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME).hideAsParsed() .setVersionCode(2).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_androidPackage_baseRevisionCodeSmaller_throwException() throws Exception { final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME).setBaseRevisionCode(2) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.baseRevisionCode = 1; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_androidPackage_splitArraySizeIsDifferent_throwException() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne }; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) .asSplit(splitNames, /* splitCodePaths= */ null, beforeSplitRevisionCodes, /* splitDependencies= */ null) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_androidPackage_splitRevisionCodeSmaller_throwException() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionTwo, revisionThree}; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) .asSplit(splitNames, /* splitCodePaths= */ null, beforeSplitRevisionCodes, /* splitDependencies= */ null) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_androidPackage_sameSplitNameRevisionsBigger() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionThree }; final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) .asSplit(splitNames, /* splitCodePaths= */ null, beforeSplitRevisionCodes, /* splitDependencies= */ null) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } @Test public void testCheckDowngrade_androidPackage_hasDifferentSplitNames() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] beforeSplitNames = new String[] { splitOne, splitTwo }; final String[] afterSplitNames = new String[] { splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; final int[] afterSplitRevisionCodes = new int[] { revisionThree }; final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) .asSplit(beforeSplitNames, /* splitCodePaths= */ null, beforeSplitRevisionCodes, /* splitDependencies= */ null) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = afterSplitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } @Test public void testCheckDowngrade_androidPackage_newSplitName() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final String[] beforeSplitNames = new String[] { splitOne }; final String[] afterSplitNames = new String[] { splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionTwo }; final int[] afterSplitRevisionCodes = new int[] { revisionOne }; final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) .asSplit(beforeSplitNames, /* splitCodePaths= */ null, beforeSplitRevisionCodes, /* splitDependencies= */ null) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = afterSplitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } private PackageSetting createPackageSetting() { return new PackageSetting(PACKAGE_NAME, PACKAGE_NAME, CODE_PATH, /* pkgFlags= */ 0, /* privateFlags= */ 0 , UUID.randomUUID()); } } services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java +49 −1 Original line number Original line Diff line number Diff line Loading @@ -1092,7 +1092,7 @@ public class PackageManagerSettingsTests { } } @Test @Test public void testNoPkg_writeReadSplitVersions() { public void testNoPkgDifferentRevisions_writeReadSplitVersions() { Settings settings = makeSettings(); Settings settings = makeSettings(); PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); packageSetting.setAppId(Process.FIRST_APPLICATION_UID); packageSetting.setAppId(Process.FIRST_APPLICATION_UID); Loading @@ -1116,6 +1116,54 @@ public class PackageManagerSettingsTests { assertThat(resultSetting.getSplitRevisionCodes()[1], is(revisionTwo)); assertThat(resultSetting.getSplitRevisionCodes()[1], is(revisionTwo)); } } @Test public void testNoPkgSameRevisions_writeReadSplitVersions() { Settings settings = makeSettings(); PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); packageSetting.setAppId(Process.FIRST_APPLICATION_UID); final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; packageSetting.setSplitNames(new String[] { splitOne, splitTwo}); packageSetting.setSplitRevisionCodes(new int[] { revisionOne, revisionOne}); settings.mPackages.put(PACKAGE_NAME_1, packageSetting); settings.writeLPr(computer, /* sync= */ true); settings.mPackages.clear(); assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); PackageSetting resultSetting = settings.getPackageLPr(PACKAGE_NAME_1); assertThat(resultSetting.getSplitNames()[0], is(splitOne)); assertThat(resultSetting.getSplitNames()[1], is(splitTwo)); assertThat(resultSetting.getSplitRevisionCodes()[0], is(revisionOne)); assertThat(resultSetting.getSplitRevisionCodes()[1], is(revisionOne)); } @Test public void testNoPkgSameSplitNames_writeReadSplitVersions() { Settings settings = makeSettings(); PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); packageSetting.setAppId(Process.FIRST_APPLICATION_UID); final String splitOne = "one"; final int revisionOne = 311; final int revisionTwo = 330; packageSetting.setSplitNames(new String[] { splitOne, splitOne}); packageSetting.setSplitRevisionCodes(new int[] { revisionOne, revisionTwo}); settings.mPackages.put(PACKAGE_NAME_1, packageSetting); settings.writeLPr(computer, /* sync= */ true); settings.mPackages.clear(); assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); PackageSetting resultSetting = settings.getPackageLPr(PACKAGE_NAME_1); assertThat(resultSetting.getSplitNames().length, is(1)); assertThat(resultSetting.getSplitRevisionCodes().length, is(1)); assertThat(resultSetting.getSplitNames()[0], is(splitOne)); assertThat(resultSetting.getSplitRevisionCodes()[0], is(revisionTwo)); } @Test @Test public void testWriteReadArchiveState() { public void testWriteReadArchiveState() { Settings settings = makeSettings(); Settings settings = makeSettings(); Loading Loading
services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -1452,6 +1452,13 @@ public class PackageManagerServiceUtils { } } if (!ArrayUtils.isEmpty(after.splitNames)) { if (!ArrayUtils.isEmpty(after.splitNames)) { if (beforeSplitNames.length != beforeSplitRevisionCodes.length) { throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE, "Current split names and the split revision codes are not 1:1 mapping." + "This indicates that the package info data has been" + " corrupted."); } for (int i = 0; i < after.splitNames.length; i++) { for (int i = 0; i < after.splitNames.length; i++) { final String splitName = after.splitNames[i]; final String splitName = after.splitNames[i]; final int j = ArrayUtils.indexOf(beforeSplitNames, splitName); final int j = ArrayUtils.indexOf(beforeSplitNames, splitName); Loading
services/core/java/com/android/server/pm/Settings.java +16 −2 Original line number Original line Diff line number Diff line Loading @@ -4489,10 +4489,24 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile String splitName = parser.getAttributeValue(null, ATTR_NAME); String splitName = parser.getAttributeValue(null, ATTR_NAME); int splitRevision = parser.getAttributeInt(null, ATTR_VERSION, -1); int splitRevision = parser.getAttributeInt(null, ATTR_VERSION, -1); if (splitName != null && splitRevision >= 0) { if (splitName != null && splitRevision >= 0) { final int beforeSplitNamesLength = outPs.getSplitNames().length; // If the split name already exists in the outPs#getSplitNames, don't add it // into the array and update its revision code below outPs.setSplitNames(ArrayUtils.appendElement(String.class, outPs.setSplitNames(ArrayUtils.appendElement(String.class, outPs.getSplitNames(), splitName)); outPs.getSplitNames(), splitName)); // If the same split name has already been added before, update the latest // revision code final int afterSplitNamesLength = outPs.getSplitNames().length; if (beforeSplitNamesLength == afterSplitNamesLength) { final int index = ArrayUtils.indexOf(outPs.getSplitNames(), splitName); final int[] splitRevisionCodes = outPs.getSplitRevisionCodes(); splitRevisionCodes[index] = splitRevision; outPs.setSplitRevisionCodes(splitRevisionCodes); } else { outPs.setSplitRevisionCodes(ArrayUtils.appendInt( outPs.setSplitRevisionCodes(ArrayUtils.appendInt( outPs.getSplitRevisionCodes(), splitRevision)); outPs.getSplitRevisionCodes(), splitRevision, /* allowDuplicates= */ true)); } } } XmlUtils.skipCurrentTag(parser); XmlUtils.skipCurrentTag(parser); Loading
services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerServiceUtilsTest.java 0 → 100644 +341 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2024 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 org.testng.Assert.assertThrows; import android.content.pm.PackageInfoLite; import android.platform.test.annotations.Presubmit; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.internal.pm.parsing.pkg.PackageImpl; import com.android.server.pm.pkg.AndroidPackage; import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; import java.util.UUID; @Presubmit @RunWith(AndroidJUnit4.class) @SmallTest public class PackageManagerServiceUtilsTest { private static final String PACKAGE_NAME = "com.android.app"; private static final File CODE_PATH = InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(); @Test public void testCheckDowngrade_packageSetting_versionCodeSmaller_throwException() throws Exception { final PackageSetting before = createPackageSetting(); before.setLongVersionCode(2); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_packageSetting_baseRevisionCodeSmaller_throwException() throws Exception { final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setBaseRevisionCode(2); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.baseRevisionCode = 1; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_packageSetting_splitArraySizeIsDifferent_throwException() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne }; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setSplitNames(splitNames); before.setSplitRevisionCodes(beforeSplitRevisionCodes); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_packageSetting_splitRevisionCodeSmaller_throwException() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionTwo, revisionThree}; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setSplitNames(splitNames); before.setSplitRevisionCodes(beforeSplitRevisionCodes); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_packageSetting_sameSplitNameRevisionsBigger() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionThree }; final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setSplitNames(splitNames); before.setSplitRevisionCodes(beforeSplitRevisionCodes); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } @Test public void testCheckDowngrade_packageSetting_hasDifferentSplitNames() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] beforeSplitNames = new String[] { splitOne, splitTwo }; final String[] afterSplitNames = new String[] { splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; final int[] afterSplitRevisionCodes = new int[] { revisionThree }; final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setSplitNames(beforeSplitNames); before.setSplitRevisionCodes(beforeSplitRevisionCodes); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = afterSplitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } @Test public void testCheckDowngrade_packageSetting_newSplitName() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final String[] beforeSplitNames = new String[] { splitOne }; final String[] afterSplitNames = new String[] { splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionTwo }; final int[] afterSplitRevisionCodes = new int[] { revisionOne }; final PackageSetting before = createPackageSetting(); before.setLongVersionCode(1); before.setSplitNames(beforeSplitNames); before.setSplitRevisionCodes(beforeSplitRevisionCodes); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = afterSplitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } @Test public void testCheckDowngrade_androidPackage_versionCodeSmaller_throwException() throws Exception { final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME).hideAsParsed() .setVersionCode(2).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_androidPackage_baseRevisionCodeSmaller_throwException() throws Exception { final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME).setBaseRevisionCode(2) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.baseRevisionCode = 1; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_androidPackage_splitArraySizeIsDifferent_throwException() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne }; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) .asSplit(splitNames, /* splitCodePaths= */ null, beforeSplitRevisionCodes, /* splitDependencies= */ null) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_androidPackage_splitRevisionCodeSmaller_throwException() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionTwo, revisionThree}; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionTwo }; final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) .asSplit(splitNames, /* splitCodePaths= */ null, beforeSplitRevisionCodes, /* splitDependencies= */ null) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; assertThrows(PackageManagerException.class, () -> PackageManagerServiceUtils.checkDowngrade(before, after)); } @Test public void testCheckDowngrade_androidPackage_sameSplitNameRevisionsBigger() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] splitNames = new String[] { splitOne, splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; final int[] afterSplitRevisionCodes = new int[] { revisionOne, revisionThree }; final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) .asSplit(splitNames, /* splitCodePaths= */ null, beforeSplitRevisionCodes, /* splitDependencies= */ null) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = splitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } @Test public void testCheckDowngrade_androidPackage_hasDifferentSplitNames() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final int revisionThree = 360; final String[] beforeSplitNames = new String[] { splitOne, splitTwo }; final String[] afterSplitNames = new String[] { splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionOne, revisionTwo}; final int[] afterSplitRevisionCodes = new int[] { revisionThree }; final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) .asSplit(beforeSplitNames, /* splitCodePaths= */ null, beforeSplitRevisionCodes, /* splitDependencies= */ null) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = afterSplitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } @Test public void testCheckDowngrade_androidPackage_newSplitName() throws Exception { final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; final int revisionTwo = 330; final String[] beforeSplitNames = new String[] { splitOne }; final String[] afterSplitNames = new String[] { splitTwo }; final int[] beforeSplitRevisionCodes = new int[] { revisionTwo }; final int[] afterSplitRevisionCodes = new int[] { revisionOne }; final AndroidPackage before = PackageImpl.forTesting(PACKAGE_NAME) .asSplit(beforeSplitNames, /* splitCodePaths= */ null, beforeSplitRevisionCodes, /* splitDependencies= */ null) .hideAsParsed().setVersionCode(1).hideAsFinal(); final PackageInfoLite after = new PackageInfoLite(); after.versionCode = 1; after.splitNames = afterSplitNames; after.splitRevisionCodes = afterSplitRevisionCodes; PackageManagerServiceUtils.checkDowngrade(before, after); } private PackageSetting createPackageSetting() { return new PackageSetting(PACKAGE_NAME, PACKAGE_NAME, CODE_PATH, /* pkgFlags= */ 0, /* privateFlags= */ 0 , UUID.randomUUID()); } }
services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java +49 −1 Original line number Original line Diff line number Diff line Loading @@ -1092,7 +1092,7 @@ public class PackageManagerSettingsTests { } } @Test @Test public void testNoPkg_writeReadSplitVersions() { public void testNoPkgDifferentRevisions_writeReadSplitVersions() { Settings settings = makeSettings(); Settings settings = makeSettings(); PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); packageSetting.setAppId(Process.FIRST_APPLICATION_UID); packageSetting.setAppId(Process.FIRST_APPLICATION_UID); Loading @@ -1116,6 +1116,54 @@ public class PackageManagerSettingsTests { assertThat(resultSetting.getSplitRevisionCodes()[1], is(revisionTwo)); assertThat(resultSetting.getSplitRevisionCodes()[1], is(revisionTwo)); } } @Test public void testNoPkgSameRevisions_writeReadSplitVersions() { Settings settings = makeSettings(); PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); packageSetting.setAppId(Process.FIRST_APPLICATION_UID); final String splitOne = "one"; final String splitTwo = "two"; final int revisionOne = 311; packageSetting.setSplitNames(new String[] { splitOne, splitTwo}); packageSetting.setSplitRevisionCodes(new int[] { revisionOne, revisionOne}); settings.mPackages.put(PACKAGE_NAME_1, packageSetting); settings.writeLPr(computer, /* sync= */ true); settings.mPackages.clear(); assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); PackageSetting resultSetting = settings.getPackageLPr(PACKAGE_NAME_1); assertThat(resultSetting.getSplitNames()[0], is(splitOne)); assertThat(resultSetting.getSplitNames()[1], is(splitTwo)); assertThat(resultSetting.getSplitRevisionCodes()[0], is(revisionOne)); assertThat(resultSetting.getSplitRevisionCodes()[1], is(revisionOne)); } @Test public void testNoPkgSameSplitNames_writeReadSplitVersions() { Settings settings = makeSettings(); PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1); packageSetting.setAppId(Process.FIRST_APPLICATION_UID); final String splitOne = "one"; final int revisionOne = 311; final int revisionTwo = 330; packageSetting.setSplitNames(new String[] { splitOne, splitOne}); packageSetting.setSplitRevisionCodes(new int[] { revisionOne, revisionTwo}); settings.mPackages.put(PACKAGE_NAME_1, packageSetting); settings.writeLPr(computer, /* sync= */ true); settings.mPackages.clear(); assertThat(settings.readLPw(computer, createFakeUsers()), is(true)); PackageSetting resultSetting = settings.getPackageLPr(PACKAGE_NAME_1); assertThat(resultSetting.getSplitNames().length, is(1)); assertThat(resultSetting.getSplitRevisionCodes().length, is(1)); assertThat(resultSetting.getSplitNames()[0], is(splitOne)); assertThat(resultSetting.getSplitRevisionCodes()[0], is(revisionTwo)); } @Test @Test public void testWriteReadArchiveState() { public void testWriteReadArchiveState() { Settings settings = makeSettings(); Settings settings = makeSettings(); Loading