Merge changes from topic "fail-validation" into rvc-qpr-dev
* changes: Delete orphaned staging directories for staged session on reboot Clean up staged session data on validation failure
This commit is contained in:
committed by
Android (Google) Code Review
commit
28829eb116
@@ -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);
|
||||
|
||||
@@ -1597,6 +1597,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() {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user