summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Keun young Park <keunyoung@google.com> 2020-06-18 16:01:05 -0700
committer Keun young Park <keunyoung@google.com> 2020-06-22 09:35:28 -0700
commit37a49da1aa47f1bb23dfa26c1fa7d2720f82ac6b (patch)
treed079b9fe5effe9d01822e412873329999edb99d5
parentcc498f3e695a18879b1e6cbb6ca348f654d1cf01 (diff)
Restore lost unlocked users after vold reset
- In automotive, vold reset / resetIfBootedAndConnected() call can lose pending unlock request for a user if boot completion and unlock happens at the same time. In automotive, user unlock can happen before boot complete. - After vold reset, check for such lost user (=marked unlocking or unlocked in UserManager level but is still locked in StorageManager level) and retry unlocking. - This also undo previous CL to keep handler messages as that cannot prevent all the race, especially race of vold reset right after onUnlockUser call. But handler update is kept inside the service. - The restoration is done only for automotive device for now as phone does not have such case. Bug: 151457974 Test: try reboot in auto devices where this race can happen. Change-Id: I3b50750f5602c805e79f79f061eed44f880b25bd
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java57
1 files changed, 51 insertions, 6 deletions
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index b46bebbd03d5..6e8eca3f46cf 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -458,6 +458,12 @@ class StorageManagerService extends IStorageManager.Stub
"(?i)(^/storage/[^/]+/(?:([0-9]+)/)?Android/(?:data|media|obb|sandbox)/)([^/]+)(/.*)?");
+ /** Automotive device unlockes users before system boot complete and this requires special
+ * handling as vold reset can lead into race conditions. When this is set, all users unlocked
+ * in {@code UserManager} level are unlocked after vold reset.
+ */
+ private final boolean mIsAutomotive;
+
private VolumeInfo findVolumeByIdOrThrow(String id) {
synchronized (mLock) {
final VolumeInfo vol = mVolumes.get(id);
@@ -1082,14 +1088,12 @@ class StorageManagerService extends IStorageManager.Stub
Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted
+ ", mDaemonConnected=" + mDaemonConnected);
if (mBootCompleted && mDaemonConnected) {
- final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
+ final UserManager userManager = mContext.getSystemService(UserManager.class);
+ final List<UserInfo> users = userManager.getUsers();
if (mIsFuseEnabled) {
mStorageSessionController.onReset(mVold, () -> {
- mHandler.removeMessages(H_RESET);
- mHandler.removeMessages(H_VOLUME_BROADCAST);
- mHandler.removeMessages(H_VOLUME_MOUNT);
- mHandler.removeMessages(H_VOLUME_UNMOUNT);
+ mHandler.removeCallbacksAndMessages(null);
});
} else {
killMediaProvider(users);
@@ -1097,7 +1101,9 @@ class StorageManagerService extends IStorageManager.Stub
final int[] systemUnlockedUsers;
synchronized (mLock) {
- systemUnlockedUsers = mSystemUnlockedUsers;
+ // make copy as sorting can change order
+ systemUnlockedUsers = Arrays.copyOf(mSystemUnlockedUsers,
+ mSystemUnlockedUsers.length);
mDisks.clear();
mVolumes.clear();
@@ -1119,6 +1125,9 @@ class StorageManagerService extends IStorageManager.Stub
mVold.onUserStarted(userId);
mStoraged.onUserStarted(userId);
}
+ if (mIsAutomotive) {
+ restoreAllUnlockedUsers(userManager, users, systemUnlockedUsers);
+ }
mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
mStorageManagerInternal.onReset(mVold);
} catch (Exception e) {
@@ -1127,6 +1136,29 @@ class StorageManagerService extends IStorageManager.Stub
}
}
+ private void restoreAllUnlockedUsers(UserManager userManager, List<UserInfo> allUsers,
+ int[] systemUnlockedUsers) throws Exception {
+ Arrays.sort(systemUnlockedUsers);
+ UserManager.invalidateIsUserUnlockedCache();
+ for (UserInfo user : allUsers) {
+ int userId = user.id;
+ if (!userManager.isUserRunning(userId)) {
+ continue;
+ }
+ if (Arrays.binarySearch(systemUnlockedUsers, userId) >= 0) {
+ continue;
+ }
+ boolean unlockingOrUnlocked = userManager.isUserUnlockingOrUnlocked(userId);
+ if (!unlockingOrUnlocked) {
+ continue;
+ }
+ Slog.w(TAG, "UNLOCK_USER lost from vold reset, will retry, user:" + userId);
+ mVold.onUserStarted(userId);
+ mStoraged.onUserStarted(userId);
+ mHandler.obtainMessage(H_COMPLETE_UNLOCK_USER, userId).sendToTarget();
+ }
+ }
+
private void onUnlockUser(int userId) {
Slog.d(TAG, "onUnlockUser " + userId);
@@ -1157,6 +1189,15 @@ class StorageManagerService extends IStorageManager.Stub
// Record user as started so newly mounted volumes kick off events
// correctly, then synthesize events for any already-mounted volumes.
synchronized (mLock) {
+ if (mIsAutomotive) {
+ for (int unlockedUser : mSystemUnlockedUsers) {
+ if (unlockedUser == userId) {
+ // This can happen as restoreAllUnlockedUsers can double post the message.
+ Log.i(TAG, "completeUnlockUser called for already unlocked user:" + userId);
+ return;
+ }
+ }
+ }
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
@@ -1822,6 +1863,9 @@ class StorageManagerService extends IStorageManager.Stub
if (WATCHDOG_ENABLE) {
Watchdog.getInstance().addMonitor(this);
}
+
+ mIsAutomotive = context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE);
}
/**
@@ -4477,6 +4521,7 @@ class StorageManagerService extends IStorageManager.Stub
pw.println("Forced scoped storage app list: "
+ DeviceConfig.getProperty(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
PROP_FORCED_SCOPED_STORAGE_WHITELIST));
+ pw.println("isAutomotive:" + mIsAutomotive);
}
synchronized (mObbMounts) {