Treat APEX installs as upgrades

It's not allowed to install a completely new APEX, hence APEX
installations should be treated as upgrades.

This change allows holders of INSTALL_PACKAGE_UPDATES permission to
silently install APEX upgrades.

Bug: 193085724
Bug: 190802380
Test: atest StagedInstallInternalTest
Change-Id: Idde7644122eeae6c444e3520f66ab1546ba7fdf6
This commit is contained in:
Nikita Ioffe
2021-07-09 18:25:57 +01:00
parent 1d2cbb6f50
commit 24e3ed6e78
4 changed files with 49 additions and 5 deletions

View File

@@ -33,6 +33,8 @@ android_test_helper_app {
java_resources: [
":com.android.apex.apkrollback.test_v2",
":StagedInstallTestApexV2_WrongSha",
":test.rebootless_apex_v1",
":test.rebootless_apex_v2",
],
}
@@ -54,6 +56,7 @@ java_test_host {
":com.android.apex.cts.shim.v2_prebuilt",
":StagedInstallTestApexV2_WrongSha",
":TestAppAv1",
":test.rebootless_apex_v1",
],
test_suites: ["general-tests"],
test_config: "StagedInstallInternalTest.xml",

View File

@@ -23,7 +23,10 @@ import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import android.Manifest;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -192,6 +195,37 @@ public class StagedInstallInternalTest {
assertSessionFailedWithMessage(sessionId, "has unexpected SHA512 hash");
}
@Test
public void testRebootlessUpdates() throws Exception {
InstallUtils.dropShellPermissionIdentity();
InstallUtils.adoptShellPermissionIdentity(Manifest.permission.INSTALL_PACKAGE_UPDATES);
final PackageManager pm =
InstrumentationRegistry.getInstrumentation().getContext().getPackageManager();
{
PackageInfo apex = pm.getPackageInfo("test.apex.rebootless", PackageManager.MATCH_APEX);
assertThat(apex.getLongVersionCode()).isEqualTo(1);
assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
.isEqualTo(ApplicationInfo.FLAG_SYSTEM);
assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED)
.isEqualTo(ApplicationInfo.FLAG_INSTALLED);
assertThat(apex.applicationInfo.sourceDir).startsWith("/system/apex");
}
TestApp apex2 = new TestApp("TestRebootlessApexV1", "test.apex.rebootless", 2,
/* isApex= */ true, "test.rebootless_apex_v2.apex");
Install.single(apex2).commit();
{
PackageInfo apex = pm.getPackageInfo("test.apex.rebootless", PackageManager.MATCH_APEX);
assertThat(apex.getLongVersionCode()).isEqualTo(2);
assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM).isEqualTo(0);
assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED)
.isEqualTo(ApplicationInfo.FLAG_INSTALLED);
assertThat(apex.applicationInfo.sourceDir).startsWith("/data/apex/active");
}
}
private static void assertSessionFailedWithMessage(int sessionId, String msg) {
assertSessionState(sessionId, (session) -> {
assertThat(session.isStagedSessionFailed()).isTrue();

View File

@@ -85,7 +85,9 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
}
deleteFiles("/system/apex/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex",
"/data/apex/active/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex",
"/data/apex/active/" + SHIM_APEX_PACKAGE_NAME + "*.apex");
"/data/apex/active/" + SHIM_APEX_PACKAGE_NAME + "*.apex",
"/system/apex/test.rebootless_apex_v1.apex",
"/data/apex/active/test.apex.rebootless*.apex");
}
@Before
@@ -124,9 +126,8 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
}
}
private void pushTestApex() throws Exception {
private void pushTestApex(String fileName) throws Exception {
CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
final String fileName = APK_IN_APEX_TESTAPEX_NAME + "_v1.apex";
final File apex = buildHelper.getTestFile(fileName);
if (!getDevice().isAdbRoot()) {
getDevice().enableAdbRoot();
@@ -142,7 +143,7 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
@Test
@LargeTest
public void testDuplicateApkInApexShouldFail() throws Exception {
pushTestApex();
pushTestApex(APK_IN_APEX_TESTAPEX_NAME + "_v1.apex");
runPhase("testDuplicateApkInApexShouldFail_Commit");
getDevice().reboot();
runPhase("testDuplicateApkInApexShouldFail_Verify");
@@ -344,6 +345,12 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
runPhase("testApexActivationFailureIsCapturedInSession_Verify");
}
@Test
public void testRebootlessUpdates() throws Exception {
pushTestApex("test.rebootless_apex_v1.apex");
runPhase("testRebootlessUpdates");
}
private List<String> getStagingDirectories() throws DeviceNotAvailableException {
String baseDir = "/data/app-staging";
try {