Merge "Perform user data back up in post install stage" into qt-dev
am: 5b9e00273b

Change-Id: I7b45401aeaf34855921f25a2c00c9af1a1a25035
diff --git a/core/java/android/content/rollback/IRollbackManager.aidl b/core/java/android/content/rollback/IRollbackManager.aidl
index db9fcb6..1b84f29 100644
--- a/core/java/android/content/rollback/IRollbackManager.aidl
+++ b/core/java/android/content/rollback/IRollbackManager.aidl
@@ -30,9 +30,9 @@
             String callerPackageName, in IntentSender statusReceiver);
 
     // Exposed for use from the system server only. Callback from the package
-    // manager during the install flow when user data can be restored for a given
+    // manager during the install flow when user data can be backed up and restored for a given
     // package.
-    void restoreUserData(String packageName, in int[] userIds, int appId, long ceDataInode,
+    void snapshotAndRestoreUserData(String packageName, in int[] userIds, int appId, long ceDataInode,
             String seInfo, int token);
 
     // Exposed for test purposes only.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e67dc48..6aec425 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -14758,7 +14758,7 @@
 
             if (ps != null) {
                 try {
-                    rm.restoreUserData(packageName, installedUsers, appId, ceDataInode,
+                    rm.snapshotAndRestoreUserData(packageName, installedUsers, appId, ceDataInode,
                             seInfo, token);
                 } catch (RemoteException re) {
                     // Cannot happen, the RollbackManager is hosted in the same process.
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 9a2778d..301f650 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -923,8 +923,8 @@
         }
 
         if (rd != null) {
-            // This is the apk session for a staged session. We have already
-            // backed up the apks, we just need to do user data backup.
+            // This is the apk session for a staged session. We do not need to create a new rollback
+            // for this session.
             PackageParser.PackageLite newPackage = null;
             try {
                 newPackage = PackageParser.parsePackageLite(
@@ -937,8 +937,6 @@
             for (PackageRollbackInfo info : rd.info.getPackages()) {
                 if (info.getPackageName().equals(packageName)) {
                     info.getInstalledUsers().addAll(IntArray.wrap(installedUsers));
-                    mAppDataRollbackHelper.snapshotAppData(rd.info.getRollbackId(), info);
-                    saveRollbackData(rd);
                     return true;
                 }
             }
@@ -959,8 +957,7 @@
         }
         newRollback.addToken(token);
 
-        return enableRollbackForPackageSession(newRollback.data, packageSession,
-                installedUsers, /* snapshotUserData*/ true);
+        return enableRollbackForPackageSession(newRollback.data, packageSession, installedUsers);
     }
 
     /**
@@ -971,8 +968,7 @@
      * @return true on success, false on failure.
      */
     private boolean enableRollbackForPackageSession(RollbackData data,
-            PackageInstaller.SessionInfo session, @NonNull int[] installedUsers,
-            boolean snapshotUserData) {
+            PackageInstaller.SessionInfo session, @NonNull int[] installedUsers) {
         // TODO: Don't attempt to enable rollback for split installs.
         final int installFlags = session.installFlags;
         if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
@@ -1033,10 +1029,6 @@
                 isApex, IntArray.wrap(installedUsers),
                 new SparseLongArray() /* ceSnapshotInodes */);
 
-        if (snapshotUserData && !isApex) {
-            mAppDataRollbackHelper.snapshotAppData(data.info.getRollbackId(), packageRollbackInfo);
-        }
-
         try {
             ApplicationInfo appInfo = pkgInfo.applicationInfo;
             RollbackStore.backupPackageCodePath(data, packageName, appInfo.sourceDir);
@@ -1057,13 +1049,15 @@
     }
 
     @Override
-    public void restoreUserData(String packageName, int[] userIds, int appId, long ceDataInode,
-            String seInfo, int token) {
+    public void snapshotAndRestoreUserData(String packageName, int[] userIds, int appId,
+            long ceDataInode, String seInfo, int token) {
         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
-            throw new SecurityException("restoreUserData may only be called by the system.");
+            throw new SecurityException(
+                    "snapshotAndRestoreUserData may only be called by the system.");
         }
 
         getHandler().post(() -> {
+            snapshotUserDataInternal(packageName);
             restoreUserDataInternal(packageName, userIds, appId, ceDataInode, seInfo, token);
             final PackageManagerInternal pmi = LocalServices.getService(
                     PackageManagerInternal.class);
@@ -1071,6 +1065,38 @@
         });
     }
 
+    private void snapshotUserDataInternal(String packageName) {
+        synchronized (mLock) {
+            // staged installs
+            ensureRollbackDataLoadedLocked();
+            for (int i = 0; i < mRollbacks.size(); i++) {
+                RollbackData data = mRollbacks.get(i);
+                if (data.state != RollbackData.ROLLBACK_STATE_ENABLING) {
+                    continue;
+                }
+
+                for (PackageRollbackInfo info : data.info.getPackages()) {
+                    if (info.getPackageName().equals(packageName)) {
+                        mAppDataRollbackHelper.snapshotAppData(data.info.getRollbackId(), info);
+                        saveRollbackData(data);
+                        return;
+                    }
+                }
+            }
+            // non-staged installs
+            PackageRollbackInfo info;
+            for (NewRollback rollback : mNewRollbacks) {
+                info = getPackageRollbackInfo(rollback.data, packageName);
+                if (info != null) {
+                    mAppDataRollbackHelper.snapshotAppData(rollback.data.info.getRollbackId(),
+                            info);
+                    saveRollbackData(rollback.data);
+                    return;
+                }
+            }
+        }
+    }
+
     private void restoreUserDataInternal(String packageName, int[] userIds, int appId,
             long ceDataInode, String seInfo, int token) {
         PackageRollbackInfo info = null;
@@ -1130,7 +1156,7 @@
 
             if (!session.isMultiPackage()) {
                 if (!enableRollbackForPackageSession(newRollback.data, session,
-                            new int[0], /* snapshotUserData */ false)) {
+                            new int[0])) {
                     Log.e(TAG, "Unable to enable rollback for session: " + sessionId);
                     result.offer(false);
                     return;
@@ -1145,7 +1171,7 @@
                         return;
                     }
                     if (!enableRollbackForPackageSession(newRollback.data, childSession,
-                                new int[0], /* snapshotUserData */ false)) {
+                                new int[0])) {
                         Log.e(TAG, "Unable to enable rollback for session: " + sessionId);
                         result.offer(false);
                         return;