From 94346f2b2f38e58c1e93ad23f39182e0c0e12c4a Mon Sep 17 00:00:00 2001 From: Robert Horvath Date: Thu, 1 Jul 2021 12:09:18 +0200 Subject: [PATCH] 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 --- .../android/server/StorageManagerService.java | 18 ++++++------ .../storage/StorageSessionController.java | 28 +++++++++++++++---- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index ec2f4aa821e27..ab6b8a21ee88e 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -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; diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java index 8d79a81fe11eb..0b34eb8234f0b 100644 --- a/services/core/java/com/android/server/storage/StorageSessionController.java +++ b/services/core/java/com/android/server/storage/StorageSessionController.java @@ -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; + } }