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

Commit 96e928da authored by Tommy Webb's avatar Tommy Webb Committed by Michael Bestas
Browse files

Fix external storage access with system user locked

Make adaptations that allow secondary users to access (their own)
external storage even if the system user is locked, so that when the
system is configured to allow this, it works properly.

* Do not require the system user to be unlocked in order to initialize
  external storage; allow any full user (i.e. non-profile) to do so.
  Under typical circumstances, the system user will be unlocked first.
  AOSP appeared to rely on that idea - along with the idea that
  the system user would only be unlocked once - as a way to assure
  that system-wide access to external storage was initialized just once
  and at an appropriate time. However, if settings allow switching
  users when the system user is locked, then a different full user may
  unlock first, and that's a fine enough time to make external storage
  available, considering that such users need external storage, too.
  And we ensure it only (successfully) happens once by checking that
  the component name assigned during initialization has yet to be set.

* Don't falsely report that volumes are unmounted just because the
  system user (user 0) is locked. Instead, check the calling user
  itself, or rather its parent if it is a profile.
  This AOSP behavior that we're altering was added as part of a legacy
  obb data migration, as a way to prevent listing volumes when that
  migration is still in progress. The volumes would be reported as
  unmounted during that time. That migration is specific to user 0
  and has no effect on other users; so, if user 0 is locked, it's
  of no consequence to users outside of its profile group, since they
  cannot access its data by design.

Test: Manual: Create a new user. `adb shell settings put global \
      allow_user_switching_when_system_user_locked 1`. Ensure your
      main user has a PIN/password/pattern. Reboot. Switch to the
      new user without unlocking the main user. Open Files. With this
      change, you'll see folders. Without it, you'll see an error.

Change-Id: Ie832a65758d763a12f61ccbb46331a3d98de7268
parent a48bd2e7
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -3882,18 +3882,22 @@ class StorageManagerService extends IStorageManager.Stub
            }
        }

        // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There
        // Report all volumes as unmounted until we've recorded that the parent 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 systemUserUnlocked;

        final boolean userIsDemo;
        final boolean storagePermission;
        final boolean ceStorageUnlocked;
        final long token = Binder.clearCallingIdentity();
        try {
            userIsDemo = LocalServices.getService(UserManagerInternal.class)
                    .getUserInfo(userId).isDemo();
            final UserInfo userInfo = LocalServices.getService(UserManagerInternal.class)
                    .getUserInfo(userId);
            final int parentUserId = userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
                    ? userInfo.profileGroupId : userId;
            systemUserUnlocked = isSystemUnlocked(parentUserId);
            userIsDemo = userInfo.isDemo();
            storagePermission = mStorageManagerInternal.hasExternalStorage(callingUid,
                    callingPackage);
            ceStorageUnlocked = isCeStorageUnlocked(userId);
+8 −4
Original line number Diff line number Diff line
@@ -272,8 +272,11 @@ public final class StorageSessionController {
     */
    public void onUnlockUser(int userId) throws ExternalStorageServiceException {
        Slog.i(TAG, "On user unlock " + userId);
        if (userId == 0) {
            initExternalStorageServiceComponent();
        if (mExternalStorageServiceComponent == null) {
            final UserInfo info = mUserManager.getUserInfo(userId);
            if (info != null && info.isFull()) {
                initExternalStorageServiceComponent(userId);
            }
        }
    }

@@ -358,7 +361,8 @@ public final class StorageSessionController {
        }
    }

    private void initExternalStorageServiceComponent() throws ExternalStorageServiceException {
    private void initExternalStorageServiceComponent(int userId)
            throws ExternalStorageServiceException {
        Slog.i(TAG, "Initialialising...");
        ProviderInfo provider = mContext.getPackageManager().resolveContentProvider(
                MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
@@ -371,7 +375,7 @@ public final class StorageSessionController {
        mExternalStorageServicePackageName = provider.applicationInfo.packageName;
        mExternalStorageServiceAppId = UserHandle.getAppId(provider.applicationInfo.uid);

        ServiceInfo serviceInfo = resolveExternalStorageServiceAsUser(UserHandle.USER_SYSTEM);
        ServiceInfo serviceInfo = resolveExternalStorageServiceAsUser(userId);
        if (serviceInfo == null) {
            throw new ExternalStorageServiceException(
                    "No valid ExternalStorageService component found");