OSDN Git Service

Move legacy obb data migration to a handler thread.
authorNarayan Kamath <narayan@google.com>
Wed, 12 Jun 2019 12:06:30 +0000 (13:06 +0100)
committerNarayan Kamath <narayan@google.com>
Wed, 12 Jun 2019 12:40:15 +0000 (13:40 +0100)
The operation can potentially take a long time to complete
depending on the volume of data to be copied, so move it off
the ActivityManager handler thread that needs to be available
for other operations.

Bug: 134570017
Test: manual; set a 1 minute sleep in migrate_legacy_obb_data.sh

Change-Id: I3d2c52e8b012ed71c53810e6919d11be9a97cc6c

core/java/android/content/pm/PackageManagerInternal.java
services/core/java/com/android/server/StorageManagerService.java
services/core/java/com/android/server/pm/Installer.java
services/core/java/com/android/server/pm/PackageManagerService.java

index 666508a..672994e 100644 (file)
@@ -994,4 +994,9 @@ public abstract class PackageManagerInternal {
      */
     public abstract void setRuntimePermissionsFingerPrint(@NonNull String fingerPrint,
             @UserIdInt int userId);
+
+    /**
+     * Migrates legacy obb data to its new location.
+     */
+    public abstract void migrateLegacyObbData();
 }
index d2b992b..deff7ef 100644 (file)
@@ -580,6 +580,7 @@ class StorageManagerService extends IStorageManager.Stub
     private static final int H_RUN_IDLE_MAINT = 11;
     private static final int H_ABORT_IDLE_MAINT = 12;
     private static final int H_BOOT_COMPLETED = 13;
+    private static final int H_COMPLETE_UNLOCK_USER = 14;
 
     class StorageManagerServiceHandler extends Handler {
         public StorageManagerServiceHandler(Looper looper) {
@@ -698,7 +699,10 @@ class StorageManagerService extends IStorageManager.Stub
                     abortIdleMaint((Runnable)msg.obj);
                     break;
                 }
-
+                case H_COMPLETE_UNLOCK_USER: {
+                    completeUnlockUser((int) msg.obj);
+                    break;
+                }
             }
         }
     }
@@ -978,6 +982,17 @@ class StorageManagerService extends IStorageManager.Stub
             Slog.wtf(TAG, e);
         }
 
+        mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
+    }
+
+    private void completeUnlockUser(int userId) {
+        // If user 0 has completed unlock, perform a one-time migration of legacy obb data
+        // to its new location. This may take time depending on the size of the data to be copied
+        // so it's done on the StorageManager handler thread.
+        if (userId == 0) {
+            mPmInternal.migrateLegacyObbData();
+        }
+
         // Record user as started so newly mounted volumes kick off events
         // correctly, then synthesize events for any already-mounted volumes.
         synchronized (mLock) {
@@ -2820,6 +2835,12 @@ class StorageManagerService extends IStorageManager.Stub
         }
     }
 
+    private boolean isSystemUnlocked(int userId) {
+        synchronized (mLock) {
+            return ArrayUtils.contains(mSystemUnlockedUsers, userId);
+        }
+    }
+
     @Override
     public void prepareUserStorage(String volumeUuid, int userId, int serialNumber, int flags) {
         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
@@ -2996,6 +3017,11 @@ class StorageManagerService extends IStorageManager.Stub
         final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
         final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
 
+        // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There
+        // are no guarantees that callers will see a consistent view of the volume before that
+        // point
+        final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM);
+
         final boolean userKeyUnlocked;
         final boolean storagePermission;
         final long token = Binder.clearCallingIdentity();
@@ -3031,7 +3057,9 @@ class StorageManagerService extends IStorageManager.Stub
                 if (!match) continue;
 
                 boolean reportUnmounted = false;
-                if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
+                if (!systemUserUnlocked) {
+                    reportUnmounted = true;
+                } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
                     reportUnmounted = true;
                 } else if (!storagePermission && !realState) {
                     reportUnmounted = true;
index c2d5b2f..adcd19e 100644 (file)
@@ -121,24 +121,6 @@ public class Installer extends SystemService {
         }
     }
 
-    @Override
-    public void onUnlockUser(int userId) {
-        if (userId == 0) {
-            if (!checkBeforeRemote()) return;
-
-            if (mInstalld == null) {
-                Slog.wtf(TAG, "Call to onUnlockUser prior to onStart.");
-                return;
-            }
-
-            try {
-                mInstalld.migrateLegacyObbData();
-            } catch (RemoteException re) {
-                Slog.wtf(TAG, "Error migrating legacy OBB data.", re);
-            }
-        }
-    }
-
     private void connect() {
         IBinder binder = ServiceManager.getService("installd");
         if (binder != null) {
@@ -708,6 +690,24 @@ public class Installer extends SystemService {
         }
     }
 
+    /**
+     * Migrates obb data from its legacy location {@code /data/media/obb} to
+     * {@code /data/media/0/Android/obb}. This call is idempotent and a fast no-op if data has
+     * already been migrated.
+     *
+     * @throws InstallerException if an error occurs.
+     */
+    public boolean migrateLegacyObbData() throws InstallerException {
+        if (!checkBeforeRemote()) return false;
+
+        try {
+            mInstalld.migrateLegacyObbData();
+            return true;
+        } catch (Exception e) {
+            throw InstallerException.from(e);
+        }
+    }
+
     private static void assertValidInstructionSet(String instructionSet)
             throws InstallerException {
         for (String abi : Build.SUPPORTED_ABIS) {
index 7d5393d..ab60181 100644 (file)
@@ -24963,6 +24963,15 @@ public class PackageManagerService extends IPackageManager.Stub
                 mSettings.setRuntimePermissionsFingerPrintLPr(fingerPrint, userId);
             }
         }
+
+        @Override
+        public void migrateLegacyObbData() {
+            try {
+                mInstaller.migrateLegacyObbData();
+            } catch (Exception e) {
+                Slog.wtf(TAG, e);
+            }
+        }
     }
 
     @GuardedBy("mPackages")