diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index 73dc8dc78fbfe..53bf7b8aa8ae6 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -1051,13 +1051,18 @@ public abstract class ApexManager { final ParsedPackage parsedPackage2 = packageParser.parsePackage( new File(apexInfo.modulePath), flags, /* useCaches= */ false); final PackageInfo finalApexPkg = PackageInfoWithoutStateUtils.generate( - parsedPackage, apexInfo, flags); + parsedPackage2, apexInfo, flags); // Installation was successful, time to update mAllPackagesCache synchronized (mLock) { - for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) { - if (mAllPackagesCache.get(i).equals(existingApexPkg)) { - mAllPackagesCache.set(i, finalApexPkg); - break; + if (isFactory(existingApexPkg)) { + existingApexPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; + mAllPackagesCache.add(finalApexPkg); + } else { + for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) { + if (mAllPackagesCache.get(i).equals(existingApexPkg)) { + mAllPackagesCache.set(i, finalApexPkg); + break; + } } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0a7053c896d05..af3cb5bbe0cbc 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -17362,6 +17362,7 @@ public class PackageManagerService extends IPackageManager.Stub } catch (PackageManagerException e) { request.installResult.setError("APEX installation failed", e); } + invalidatePackageInfoCache(); notifyInstallObserver(request.installResult, request.args.observer); } diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java index fb768a8156248..8b8a7e631caff 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java @@ -37,6 +37,7 @@ import android.apex.ApexSessionInfo; import android.apex.ApexSessionParams; import android.apex.IApexService; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; @@ -349,9 +350,9 @@ public class ApexManagerTest { } @Test - public void testInstallPackage() throws Exception { + public void testInstallPackage_activeOnSystem() throws Exception { ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ true, - /* isFactory= */ false, extractResource("test.apex_rebootless_v1", + /* isFactory= */ true, extractResource("test.apex_rebootless_v1", "test.rebootless_apex_v1.apex")); when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo}); mApexManager.scanApexPackagesTraced(mPackageParser2, @@ -369,6 +370,55 @@ public class ApexManagerTest { ApexManager.MATCH_ACTIVE_PACKAGE); assertThat(newInfo.applicationInfo.sourceDir).isEqualTo(finalApex.getAbsolutePath()); assertThat(newInfo.applicationInfo.longVersionCode).isEqualTo(2); + assertThat(newInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM).isEqualTo(0); + assertThat(newInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) + .isEqualTo(ApplicationInfo.FLAG_INSTALLED); + + PackageInfo factoryInfo = mApexManager.getPackageInfo("test.apex.rebootless", + ApexManager.MATCH_FACTORY_PACKAGE); + assertThat(factoryInfo.applicationInfo.sourceDir).isEqualTo(activeApexInfo.modulePath); + assertThat(factoryInfo.applicationInfo.longVersionCode).isEqualTo(1); + assertThat(factoryInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) + .isEqualTo(ApplicationInfo.FLAG_SYSTEM); + assertThat(factoryInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED).isEqualTo(0); + } + + @Test + public void testInstallPackage_activeOnData() throws Exception { + ApexInfo factoryApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ false, + /* isFactory= */ true, extractResource("test.apex_rebootless_v1", + "test.rebootless_apex_v1.apex")); + ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ true, + /* isFactory= */ false, extractResource("test.apex.rebootless@1", + "test.rebootless_apex_v1.apex")); + when(mApexService.getAllPackages()) + .thenReturn(new ApexInfo[]{factoryApexInfo, activeApexInfo}); + mApexManager.scanApexPackagesTraced(mPackageParser2, + ParallelPackageParser.makeExecutorService()); + + File finalApex = extractResource("test.rebootles_apex_v2", "test.rebootless_apex_v2.apex"); + ApexInfo newApexInfo = createApexInfo("test.apex_rebootless", 2, /* isActive= */ true, + /* isFactory= */ false, finalApex); + when(mApexService.installAndActivatePackage(anyString())).thenReturn(newApexInfo); + + File installedApex = extractResource("installed", "test.rebootless_apex_v2.apex"); + mApexManager.installPackage(installedApex, mPackageParser2); + + PackageInfo newInfo = mApexManager.getPackageInfo("test.apex.rebootless", + ApexManager.MATCH_ACTIVE_PACKAGE); + assertThat(newInfo.applicationInfo.sourceDir).isEqualTo(finalApex.getAbsolutePath()); + assertThat(newInfo.applicationInfo.longVersionCode).isEqualTo(2); + assertThat(newInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM).isEqualTo(0); + assertThat(newInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) + .isEqualTo(ApplicationInfo.FLAG_INSTALLED); + + PackageInfo factoryInfo = mApexManager.getPackageInfo("test.apex.rebootless", + ApexManager.MATCH_FACTORY_PACKAGE); + assertThat(factoryInfo.applicationInfo.sourceDir).isEqualTo(factoryApexInfo.modulePath); + assertThat(factoryInfo.applicationInfo.longVersionCode).isEqualTo(1); + assertThat(factoryInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) + .isEqualTo(ApplicationInfo.FLAG_SYSTEM); + assertThat(factoryInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED).isEqualTo(0); } @Test diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java index d6b3c27b4b09f..9cdaef75c491a 100644 --- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java @@ -212,6 +212,28 @@ public class StagedInstallInternalTest { assertThat(apex.applicationInfo.sourceDir).startsWith("/system/apex"); } + TestApp apex1 = new TestApp("TestRebootlessApexV1", "test.apex.rebootless", 1, + /* isApex= */ true, "test.rebootless_apex_v1.apex"); + Install.single(apex1).commit(); + + { + PackageInfo apex = pm.getPackageInfo("test.apex.rebootless", PackageManager.MATCH_APEX); + assertThat(apex.getLongVersionCode()).isEqualTo(1); + 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"); + } + { + PackageInfo apex = pm.getPackageInfo("test.apex.rebootless", + PackageManager.MATCH_APEX | PackageManager.MATCH_FACTORY_ONLY); + assertThat(apex.getLongVersionCode()).isEqualTo(1); + assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) + .isEqualTo(ApplicationInfo.FLAG_SYSTEM); + assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED).isEqualTo(0); + 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(); @@ -224,6 +246,15 @@ public class StagedInstallInternalTest { .isEqualTo(ApplicationInfo.FLAG_INSTALLED); assertThat(apex.applicationInfo.sourceDir).startsWith("/data/apex/active"); } + { + PackageInfo apex = pm.getPackageInfo("test.apex.rebootless", + PackageManager.MATCH_APEX | PackageManager.MATCH_FACTORY_ONLY); + assertThat(apex.getLongVersionCode()).isEqualTo(1); + assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) + .isEqualTo(ApplicationInfo.FLAG_SYSTEM); + assertThat(apex.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED).isEqualTo(0); + assertThat(apex.applicationInfo.sourceDir).startsWith("/system/apex"); + } } private static void assertSessionFailedWithMessage(int sessionId, String msg) {