Loading core/java/android/os/storage/VolumeInfo.java +30 −14 Original line number Original line Diff line number Diff line Loading @@ -56,11 +56,12 @@ import java.util.UUID; * <ul> * <ul> * <li>{@link #MOUNT_FLAG_PRIMARY} means the volume provides primary external * <li>{@link #MOUNT_FLAG_PRIMARY} means the volume provides primary external * storage, historically found at {@code /sdcard}. * storage, historically found at {@code /sdcard}. * <li>{@link #MOUNT_FLAG_VISIBLE} means the volume is visible to third-party * <li>{@link #MOUNT_FLAG_VISIBLE_FOR_READ} and * apps for direct filesystem access. The system should send out relevant * {@link #MOUNT_FLAG_VISIBLE_FOR_WRITE} mean the volume is visible to * storage broadcasts and index any media on visible volumes. Visible volumes * third-party apps for direct filesystem access. The system should send out * are considered a more stable part of the device, which is why we take the * relevant storage broadcasts and index any media on visible volumes. Visible * time to index them. In particular, transient volumes like USB OTG devices * volumes are considered a more stable part of the device, which is why we take * the time to index them. In particular, transient volumes like USB OTG devices * <em>should not</em> be marked as visible; their contents should be surfaced * <em>should not</em> be marked as visible; their contents should be surfaced * to apps through the Storage Access Framework. * to apps through the Storage Access Framework. * </ul> * </ul> Loading Loading @@ -100,7 +101,8 @@ public class VolumeInfo implements Parcelable { public static final int STATE_BAD_REMOVAL = IVold.VOLUME_STATE_BAD_REMOVAL; public static final int STATE_BAD_REMOVAL = IVold.VOLUME_STATE_BAD_REMOVAL; public static final int MOUNT_FLAG_PRIMARY = IVold.MOUNT_FLAG_PRIMARY; public static final int MOUNT_FLAG_PRIMARY = IVold.MOUNT_FLAG_PRIMARY; public static final int MOUNT_FLAG_VISIBLE = IVold.MOUNT_FLAG_VISIBLE; public static final int MOUNT_FLAG_VISIBLE_FOR_READ = IVold.MOUNT_FLAG_VISIBLE_FOR_READ; public static final int MOUNT_FLAG_VISIBLE_FOR_WRITE = IVold.MOUNT_FLAG_VISIBLE_FOR_WRITE; private static SparseArray<String> sStateToEnvironment = new SparseArray<>(); private static SparseArray<String> sStateToEnvironment = new SparseArray<>(); private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>(); private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>(); Loading Loading @@ -312,18 +314,32 @@ public class VolumeInfo implements Parcelable { return isPrimary() && (getType() == TYPE_PUBLIC); return isPrimary() && (getType() == TYPE_PUBLIC); } } private boolean isVisibleForRead() { return (mountFlags & MOUNT_FLAG_VISIBLE_FOR_READ) != 0; } private boolean isVisibleForWrite() { return (mountFlags & MOUNT_FLAG_VISIBLE_FOR_WRITE) != 0; } @UnsupportedAppUsage @UnsupportedAppUsage public boolean isVisible() { public boolean isVisible() { return (mountFlags & MOUNT_FLAG_VISIBLE) != 0; return isVisibleForRead() || isVisibleForWrite(); } } public boolean isVisibleForUser(int userId) { private boolean isVolumeSupportedForUser(int userId) { if ((type == TYPE_PUBLIC || type == TYPE_STUB || type == TYPE_EMULATED) if (mountUserId != userId) { && mountUserId == userId) { return isVisible(); } return false; return false; } } return type == TYPE_PUBLIC || type == TYPE_STUB || type == TYPE_EMULATED; } /** * Returns {@code true} if this volume is visible for {@code userId}, {@code false} otherwise. */ public boolean isVisibleForUser(int userId) { return isVolumeSupportedForUser(userId) && isVisible(); } /** /** * Returns {@code true} if this volume is the primary emulated volume for {@code userId}, * Returns {@code true} if this volume is the primary emulated volume for {@code userId}, Loading @@ -335,12 +351,12 @@ public class VolumeInfo implements Parcelable { } } public boolean isVisibleForRead(int userId) { public boolean isVisibleForRead(int userId) { return isVisibleForUser(userId); return isVolumeSupportedForUser(userId) && isVisibleForRead(); } } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isVisibleForWrite(int userId) { public boolean isVisibleForWrite(int userId) { return isVisibleForUser(userId); return isVolumeSupportedForUser(userId) && isVisibleForWrite(); } } @UnsupportedAppUsage @UnsupportedAppUsage Loading packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -251,7 +251,7 @@ public class ExternalStorageProvider extends FileSystemProvider { if (volume.getType() == VolumeInfo.TYPE_PUBLIC) { if (volume.getType() == VolumeInfo.TYPE_PUBLIC) { root.flags |= Root.FLAG_HAS_SETTINGS; root.flags |= Root.FLAG_HAS_SETTINGS; } } if (volume.isVisibleForRead(userId)) { if (volume.isVisibleForUser(userId)) { root.visiblePath = volume.getPathForUser(userId); root.visiblePath = volume.getPathForUser(userId); } else { } else { root.visiblePath = null; root.visiblePath = null; Loading services/core/java/com/android/server/StorageManagerService.java +8 −8 Original line number Original line Diff line number Diff line Loading @@ -1230,7 +1230,7 @@ class StorageManagerService extends IStorageManager.Stub } } for (int i = 0; i < mVolumes.size(); i++) { for (int i = 0; i < mVolumes.size(); i++) { final VolumeInfo vol = mVolumes.valueAt(i); final VolumeInfo vol = mVolumes.valueAt(i); if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) { if (vol.isVisibleForUser(userId) && vol.isMountedReadable()) { final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); Loading Loading @@ -1558,13 +1558,13 @@ class StorageManagerService extends IStorageManager.Stub && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) { && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) { Slog.v(TAG, "Found primary storage at " + vol); Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) { } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) { Slog.v(TAG, "Found primary storage at " + vol); Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } } Loading @@ -1574,13 +1574,13 @@ class StorageManagerService extends IStorageManager.Stub && vol.disk.isDefaultPrimary()) { && vol.disk.isDefaultPrimary()) { Slog.v(TAG, "Found primary storage at " + vol); Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE; } } // Adoptable public disks are visible to apps, since they meet // Adoptable public disks are visible to apps, since they meet // public API requirement of being in a stable location. // public API requirement of being in a stable location. if (vol.disk.isAdoptable()) { if (vol.disk.isAdoptable()) { vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE; } } vol.mountUserId = mCurrentUserId; vol.mountUserId = mCurrentUserId; Loading @@ -1591,7 +1591,7 @@ class StorageManagerService extends IStorageManager.Stub } else if (vol.type == VolumeInfo.TYPE_STUB) { } else if (vol.type == VolumeInfo.TYPE_STUB) { if (vol.disk.isStubVisible()) { if (vol.disk.isStubVisible()) { vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE; } } vol.mountUserId = mCurrentUserId; vol.mountUserId = mCurrentUserId; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); Loading Loading @@ -1738,7 +1738,7 @@ class StorageManagerService extends IStorageManager.Stub // started after this point will trigger additional // started after this point will trigger additional // user-specific broadcasts. // user-specific broadcasts. for (int userId : mSystemUnlockedUsers) { for (int userId : mSystemUnlockedUsers) { if (vol.isVisibleForRead(userId)) { if (vol.isVisibleForUser(userId)) { final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); false); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); Loading Loading @@ -3766,7 +3766,7 @@ class StorageManagerService extends IStorageManager.Stub if (forWrite) { if (forWrite) { match = vol.isVisibleForWrite(userId); match = vol.isVisibleForWrite(userId); } else { } else { match = vol.isVisibleForRead(userId) match = vol.isVisibleForUser(userId) || (includeInvisible && vol.getPath() != null); || (includeInvisible && vol.getPath() != null); } } if (!match) continue; if (!match) continue; Loading Loading
core/java/android/os/storage/VolumeInfo.java +30 −14 Original line number Original line Diff line number Diff line Loading @@ -56,11 +56,12 @@ import java.util.UUID; * <ul> * <ul> * <li>{@link #MOUNT_FLAG_PRIMARY} means the volume provides primary external * <li>{@link #MOUNT_FLAG_PRIMARY} means the volume provides primary external * storage, historically found at {@code /sdcard}. * storage, historically found at {@code /sdcard}. * <li>{@link #MOUNT_FLAG_VISIBLE} means the volume is visible to third-party * <li>{@link #MOUNT_FLAG_VISIBLE_FOR_READ} and * apps for direct filesystem access. The system should send out relevant * {@link #MOUNT_FLAG_VISIBLE_FOR_WRITE} mean the volume is visible to * storage broadcasts and index any media on visible volumes. Visible volumes * third-party apps for direct filesystem access. The system should send out * are considered a more stable part of the device, which is why we take the * relevant storage broadcasts and index any media on visible volumes. Visible * time to index them. In particular, transient volumes like USB OTG devices * volumes are considered a more stable part of the device, which is why we take * the time to index them. In particular, transient volumes like USB OTG devices * <em>should not</em> be marked as visible; their contents should be surfaced * <em>should not</em> be marked as visible; their contents should be surfaced * to apps through the Storage Access Framework. * to apps through the Storage Access Framework. * </ul> * </ul> Loading Loading @@ -100,7 +101,8 @@ public class VolumeInfo implements Parcelable { public static final int STATE_BAD_REMOVAL = IVold.VOLUME_STATE_BAD_REMOVAL; public static final int STATE_BAD_REMOVAL = IVold.VOLUME_STATE_BAD_REMOVAL; public static final int MOUNT_FLAG_PRIMARY = IVold.MOUNT_FLAG_PRIMARY; public static final int MOUNT_FLAG_PRIMARY = IVold.MOUNT_FLAG_PRIMARY; public static final int MOUNT_FLAG_VISIBLE = IVold.MOUNT_FLAG_VISIBLE; public static final int MOUNT_FLAG_VISIBLE_FOR_READ = IVold.MOUNT_FLAG_VISIBLE_FOR_READ; public static final int MOUNT_FLAG_VISIBLE_FOR_WRITE = IVold.MOUNT_FLAG_VISIBLE_FOR_WRITE; private static SparseArray<String> sStateToEnvironment = new SparseArray<>(); private static SparseArray<String> sStateToEnvironment = new SparseArray<>(); private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>(); private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>(); Loading Loading @@ -312,18 +314,32 @@ public class VolumeInfo implements Parcelable { return isPrimary() && (getType() == TYPE_PUBLIC); return isPrimary() && (getType() == TYPE_PUBLIC); } } private boolean isVisibleForRead() { return (mountFlags & MOUNT_FLAG_VISIBLE_FOR_READ) != 0; } private boolean isVisibleForWrite() { return (mountFlags & MOUNT_FLAG_VISIBLE_FOR_WRITE) != 0; } @UnsupportedAppUsage @UnsupportedAppUsage public boolean isVisible() { public boolean isVisible() { return (mountFlags & MOUNT_FLAG_VISIBLE) != 0; return isVisibleForRead() || isVisibleForWrite(); } } public boolean isVisibleForUser(int userId) { private boolean isVolumeSupportedForUser(int userId) { if ((type == TYPE_PUBLIC || type == TYPE_STUB || type == TYPE_EMULATED) if (mountUserId != userId) { && mountUserId == userId) { return isVisible(); } return false; return false; } } return type == TYPE_PUBLIC || type == TYPE_STUB || type == TYPE_EMULATED; } /** * Returns {@code true} if this volume is visible for {@code userId}, {@code false} otherwise. */ public boolean isVisibleForUser(int userId) { return isVolumeSupportedForUser(userId) && isVisible(); } /** /** * Returns {@code true} if this volume is the primary emulated volume for {@code userId}, * Returns {@code true} if this volume is the primary emulated volume for {@code userId}, Loading @@ -335,12 +351,12 @@ public class VolumeInfo implements Parcelable { } } public boolean isVisibleForRead(int userId) { public boolean isVisibleForRead(int userId) { return isVisibleForUser(userId); return isVolumeSupportedForUser(userId) && isVisibleForRead(); } } @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isVisibleForWrite(int userId) { public boolean isVisibleForWrite(int userId) { return isVisibleForUser(userId); return isVolumeSupportedForUser(userId) && isVisibleForWrite(); } } @UnsupportedAppUsage @UnsupportedAppUsage Loading
packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -251,7 +251,7 @@ public class ExternalStorageProvider extends FileSystemProvider { if (volume.getType() == VolumeInfo.TYPE_PUBLIC) { if (volume.getType() == VolumeInfo.TYPE_PUBLIC) { root.flags |= Root.FLAG_HAS_SETTINGS; root.flags |= Root.FLAG_HAS_SETTINGS; } } if (volume.isVisibleForRead(userId)) { if (volume.isVisibleForUser(userId)) { root.visiblePath = volume.getPathForUser(userId); root.visiblePath = volume.getPathForUser(userId); } else { } else { root.visiblePath = null; root.visiblePath = null; Loading
services/core/java/com/android/server/StorageManagerService.java +8 −8 Original line number Original line Diff line number Diff line Loading @@ -1230,7 +1230,7 @@ class StorageManagerService extends IStorageManager.Stub } } for (int i = 0; i < mVolumes.size(); i++) { for (int i = 0; i < mVolumes.size(); i++) { final VolumeInfo vol = mVolumes.valueAt(i); final VolumeInfo vol = mVolumes.valueAt(i); if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) { if (vol.isVisibleForUser(userId) && vol.isMountedReadable()) { final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); Loading Loading @@ -1558,13 +1558,13 @@ class StorageManagerService extends IStorageManager.Stub && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) { && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) { Slog.v(TAG, "Found primary storage at " + vol); Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) { } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) { Slog.v(TAG, "Found primary storage at " + vol); Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); } } Loading @@ -1574,13 +1574,13 @@ class StorageManagerService extends IStorageManager.Stub && vol.disk.isDefaultPrimary()) { && vol.disk.isDefaultPrimary()) { Slog.v(TAG, "Found primary storage at " + vol); Slog.v(TAG, "Found primary storage at " + vol); vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE; } } // Adoptable public disks are visible to apps, since they meet // Adoptable public disks are visible to apps, since they meet // public API requirement of being in a stable location. // public API requirement of being in a stable location. if (vol.disk.isAdoptable()) { if (vol.disk.isAdoptable()) { vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE; } } vol.mountUserId = mCurrentUserId; vol.mountUserId = mCurrentUserId; Loading @@ -1591,7 +1591,7 @@ class StorageManagerService extends IStorageManager.Stub } else if (vol.type == VolumeInfo.TYPE_STUB) { } else if (vol.type == VolumeInfo.TYPE_STUB) { if (vol.disk.isStubVisible()) { if (vol.disk.isStubVisible()) { vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE; vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE; } } vol.mountUserId = mCurrentUserId; vol.mountUserId = mCurrentUserId; mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget(); Loading Loading @@ -1738,7 +1738,7 @@ class StorageManagerService extends IStorageManager.Stub // started after this point will trigger additional // started after this point will trigger additional // user-specific broadcasts. // user-specific broadcasts. for (int userId : mSystemUnlockedUsers) { for (int userId : mSystemUnlockedUsers) { if (vol.isVisibleForRead(userId)) { if (vol.isVisibleForUser(userId)) { final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false); false); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget(); Loading Loading @@ -3766,7 +3766,7 @@ class StorageManagerService extends IStorageManager.Stub if (forWrite) { if (forWrite) { match = vol.isVisibleForWrite(userId); match = vol.isVisibleForWrite(userId); } else { } else { match = vol.isVisibleForRead(userId) match = vol.isVisibleForUser(userId) || (includeInvisible && vol.getPath() != null); || (includeInvisible && vol.getPath() != null); } } if (!match) continue; if (!match) continue; Loading