Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec050f6a authored by JW Wang's avatar JW Wang
Browse files

Clean up staging directories of abandoned sessions (4/n)

Now ag/12369403 prevents a staged session from being a child of a
non-staged session which however discloses a bug where the staging
directory is not correctly cleaned up when a non-committed staged
session is abandoned.

This CL fixes that and adds a test to check staging directories are
correctly deleted when abandoning both committed and non-committed
sessions.

Bug: 163976510
Test: atest StagedInstallTest StagedInstallInternalTest
Change-Id: I5d0eed9c5cc71c29a12e61471b2f870140899087
parent 348096df
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -2762,15 +2762,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                // do it now.
                return;
            }
            if (mCommitted) {
            mDestroyed = true;
            if (mCommitted) {
                if (!mStagingManager.abortCommittedSessionLocked(this)) {
                    // Do not clean up the staged session from system. It is not safe yet.
                    mCallback.onStagedSessionChanged(this);
                    return;
                }
                cleanStageDir(getChildSessionsLocked());
            }
            cleanStageDir(getChildSessionsLocked());
            destroyInternal();
        }
        dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
+12 −0
Original line number Diff line number Diff line
@@ -119,6 +119,18 @@ public class StagedInstallInternalTest {
        assertSessionReady(sessionId);
    }

    @Test
    public void testAbandonStagedSessionShouldCleanUp() throws Exception {
        int id1 = Install.single(TestApp.A1).setStaged().createSession();
        InstallUtils.getPackageInstaller().abandonSession(id1);
        int id2 = Install.multi(TestApp.A1).setStaged().createSession();
        InstallUtils.getPackageInstaller().abandonSession(id2);
        int id3 = Install.single(TestApp.A1).setStaged().commit();
        InstallUtils.getPackageInstaller().abandonSession(id3);
        int id4 = Install.multi(TestApp.A1).setStaged().commit();
        InstallUtils.getPackageInstaller().abandonSession(id4);
    }

    private static void assertSessionReady(int sessionId) {
        assertSessionState(sessionId,
                (session) -> assertThat(session.isStagedSessionReady()).isTrue());
+25 −0
Original line number Diff line number Diff line
@@ -41,6 +41,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@RunWith(DeviceJUnit4ClassRunner.class)
public class StagedInstallInternalTest extends BaseHostJUnit4Test {
@@ -200,6 +203,28 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
        assertThat(sessionIds.length).isEqualTo(3);
    }

    @Test
    public void testAbandonStagedSessionShouldCleanUp() throws Exception {
        List<String> before = getStagingDirectories();
        runPhase("testAbandonStagedSessionShouldCleanUp");
        List<String> after = getStagingDirectories();
        // The staging directories generated during the test should be deleted
        assertThat(after).isEqualTo(before);
    }

    private List<String> getStagingDirectories() {
        String baseDir = "/data/app-staging";
        try {
            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;
        }
    }

    private void restartSystemServer() throws Exception {
        // Restart the system server
        ProcessInfo oldPs = getDevice().getProcessByName("system_server");