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

Commit 94346f2b authored by Robert Horvath's avatar Robert Horvath
Browse files

Skip storage sessions for users without ExternalStorageService

When a volume is mounted, StorageSessionController currently attempts to
bind to the ExternalStorageService to create a storage session.
If a user does not provide an ExternalStorageService (ie. does not have
com.android.providers.media.module installed), binding to the service
and creating the session for that user fails, an
ExternalStorageServiceException is thrown and StorageManagerService
resets.
After the reset, it retries mounting volumes for each user, so
ExternalStorageServiceException is thrown repeatedly,
and android.intent.action.MEDIA_MOUNTED is broadcast
for users where mounting succeeds repeatedly.

With this change, mounting emulated volumes is skipped if the target
user does not provide an ExternalStorageService, skipping creating the
FUSE volume and the attempt to bind to the ExternalStorageService to
create a storage session.

Bug: 188080785
Test: Create profile without com.android.providers.media.module,
      verify volume ignored for profile,
      no ExternalStorageServiceException thrown,
      android.intent.action.MEDIA_MOUNTED not repeatedly broadcast.
      Verify no change if package is installed in user.
Test: atest AdoptableHostTest
Change-Id: Iaedef3e49655bc5456e6149b634cddc875668fc8
parent acd597a5
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -1541,17 +1541,19 @@ class StorageManagerService extends IStorageManager.Stub
        }

        if (vol.type == VolumeInfo.TYPE_EMULATED) {
            if (!mStorageSessionController.supportsExternalStorage(vol.mountUserId)) {
                Slog.d(TAG, "Ignoring volume " + vol.getId() + " because user "
                        + Integer.toString(vol.mountUserId)
                        + " does not support external storage.");
                return;
            }

            final StorageManager storage = mContext.getSystemService(StorageManager.class);
            final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);

            if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
                    && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
                Slog.v(TAG, "Found primary storage at " + vol);
                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
                mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();

            } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
            if ((Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
                    && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id))
                    || Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
                Slog.v(TAG, "Found primary storage at " + vol);
                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
+22 −6
Original line number Diff line number Diff line
@@ -368,16 +368,12 @@ public final class StorageSessionController {
        mExternalStorageServicePackageName = provider.applicationInfo.packageName;
        mExternalStorageServiceAppId = UserHandle.getAppId(provider.applicationInfo.uid);

        Intent intent = new Intent(ExternalStorageService.SERVICE_INTERFACE);
        intent.setPackage(mExternalStorageServicePackageName);
        ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent,
                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
        if (resolveInfo == null || resolveInfo.serviceInfo == null) {
        ServiceInfo serviceInfo = resolveExternalStorageServiceAsUser(UserHandle.USER_SYSTEM);
        if (serviceInfo == null) {
            throw new ExternalStorageServiceException(
                    "No valid ExternalStorageService component found");
        }

        ServiceInfo serviceInfo = resolveInfo.serviceInfo;
        ComponentName name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
        if (!Manifest.permission.BIND_EXTERNAL_STORAGE_SERVICE
                .equals(serviceInfo.permission)) {
@@ -490,4 +486,24 @@ public final class StorageSessionController {
    private boolean shouldHandle(@Nullable VolumeInfo vol) {
        return !mIsResetting && (vol == null || isSupportedVolume(vol));
    }

    /**
     * Returns {@code true} if the given user supports external storage,
     * {@code false} otherwise.
     */
    public boolean supportsExternalStorage(int userId) {
        return resolveExternalStorageServiceAsUser(userId) != null;
    }

    private ServiceInfo resolveExternalStorageServiceAsUser(int userId) {
        Intent intent = new Intent(ExternalStorageService.SERVICE_INTERFACE);
        intent.setPackage(mExternalStorageServicePackageName);
        ResolveInfo resolveInfo = mContext.getPackageManager().resolveServiceAsUser(intent,
                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, userId);
        if (resolveInfo == null) {
            return null;
        }

        return resolveInfo.serviceInfo;
    }
}