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

Commit 6b7bb604 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Split app move into separate copy/delete steps.

App movement now has three distinct stages: copying, scanning, and
cleanup.  Previously, a battery pull late in the move process would
end up with packages.xml pointing at the old location which had been
torn down.  Now, we update packages.xml to point at the new location
as the "source of truth" before we start deleting the old location.

Bug: 21831336
Change-Id: I6f57f37a8cb335127db9ebb7c6b6cfe5755ada99
parent 2047929e
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -264,9 +264,9 @@ public final class Installer extends SystemService {
        return mInstaller.execute(builder.toString());
    }

    public int moveCompleteApp(String fromUuid, String toUuid, String packageName,
    public int copyCompleteApp(String fromUuid, String toUuid, String packageName,
            String dataAppName, int appId, String seinfo) {
        StringBuilder builder = new StringBuilder("mvcompleteapp");
        StringBuilder builder = new StringBuilder("cpcompleteapp");
        builder.append(' ');
        builder.append(escapeNull(fromUuid));
        builder.append(' ');
+21 −23
Original line number Diff line number Diff line
@@ -11278,7 +11278,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            if (DEBUG_INSTALL) Slog.d(TAG, "Moving " + move.packageName + " from "
                    + move.fromUuid + " to " + move.toUuid);
            synchronized (mInstaller) {
                if (mInstaller.moveCompleteApp(move.fromUuid, move.toUuid, move.packageName,
                if (mInstaller.copyCompleteApp(move.fromUuid, move.toUuid, move.packageName,
                        move.dataAppName, move.appId, move.seinfo) != 0) {
                    return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
                }
@@ -11293,14 +11293,14 @@ public class PackageManagerService extends IPackageManager.Stub {
        int doPreInstall(int status) {
            if (status != PackageManager.INSTALL_SUCCEEDED) {
                cleanUp();
                cleanUp(move.toUuid);
            }
            return status;
        }
        boolean doRename(int status, PackageParser.Package pkg, String oldCodePath) {
            if (status != PackageManager.INSTALL_SUCCEEDED) {
                cleanUp();
                cleanUp(move.toUuid);
                return false;
            }
@@ -11317,8 +11317,10 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
        int doPostInstall(int status, int uid) {
            if (status != PackageManager.INSTALL_SUCCEEDED) {
                cleanUp();
            if (status == PackageManager.INSTALL_SUCCEEDED) {
                cleanUp(move.fromUuid);
            } else {
                cleanUp(move.toUuid);
            }
            return status;
        }
@@ -11333,32 +11335,28 @@ public class PackageManagerService extends IPackageManager.Stub {
            return (resourceFile != null) ? resourceFile.getAbsolutePath() : null;
        }
        private boolean cleanUp() {
            if (codeFile == null || !codeFile.exists()) {
                return false;
            }
        private boolean cleanUp(String volumeUuid) {
            final File codeFile = new File(Environment.getDataAppDirectory(volumeUuid),
                    move.dataAppName);
            Slog.d(TAG, "Cleaning up " + move.packageName + " on " + volumeUuid);
            synchronized (mInstallLock) {
                // Clean up both app data and code
                removeDataDirsLI(volumeUuid, move.packageName);
                if (codeFile.isDirectory()) {
                    mInstaller.rmPackageDir(codeFile.getAbsolutePath());
                } else {
                    codeFile.delete();
                }
            if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
                resourceFile.delete();
            }
            return true;
        }
        void cleanUpResourcesLI() {
            cleanUp();
            throw new UnsupportedOperationException();
        }
        boolean doPostDeleteLI(boolean delete) {
            // XXX err, shouldn't we respect the delete flag?
            cleanUpResourcesLI();
            return true;
            throw new UnsupportedOperationException();
        }
    }