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

Commit bcaac0ad authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Surface outgoing Uri permission grants.

This enables apps to discover and clean up persisted Uri grants when
the underlying Uri becomes invalid, such as when an account is
removed.

Bug: 11142566
Change-Id: Ieeb36cb1155acf226327ebe91cdd30b822d69d1b
parent e6d419de
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5759,6 +5759,7 @@ package android.content {
    method public static java.util.List<android.content.SyncInfo> getCurrentSyncs();
    method public static int getIsSyncable(android.accounts.Account, java.lang.String);
    method public static boolean getMasterSyncAutomatically();
    method public java.util.List<android.content.UriPermission> getOutgoingPersistedUriPermissions();
    method public static java.util.List<android.content.PeriodicSync> getPeriodicSyncs(android.accounts.Account, java.lang.String);
    method public java.util.List<android.content.UriPermission> getPersistedUriPermissions();
    method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String);
+8 −2
Original line number Diff line number Diff line
@@ -1160,7 +1160,10 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM

        case GET_PERSISTED_URI_PERMISSIONS_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            final ParceledListSlice<UriPermission> perms = getPersistedUriPermissions();
            final String packageName = data.readString();
            final boolean incoming = data.readInt() != 0;
            final ParceledListSlice<UriPermission> perms = getPersistedUriPermissions(
                    packageName, incoming);
            reply.writeNoException();
            perms.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
            return true;
@@ -3500,10 +3503,13 @@ class ActivityManagerProxy implements IActivityManager
    }

    @Override
    public ParceledListSlice<UriPermission> getPersistedUriPermissions() throws RemoteException {
    public ParceledListSlice<UriPermission> getPersistedUriPermissions(
            String packageName, boolean incoming) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeString(packageName);
        data.writeInt(incoming ? 1 : 0);
        mRemote.transact(GET_PERSISTED_URI_PERMISSIONS_TRANSACTION, data, reply, 0);
        reply.readException();
        final ParceledListSlice<UriPermission> perms = ParceledListSlice.CREATOR.createFromParcel(
+2 −1
Original line number Diff line number Diff line
@@ -215,7 +215,8 @@ public interface IActivityManager extends IInterface {
            int mode) throws RemoteException;
    public void takePersistableUriPermission(Uri uri, int modeFlags) throws RemoteException;
    public void releasePersistableUriPermission(Uri uri, int modeFlags) throws RemoteException;
    public ParceledListSlice<UriPermission> getPersistedUriPermissions() throws RemoteException;
    public ParceledListSlice<UriPermission> getPersistedUriPermissions(
            String packageName, boolean incoming) throws RemoteException;

    public void showWaitingForDebugger(IApplicationThread who, boolean waiting)
            throws RemoteException;
+20 −3
Original line number Diff line number Diff line
@@ -1659,8 +1659,9 @@ public abstract class ContentResolver {
    }

    /**
     * Return list of all Uri permission grants that have been persisted for the
     * calling app. Only persistable grants taken with
     * Return list of all Uri permission grants that have been persisted by the
     * calling app. That is, the returned permissions have been granted
     * <em>to</em> the calling app. Only persistable grants taken with
     * {@link #takePersistableUriPermission(Uri, int)} are returned.
     *
     * @see #takePersistableUriPermission(Uri, int)
@@ -1668,7 +1669,23 @@ public abstract class ContentResolver {
     */
    public List<UriPermission> getPersistedUriPermissions() {
        try {
            return ActivityManagerNative.getDefault().getPersistedUriPermissions().getList();
            return ActivityManagerNative.getDefault()
                    .getPersistedUriPermissions(mPackageName, true).getList();
        } catch (RemoteException e) {
            throw new RuntimeException("Activity manager has died", e);
        }
    }

    /**
     * Return list of all persisted Uri permission grants that are hosted by the
     * calling app. That is, the returned permissions have been granted
     * <em>from</em> the calling app. Only grants taken with
     * {@link #takePersistableUriPermission(Uri, int)} are returned.
     */
    public List<UriPermission> getOutgoingPersistedUriPermissions() {
        try {
            return ActivityManagerNative.getDefault()
                    .getPersistedUriPermissions(mPackageName, false).getList();
        } catch (RemoteException e) {
            throw new RuntimeException("Activity manager has died", e);
        }
+38 −11
Original line number Diff line number Diff line
@@ -6489,27 +6489,54 @@ public final class ActivityManagerService extends ActivityManagerNative
    }
    @Override
    public ParceledListSlice<android.content.UriPermission> getPersistedUriPermissions() {
    public ParceledListSlice<android.content.UriPermission> getPersistedUriPermissions(
            String packageName, boolean incoming) {
        enforceNotIsolatedCaller("getPersistedUriPermissions");
        Preconditions.checkNotNull(packageName, "packageName");
        synchronized (this) {
        final int callingUid = Binder.getCallingUid();
        final IPackageManager pm = AppGlobals.getPackageManager();
        try {
            final int packageUid = pm.getPackageUid(packageName, UserHandle.getUserId(callingUid));
            if (packageUid != callingUid) {
                throw new SecurityException(
                        "Package " + packageName + " does not belong to calling UID " + callingUid);
            }
        } catch (RemoteException e) {
            throw new SecurityException("Failed to verify package name ownership");
        }
        final ArrayList<android.content.UriPermission> result = Lists.newArrayList();
        synchronized (this) {
            if (incoming) {
                final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
                if (perms == null) {
                Slog.w(TAG, "No permission grants found for UID " + callingUid);
                    Slog.w(TAG, "No permission grants found for " + packageName);
                } else {
                    final int size = perms.size();
                    for (int i = 0; i < size; i++) {
                        final UriPermission perm = perms.valueAt(i);
                    if (perm.persistedModeFlags != 0) {
                        if (packageName.equals(perm.targetPkg) && perm.persistedModeFlags != 0) {
                            result.add(perm.buildPersistedPublicApiObject());
                        }
                    }
                }
            return new ParceledListSlice<android.content.UriPermission>(result);
            } else {
                final int size = mGrantedUriPermissions.size();
                for (int i = 0; i < size; i++) {
                    final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
                    final int permsSize = perms.size();
                    for (int j = 0; j < permsSize; j++) {
                        final UriPermission perm = perms.valueAt(j);
                        if (packageName.equals(perm.sourcePkg) && perm.persistedModeFlags != 0) {
                            result.add(perm.buildPersistedPublicApiObject());
                        }
                    }
                }
            }
        }
        return new ParceledListSlice<android.content.UriPermission>(result);
    }
    @Override
    public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
Loading