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

Commit 00049d6d authored by Sailendra Bathi's avatar Sailendra Bathi Committed by Android (Google) Code Review
Browse files

Merge changes from topic "bug209973853_ 213658045"

* changes:
  Make StorageVolume#getOwner public
  Add API getStorageVolumesIncludingSharedProfiles()
parents a1ab74c7 1f381502
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -32416,6 +32416,7 @@ package android.os.storage {
    method @Nullable public android.os.storage.StorageVolume getStorageVolume(@NonNull java.io.File);
    method @NonNull public android.os.storage.StorageVolume getStorageVolume(@NonNull android.net.Uri);
    method @NonNull public java.util.List<android.os.storage.StorageVolume> getStorageVolumes();
    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_EXTERNAL_STORAGE) public java.util.List<android.os.storage.StorageVolume> getStorageVolumesIncludingSharedProfiles();
    method @NonNull public java.util.UUID getUuidForPath(@NonNull java.io.File) throws java.io.IOException;
    method public boolean isAllocationSupported(@NonNull java.io.FileDescriptor);
    method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException;
@@ -32449,6 +32450,7 @@ package android.os.storage {
    method public String getDescription(android.content.Context);
    method @Nullable public java.io.File getDirectory();
    method @Nullable public String getMediaStoreVolumeName();
    method @NonNull public android.os.UserHandle getOwner();
    method public String getState();
    method @Nullable public java.util.UUID getStorageUuid();
    method @Nullable public String getUuid();
+0 −4
Original line number Diff line number Diff line
@@ -541,10 +541,6 @@ package android.os.storage {
    field public static final int APP_IO_BLOCKED_REASON_UNKNOWN = 0; // 0x0
  }

  public final class StorageVolume implements android.os.Parcelable {
    method @NonNull public android.os.UserHandle getOwner();
  }

}

package android.provider {
+19 −0
Original line number Diff line number Diff line
@@ -291,6 +291,8 @@ public class StorageManager {
    public static final int FLAG_INCLUDE_INVISIBLE = 1 << 10;
    /** {@hide} */
    public static final int FLAG_INCLUDE_RECENT = 1 << 11;
    /** {@hide} */
    public static final int FLAG_INCLUDE_SHARED_PROFILE = 1 << 12;

    /** {@hide} */
    public static final int FSTRIM_FLAG_DEEP = IVold.FSTRIM_FLAG_DEEP_TRIM;
@@ -1327,6 +1329,23 @@ public class StorageManager {
        return res;
    }

    /**
     * Return the list of shared/external storage volumes currently available to
     * the calling user and the user it shares media with
     * CDD link : https://source.android.com/compatibility/12/android-12-cdd#95_multi-user_support
     * <p>
     * This is similar to {@link StorageManager#getStorageVolumes()} except that the result also
     * includes the volumes belonging to any user it shares media with
     */
    @RequiresPermission(android.Manifest.permission.MANAGE_EXTERNAL_STORAGE)
    public @NonNull List<StorageVolume> getStorageVolumesIncludingSharedProfiles() {
        final ArrayList<StorageVolume> res = new ArrayList<>();
        Collections.addAll(res,
                getVolumeList(mContext.getUserId(),
                        FLAG_REAL_STATE | FLAG_INCLUDE_INVISIBLE | FLAG_INCLUDE_SHARED_PROFILE));
        return res;
    }

    /**
     * Return the list of shared/external storage volumes both currently and
     * recently available to the calling user.
+2 −6
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package android.os.storage;

import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
@@ -308,11 +306,9 @@ public final class StorageVolume implements Parcelable {

    /**
     * Returns the user that owns this volume
     *
     * {@hide}
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    @SystemApi(client = MODULE_LIBRARIES)
    // TODO(b/193460475) : Android Lint handle API change from systemApi to public Api incorrectly
    @SuppressLint("NewApi")
    public @NonNull UserHandle getOwner() {
        return mOwner;
    }
+57 −4
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ import android.provider.DocumentsContract;
import android.provider.Downloads;
import android.provider.MediaStore;
import android.provider.Settings;
import android.service.storage.ExternalStorageService;
import android.sysprop.VoldProperties;
import android.text.TextUtils;
import android.text.format.DateUtils;
@@ -491,6 +492,8 @@ class StorageManagerService extends IStorageManager.Stub
    @GuardedBy("mAppFuseLock")
    private AppFuseBridge mAppFuseBridge = null;

    private HashMap<Integer, Integer> mUserSharesMediaWith = new HashMap<>();

    /** Matches known application dir paths. The first group contains the generic part of the path,
     * the second group contains the user id (or null if it's a public volume without users), the
     * third group contains the package name, and the fourth group the remainder of the path.
@@ -1235,6 +1238,21 @@ class StorageManagerService extends IStorageManager.Stub
    private void onUnlockUser(int userId) {
        Slog.d(TAG, "onUnlockUser " + userId);

        if (userId != UserHandle.USER_SYSTEM) {
            // Check if this user shares media with another user
            try {
                Context userContext = mContext.createPackageContextAsUser("system", 0,
                        UserHandle.of(userId));
                UserManager um = userContext.getSystemService(UserManager.class);
                if (um != null && um.isMediaSharedWithParent()) {
                    int parentUserId = um.getProfileParent(userId).id;
                    mUserSharesMediaWith.put(userId, parentUserId);
                    mUserSharesMediaWith.put(parentUserId, userId);
                }
            } catch (PackageManager.NameNotFoundException e) {
                Log.e(TAG, "Failed to create user context for user " + userId);
            }
        }
        // We purposefully block here to make sure that user-specific
        // staging area is ready so it's ready for zygote-forked apps to
        // bind mount against.
@@ -3971,6 +3989,29 @@ class StorageManagerService extends IStorageManager.Stub
        final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
        final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
        final boolean includeRecent = (flags & StorageManager.FLAG_INCLUDE_RECENT) != 0;
        final boolean includeSharedProfile =
                (flags & StorageManager.FLAG_INCLUDE_SHARED_PROFILE) != 0;

        // Only Apps with MANAGE_EXTERNAL_STORAGE should call the API with includeSharedProfile
        if (includeSharedProfile) {
            try {
                // Get package name for calling app and
                // verify it has MANAGE_EXTERNAL_STORAGE permission
                final String[] packagesFromUid = mIPackageManager.getPackagesForUid(callingUid);
                if (packagesFromUid == null) {
                    throw new SecurityException("Unknown uid " + callingUid);
                }
                // Checking first entry in packagesFromUid is enough as using "sharedUserId"
                // mechanism is rare and discouraged. Also, Apps that share same UID share the same
                // permissions.
                if (!mStorageManagerInternal.hasExternalStorageAccess(callingUid,
                        packagesFromUid[0])) {
                    throw new SecurityException("Only File Manager Apps permitted");
                }
            } catch (RemoteException re) {
                throw new SecurityException("Unknown uid " + callingUid, re);
            }
        }

        // Report all volumes as unmounted until we've recorded that user 0 has unlocked. There
        // are no guarantees that callers will see a consistent view of the volume before that
@@ -4002,6 +4043,7 @@ class StorageManagerService extends IStorageManager.Stub

        final ArrayList<StorageVolume> res = new ArrayList<>();
        final ArraySet<String> resUuids = new ArraySet<>();
        final int userIdSharingMedia = mUserSharesMediaWith.getOrDefault(userId, -1);
        synchronized (mLock) {
            for (int i = 0; i < mVolumes.size(); i++) {
                final String volId = mVolumes.keyAt(i);
@@ -4014,6 +4056,11 @@ class StorageManagerService extends IStorageManager.Stub
                        if (vol.getMountUserId() == userId) {
                            break;
                        }
                        if (includeSharedProfile && vol.getMountUserId() == userIdSharingMedia) {
                            // If the volume belongs to a user we share media with,
                            // return it too.
                            break;
                        }
                        // Skip if emulated volume not for userId
                    default:
                        continue;
@@ -4021,10 +4068,12 @@ class StorageManagerService extends IStorageManager.Stub

                boolean match = false;
                if (forWrite) {
                    match = vol.isVisibleForWrite(userId);
                    match = vol.isVisibleForWrite(userId)
                            || (includeSharedProfile && vol.isVisibleForWrite(userIdSharingMedia));
                } else {
                    match = vol.isVisibleForUser(userId)
                            || (includeInvisible && vol.getPath() != null);
                            || (includeInvisible && vol.getPath() != null)
                            || (includeSharedProfile && vol.isVisibleForRead(userIdSharingMedia));
                }
                if (!match) continue;

@@ -4045,9 +4094,13 @@ class StorageManagerService extends IStorageManager.Stub
                    reportUnmounted = true;
                }

                final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
                int volUserId = userId;
                if (volUserId != vol.getMountUserId() && vol.getMountUserId() >= 0) {
                    volUserId = vol.getMountUserId();
                }
                final StorageVolume userVol = vol.buildStorageVolume(mContext, volUserId,
                        reportUnmounted);
                if (vol.isPrimary()) {
                if (vol.isPrimary() && vol.getMountUserId() == userId) {
                    res.add(0, userVol);
                    foundPrimary = true;
                } else {