Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e915a7e1 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Attempt at fixing race condition during boot.

We've found local evidence that on fast hardware that the
MediaProvider.updateVolumes() method can be invoked while the
device is still unlocking.  This can cause a race condition due to
the "reportUnmounted" logic in StorageManagerService.getVolumeList()
which attempts to hide all volumes from apps until after the user
has been unlocked.

Since MediaProvider itself is the one hosting the FUSE daemon, it
always needs to know the real underlying state of volumes, so this
change adds special treatment to never augment the mount state
when the caller is the FUSE daemon.

Bug: 159189865
Test: manual
Change-Id: Id86e86aa942a697877860961d20ff0d8458dbc10
parent f21036b4
Loading
Loading
Loading
Loading
+17 −1
Original line number Original line Diff line number Diff line
@@ -3535,6 +3535,13 @@ class StorageManagerService extends IStorageManager.Stub
        // point
        // point
        final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM);
        final boolean systemUserUnlocked = isSystemUnlocked(UserHandle.USER_SYSTEM);


        // When the caller is the app actually hosting external storage, we
        // should never attempt to augment the actual storage volume state,
        // otherwise we risk confusing it with race conditions as users go
        // through various unlocked states
        final boolean callerIsMediaStore = UserHandle.isSameApp(Binder.getCallingUid(),
                mMediaStoreAuthorityAppId);

        final boolean userIsDemo;
        final boolean userIsDemo;
        final boolean userKeyUnlocked;
        final boolean userKeyUnlocked;
        final boolean storagePermission;
        final boolean storagePermission;
@@ -3554,6 +3561,7 @@ class StorageManagerService extends IStorageManager.Stub
        final ArraySet<String> resUuids = new ArraySet<>();
        final ArraySet<String> resUuids = new ArraySet<>();
        synchronized (mLock) {
        synchronized (mLock) {
            for (int i = 0; i < mVolumes.size(); i++) {
            for (int i = 0; i < mVolumes.size(); i++) {
                final String volId = mVolumes.keyAt(i);
                final VolumeInfo vol = mVolumes.valueAt(i);
                final VolumeInfo vol = mVolumes.valueAt(i);
                switch (vol.getType()) {
                switch (vol.getType()) {
                    case VolumeInfo.TYPE_PUBLIC:
                    case VolumeInfo.TYPE_PUBLIC:
@@ -3578,11 +3586,19 @@ class StorageManagerService extends IStorageManager.Stub
                if (!match) continue;
                if (!match) continue;


                boolean reportUnmounted = false;
                boolean reportUnmounted = false;
                if (!systemUserUnlocked) {
                if (callerIsMediaStore) {
                    // When the caller is the app actually hosting external storage, we
                    // should never attempt to augment the actual storage volume state,
                    // otherwise we risk confusing it with race conditions as users go
                    // through various unlocked states
                } else if (!systemUserUnlocked) {
                    reportUnmounted = true;
                    reportUnmounted = true;
                    Slog.w(TAG, "Reporting " + volId + " unmounted due to system locked");
                } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
                } else if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
                    reportUnmounted = true;
                    reportUnmounted = true;
                    Slog.w(TAG, "Reporting " + volId + "unmounted due to " + userId + " locked");
                } else if (!storagePermission && !realState) {
                } else if (!storagePermission && !realState) {
                    Slog.w(TAG, "Reporting " + volId + "unmounted due to missing permissions");
                    reportUnmounted = true;
                    reportUnmounted = true;
                }
                }