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

Commit 655f1a45 authored by Dmitrii Merkurev's avatar Dmitrii Merkurev
Browse files

Currently, Uri Permissions read/write grants are modified/accessed from...

Currently, Uri Permissions read/write grants  are modified/accessed from different parts across the system:

* `UriGrantsManagerService.revokeUriPermissionFromOwner` (which is using `owner.removeUriPermission` (iterating over all read/write permissions for owner) without locking)

* `UriGrantsManagerService.grantUriPermissionUnchecked` (which is using `UriPermission.grantModes` (adding new read/write permissions for owner) without any locking)

* `UriGrantsManagerService.removeUriPermissionsForPackageLocked` and `UriGrantsManagerService.revokeUriPermissionLocked` (which is using `UriPermission.revokeModes` (removing read/write permissions for owner) with main UriGrantsManagerService lock)

* `WindowManager` and `ActivityManager` (that using `removeUriPermissions` directly (iterating over all read/write permissions for owner) without any locking)

Introduce synchronization for this part of the system.

Bug: 213993781
Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/uri/
Change-Id: Idbe02e53e2b4c9fcb02d6e22dc92480d711c7779
parent 71f72f13
Loading
Loading
Loading
Loading
+82 −58
Original line number Diff line number Diff line
@@ -30,7 +30,9 @@ import com.android.server.am.UriPermissionOwnerProto;
import com.google.android.collect.Sets;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class UriPermissionOwner {
    private final UriGrantsManagerInternal mService;
@@ -79,10 +81,13 @@ public class UriPermissionOwner {
    }

    void removeUriPermission(GrantUri grantUri, int mode, String targetPgk, int targetUserId) {
        final List<UriPermission> permissionsToRemove = new ArrayList<>();

        synchronized (this) {
            if ((mode & FLAG_GRANT_READ_URI_PERMISSION) != 0 && mReadPerms != null) {
            Iterator<UriPermission> it = mReadPerms.iterator();
                final Iterator<UriPermission> it = mReadPerms.iterator();
                while (it.hasNext()) {
                UriPermission perm = it.next();
                    final UriPermission perm = it.next();
                    if (grantUri != null && !grantUri.equals(perm.uri)) {
                        continue;
                    }
@@ -92,18 +97,19 @@ public class UriPermissionOwner {
                    if (targetUserId != UserHandle.USER_ALL && targetUserId != perm.targetUserId) {
                        continue;
                    }
                    permissionsToRemove.add(perm);
                    perm.removeReadOwner(this);
                mService.removeUriPermissionIfNeeded(perm);
                    it.remove();
                }
                if (mReadPerms.isEmpty()) {
                    mReadPerms = null;
                }
            }

            if ((mode & FLAG_GRANT_WRITE_URI_PERMISSION) != 0 && mWritePerms != null) {
            Iterator<UriPermission> it = mWritePerms.iterator();
                final Iterator<UriPermission> it = mWritePerms.iterator();
                while (it.hasNext()) {
                UriPermission perm = it.next();
                    final UriPermission perm = it.next();
                    if (grantUri != null && !grantUri.equals(perm.uri)) {
                        continue;
                    }
@@ -113,8 +119,8 @@ public class UriPermissionOwner {
                    if (targetUserId != UserHandle.USER_ALL && targetUserId != perm.targetUserId) {
                        continue;
                    }
                    permissionsToRemove.add(perm);
                    perm.removeWriteOwner(this);
                mService.removeUriPermissionIfNeeded(perm);
                    it.remove();
                }
                if (mWritePerms.isEmpty()) {
@@ -123,55 +129,73 @@ public class UriPermissionOwner {
            }
        }

        final int permissionsToRemoveSize = permissionsToRemove.size();
        for (int i = 0; i < permissionsToRemoveSize; i++) {
            mService.removeUriPermissionIfNeeded(permissionsToRemove.get(i));
        }
    }

    public void addReadPermission(UriPermission perm) {
        synchronized (this) {
            if (mReadPerms == null) {
                mReadPerms = Sets.newArraySet();
            }
            mReadPerms.add(perm);
        }
    }

    public void addWritePermission(UriPermission perm) {
        synchronized (this) {
            if (mWritePerms == null) {
                mWritePerms = Sets.newArraySet();
            }
            mWritePerms.add(perm);
        }
    }

    public void removeReadPermission(UriPermission perm) {
        synchronized (this) {
            mReadPerms.remove(perm);
            if (mReadPerms.isEmpty()) {
                mReadPerms = null;
            }
        }
    }

    public void removeWritePermission(UriPermission perm) {
        synchronized (this) {
            mWritePerms.remove(perm);
            if (mWritePerms.isEmpty()) {
                mWritePerms = null;
            }
        }
    }

    public void dump(PrintWriter pw, String prefix) {
        synchronized (this) {
            if (mReadPerms != null) {
            pw.print(prefix); pw.print("readUriPermissions="); pw.println(mReadPerms);
                pw.print(prefix);
                pw.print("readUriPermissions=");
                pw.println(mReadPerms);
            }
            if (mWritePerms != null) {
            pw.print(prefix); pw.print("writeUriPermissions="); pw.println(mWritePerms);
                pw.print(prefix);
                pw.print("writeUriPermissions=");
                pw.println(mWritePerms);
            }
        }
    }

    public void dumpDebug(ProtoOutputStream proto, long fieldId) {
        long token = proto.start(fieldId);
        proto.write(UriPermissionOwnerProto.OWNER, mOwner.toString());
        synchronized (this) {
            if (mReadPerms != null) {
            synchronized (mReadPerms) {
                for (UriPermission p : mReadPerms) {
                    p.uri.dumpDebug(proto, UriPermissionOwnerProto.READ_PERMS);
                }
            }
        }
            if (mWritePerms != null) {
            synchronized (mWritePerms) {
                for (UriPermission p : mWritePerms) {
                    p.uri.dumpDebug(proto, UriPermissionOwnerProto.WRITE_PERMS);
                }