summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-12-16 00:19:27 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-12-16 00:19:27 +0000
commitf1563010352f32301e8af75c5479b81ef5b90aa7 (patch)
tree625503b6cd7dbfe16c1d745aa91be305870d7690
parent0c0a65508f1a7fd5d07f6b7f9df7c33ba31bd373 (diff)
parent2dfebdbfd521bd87dac323d3350733586e46ef52 (diff)
downloadbase-android11-qpr1-release.tar.gz
Merge cherrypicks of [13232455, 13232456, 13232432, 13232495, 13232299, 13232399, 13232951, 13232952, 13232953, 13232954, 13232955, 13232956, 13232957, 13232522, 13232433, 13232353, 13232400, 13232354, 13232699, 13232700, 13232701, 13232702] into rvc-qpr1-releaseandroid-11.0.0_r29android11-qpr1-release
Change-Id: Ib418ded080791ab8610cd2623246270286a70f2e
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java4
-rw-r--r--tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java13
-rw-r--r--tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java51
4 files changed, 72 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 330f99523507..9f0efa5fad83 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -299,6 +299,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
final ArraySet<File> unclaimedStages = newArraySet(
stagingDir.listFiles(sStageFilter));
+ // We also need to clean up orphaned staging directory for staged sessions
+ final File stagedSessionStagingDir = Environment.getDataStagingDirectory(volumeUuid);
+ unclaimedStages.addAll(newArraySet(stagedSessionStagingDir.listFiles()));
+
// Ignore stages claimed by active sessions
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index ea53132ae409..c9f09545c3e6 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1581,6 +1581,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
destroyInternal();
// Dispatch message to remove session from PackageInstallerService.
dispatchSessionFinished(error, detailMessage, null);
+ // TODO(b/173194203): clean up staged session in destroyInternal() call instead
+ if (isStaged() && stageDir != null) {
+ cleanStageDir();
+ }
}
private void onStorageUnhealthy() {
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 02597d548361..e67354982b05 100644
--- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -96,6 +96,19 @@ public class StagedInstallInternalTest {
assertSessionReady(sessionId);
}
+ @Test
+ public void testStagedInstallationShouldCleanUpOnValidationFailure() throws Exception {
+ InstallUtils.commitExpectingFailure(AssertionError.class, "INSTALL_FAILED_INVALID_APK",
+ Install.single(TestApp.AIncompleteSplit).setStaged());
+ }
+
+ @Test
+ public void testStagedInstallationShouldCleanUpOnValidationFailureMultiPackage()
+ throws Exception {
+ InstallUtils.commitExpectingFailure(AssertionError.class, "INSTALL_FAILED_INVALID_APK",
+ Install.multi(TestApp.AIncompleteSplit, TestApp.B1, TestApp.Apex1).setStaged());
+ }
+
private static void assertSessionReady(int sessionId) {
assertSessionState(sessionId,
(session) -> assertThat(session.isStagedSessionReady()).isTrue());
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index 9b432f7d0ca5..28a5424199a4 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertTrue;
import com.android.ddmlib.Log;
+import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.util.ProcessInfo;
@@ -30,6 +31,10 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
@RunWith(DeviceJUnit4ClassRunner.class)
public class StagedInstallInternalTest extends BaseHostJUnit4Test {
@@ -87,6 +92,52 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
runPhase("testSystemServerRestartDoesNotAffectStagedSessions_Verify");
}
+ @Test
+ public void testStagedInstallationShouldCleanUpOnValidationFailure() throws Exception {
+ List<String> before = getStagingDirectories();
+ runPhase("testStagedInstallationShouldCleanUpOnValidationFailure");
+ List<String> after = getStagingDirectories();
+ assertThat(after).isEqualTo(before);
+ }
+
+ @Test
+ public void testStagedInstallationShouldCleanUpOnValidationFailureMultiPackage()
+ throws Exception {
+ List<String> before = getStagingDirectories();
+ runPhase("testStagedInstallationShouldCleanUpOnValidationFailureMultiPackage");
+ List<String> after = getStagingDirectories();
+ assertThat(after).isEqualTo(before);
+ }
+
+ @Test
+ public void testOrphanedStagingDirectoryGetsCleanedUpOnReboot() throws Exception {
+ //create random directories in /data/app-staging folder
+ getDevice().enableAdbRoot();
+ getDevice().executeShellCommand("mkdir /data/app-staging/session_123");
+ getDevice().executeShellCommand("mkdir /data/app-staging/random_name");
+ getDevice().disableAdbRoot();
+
+ assertThat(getStagingDirectories()).isNotEmpty();
+ getDevice().reboot();
+ assertThat(getStagingDirectories()).isEmpty();
+ }
+
+ private List<String> getStagingDirectories() throws DeviceNotAvailableException {
+ String baseDir = "/data/app-staging";
+ try {
+ getDevice().enableAdbRoot();
+ return getDevice().getFileEntry(baseDir).getChildren(false)
+ .stream().filter(entry -> entry.getName().matches("session_\\d+"))
+ .map(entry -> entry.getName())
+ .collect(Collectors.toList());
+ } catch (Exception e) {
+ // Return an empty list if any error
+ return Collections.EMPTY_LIST;
+ } finally {
+ getDevice().disableAdbRoot();
+ }
+ }
+
private void restartSystemServer() throws Exception {
// Restart the system server
long oldStartTime = getDevice().getProcessByName("system_server").getStartTime();