From 6b7bb60457501ff4110933c3e9b66446eb4f7b19 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 7 Jul 2015 13:32:09 -0700 Subject: [PATCH] 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 --- .../java/com/android/server/pm/Installer.java | 4 +- .../server/pm/PackageManagerService.java | 44 +++++++++---------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 8dc4bd3b32af6..b59b4b2586ee7 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -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(' '); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0240dbb7a7853..8fbdfcaafb3da 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -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 (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(); } }