Merge "Clean up how APK backups are made."
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 4613400..4c2b3c2 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -47,7 +47,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.LocalServices;
 import com.android.server.pm.Installer;
-import com.android.server.pm.PackageManagerServiceUtils;
 
 import java.io.File;
 import java.io.IOException;
@@ -329,15 +328,18 @@
                 int sessionId = packageInstaller.createSession(params);
                 PackageInstaller.Session session = packageInstaller.openSession(sessionId);
 
-                // TODO: Will it always be called "base.apk"? What about splits?
-                // What about apex?
-                File packageDir = new File(data.backupDir, info.getPackageName());
-                File baseApk = new File(packageDir, "base.apk");
-                try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(baseApk,
+                File packageCode = RollbackStore.getPackageCode(data, info.getPackageName());
+                if (packageCode == null) {
+                    sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE,
+                            "Backup copy of package code inaccessible");
+                    return;
+                }
+
+                try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(packageCode,
                         ParcelFileDescriptor.MODE_READ_ONLY)) {
                     final long token = Binder.clearCallingIdentity();
                     try {
-                        session.write("base.apk", 0, baseApk.length(), fd);
+                        session.write(packageCode.getName(), 0, packageCode.length(), fd);
                     } finally {
                         Binder.restoreCallingIdentity(token);
                     }
@@ -735,17 +737,19 @@
         VersionedPackage newVersion = new VersionedPackage(packageName, newPackage.versionCode);
 
         // Get information about the currently installed package.
-        PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
-        PackageParser.Package installedPackage = pm.getPackage(packageName);
-        if (installedPackage == null) {
+        PackageManager pm = mContext.getPackageManager();
+        PackageInfo pkgInfo = null;
+        try {
+            pkgInfo = pm.getPackageInfo(packageName, 0);
+        } catch (PackageManager.NameNotFoundException e) {
             // TODO: Support rolling back fresh package installs rather than
             // fail here. Test this case.
             Log.e(TAG, packageName + " is not installed");
             return false;
         }
-        VersionedPackage installedVersion = new VersionedPackage(packageName,
-                installedPackage.getLongVersionCode());
 
+        VersionedPackage installedVersion = new VersionedPackage(packageName,
+                pkgInfo.getLongVersionCode());
 
         final IntArray pendingBackups = mUserdataHelper.snapshotAppData(packageName,
                 installedUsers);
@@ -769,16 +773,12 @@
             return false;
         }
 
-        File packageDir = mRollbackStore.packageCodePathForAvailableRollback(data, packageName);
-        packageDir.mkdirs();
-
-        // TODO: Copy by hard link instead to save on cpu and storage space?
-        int status = PackageManagerServiceUtils.copyPackage(installedPackage.codePath, packageDir);
-        if (status != PackageManager.INSTALL_SUCCEEDED) {
-            Log.e(TAG, "Unable to copy package for rollback for " + packageName);
+        try {
+            RollbackStore.backupPackageCode(data, packageName, pkgInfo.applicationInfo.sourceDir);
+        } catch (IOException e) {
+            Log.e(TAG, "Unable to copy package for rollback for " + packageName, e);
             return false;
         }
-
         return true;
     }
 
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index c70f47d..d8e1f62 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -33,6 +33,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.nio.file.Files;
 import java.time.Instant;
 import java.time.format.DateTimeParseException;
 import java.util.ArrayList;
@@ -201,11 +202,30 @@
     }
 
     /**
-     * Returns the directory where the code for a package should be stored for
-     * given rollback <code>data</code> and <code>packageName</code>.
+     * Creates a backup copy of the apk or apex for a package.
      */
-    File packageCodePathForAvailableRollback(RollbackData data, String packageName) {
-        return new File(data.backupDir, packageName);
+    static void backupPackageCode(RollbackData data, String packageName, String codePath)
+            throws IOException {
+        File sourceFile = new File(codePath);
+        File targetDir = new File(data.backupDir, packageName);
+        targetDir.mkdirs();
+        File targetFile = new File(targetDir, sourceFile.getName());
+
+        // TODO: Copy by hard link instead to save on cpu and storage space?
+        Files.copy(sourceFile.toPath(), targetFile.toPath());
+    }
+
+    /**
+     * Returns the apk or apex file backed up for the given package.
+     * Returns null if none found.
+     */
+    static File getPackageCode(RollbackData data, String packageName) {
+        File targetDir = new File(data.backupDir, packageName);
+        File[] files = targetDir.listFiles();
+        if (files == null || files.length != 1) {
+            return null;
+        }
+        return files[0];
     }
 
     /**