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

Commit 6ebcfe31 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Revert "Slices permission model""

parents 6e3be007 1214c878
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -29,6 +29,4 @@ interface ISliceManager {
    void unpinSlice(String pkg, in Uri uri);
    boolean hasSliceAccess(String pkg);
    SliceSpec[] getPinnedSpecs(in Uri uri, String pkg);
    int checkSlicePermission(in Uri uri, String pkg, int pid, int uid);
    void grantPermissionFromUser(in Uri uri, String pkg, String callingPkg, boolean allSlices);
}
+0 −7
Original line number Diff line number Diff line
@@ -155,13 +155,6 @@ public final class Slice implements Parcelable {
     * content associated with this slice.
     */
    public static final String HINT_SEE_MORE = "see_more";
    /**
     * A hint to tell the system that this slice cares about the return value of
     * {@link SliceProvider#getBindingPackage} and should not cache the result
     * for multiple apps.
     * @hide
     */
    public static final String HINT_CALLER_NEEDED = "caller_needed";
    /**
     * Key to retrieve an extra added to an intent when a control is changed.
     */
+2 −63
Original line number Diff line number Diff line
@@ -53,33 +53,11 @@ public class SliceManager {

    private static final String TAG = "SliceManager";

    /**
     * @hide
     */
    public static final String ACTION_REQUEST_SLICE_PERMISSION =
            "android.intent.action.REQUEST_SLICE_PERMISSION";

    private final ISliceManager mService;
    private final Context mContext;
    private final ArrayMap<Pair<Uri, SliceCallback>, ISliceListener> mListenerLookup =
            new ArrayMap<>();

    /**
     * Permission denied.
     * @hide
     */
    public static final int PERMISSION_DENIED = -1;
    /**
     * Permission granted.
     * @hide
     */
    public static final int PERMISSION_GRANTED = 0;
    /**
     * Permission just granted by the user, and should be granted uri permission as well.
     * @hide
     */
    public static final int PERMISSION_USER_GRANTED = 1;

    /**
     * @hide
     */
@@ -306,7 +284,7 @@ public class SliceManager {
            extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
            extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS,
                    new ArrayList<>(supportedSpecs));
            final Bundle res = provider.call(mContext.getPackageName(), SliceProvider.METHOD_SLICE,
            final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_SLICE,
                    null, extras);
            Bundle.setDefusable(res, true);
            if (res == null) {
@@ -364,7 +342,7 @@ public class SliceManager {
            extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
            extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS,
                    new ArrayList<>(supportedSpecs));
            final Bundle res = provider.call(mContext.getPackageName(),
            final Bundle res = provider.call(resolver.getPackageName(),
                    SliceProvider.METHOD_MAP_INTENT, null, extras);
            if (res == null) {
                return null;
@@ -379,45 +357,6 @@ public class SliceManager {
        }
    }

    /**
     * Does the permission check to see if a caller has access to a specific slice.
     * @hide
     */
    public void enforceSlicePermission(Uri uri, String pkg, int pid, int uid) {
        try {
            if (pkg == null) {
                throw new SecurityException("No pkg specified");
            }
            int result = mService.checkSlicePermission(uri, pkg, pid, uid);
            if (result == PERMISSION_DENIED) {
                throw new SecurityException("User " + uid + " does not have slice permission for "
                        + uri + ".");
            }
            if (result == PERMISSION_USER_GRANTED) {
                // We just had a user grant of this permission and need to grant this to the app
                // permanently.
                mContext.grantUriPermission(pkg, uri.buildUpon().path("").build(),
                        Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
                                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                                | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Called by SystemUI to grant a slice permission after a dialog is shown.
     * @hide
     */
    public void grantPermissionFromUser(Uri uri, String pkg, boolean allSlices) {
        try {
            mService.grantPermissionFromUser(uri, pkg, mContext.getPackageName(), allSlices);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Class that listens to changes in {@link Slice}s.
     */
+25 −120
Original line number Diff line number Diff line
@@ -15,19 +15,13 @@
 */
package android.app.slice;

import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ProviderInfo;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
@@ -135,41 +129,9 @@ public abstract class SliceProvider extends ContentProvider {
     * @hide
     */
    public static final String EXTRA_SLICE_DESCENDANTS = "slice_descendants";
    /**
     * @hide
     */
    public static final String EXTRA_PKG = "pkg";
    /**
     * @hide
     */
    public static final String EXTRA_PROVIDER_PKG = "provider_pkg";
    /**
     * @hide
     */
    public static final String EXTRA_OVERRIDE_PKG = "override_pkg";

    private static final boolean DEBUG = false;

    private String mBindingPkg;
    private SliceManager mSliceManager;

    /**
     * Return the package name of the caller that initiated the binding request
     * currently happening. The returned package will have been
     * verified to belong to the calling UID. Returns {@code null} if not
     * currently performing an {@link #onBindSlice(Uri, List)}.
     * @hide
     */
    public final @Nullable String getBindingPackage() {
        return mBindingPkg;
    }

    @Override
    public void attachInfo(Context context, ProviderInfo info) {
        super.attachInfo(context, info);
        mSliceManager = context.getSystemService(SliceManager.class);
    }

    /**
     * Implemented to create a slice. Will be called on the main thread.
     * <p>
@@ -300,27 +262,28 @@ public abstract class SliceProvider extends ContentProvider {
    public Bundle call(String method, String arg, Bundle extras) {
        if (method.equals(METHOD_SLICE)) {
            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
            if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.myUid())) {
                getContext().enforceUriPermission(uri, permission.BIND_SLICE,
                        permission.BIND_SLICE, Binder.getCallingPid(), Binder.getCallingUid(),
                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
                        "Slice binding requires the permission BIND_SLICE");
            }
            List<SliceSpec> supportedSpecs = extras.getParcelableArrayList(EXTRA_SUPPORTED_SPECS);

            String callingPackage = getCallingPackage();
            if (extras.containsKey(EXTRA_OVERRIDE_PKG)) {
                if (Binder.getCallingUid() != Process.SYSTEM_UID) {
                    throw new SecurityException("Only the system can override calling pkg");
                }
                callingPackage = extras.getString(EXTRA_OVERRIDE_PKG);
            }
            Slice s = handleBindSlice(uri, supportedSpecs, callingPackage);
            Slice s = handleBindSlice(uri, supportedSpecs);
            Bundle b = new Bundle();
            b.putParcelable(EXTRA_SLICE, s);
            return b;
        } else if (method.equals(METHOD_MAP_INTENT)) {
            getContext().enforceCallingPermission(permission.BIND_SLICE,
                    "Slice binding requires the permission BIND_SLICE");
            Intent intent = extras.getParcelable(EXTRA_INTENT);
            if (intent == null) return null;
            Uri uri = onMapIntentToUri(intent);
            List<SliceSpec> supportedSpecs = extras.getParcelableArrayList(EXTRA_SUPPORTED_SPECS);
            Bundle b = new Bundle();
            if (uri != null) {
                Slice s = handleBindSlice(uri, supportedSpecs, getCallingPackage());
                Slice s = handleBindSlice(uri, supportedSpecs);
                b.putParcelable(EXTRA_SLICE, s);
            } else {
                b.putParcelable(EXTRA_SLICE, null);
@@ -328,14 +291,20 @@ public abstract class SliceProvider extends ContentProvider {
            return b;
        } else if (method.equals(METHOD_PIN)) {
            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
                throw new SecurityException("Only the system can pin/unpin slices");
            if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.myUid())) {
                getContext().enforceUriPermission(uri, permission.BIND_SLICE,
                        permission.BIND_SLICE, Binder.getCallingPid(), Binder.getCallingUid(),
                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
                        "Slice binding requires the permission BIND_SLICE");
            }
            handlePinSlice(uri);
        } else if (method.equals(METHOD_UNPIN)) {
            Uri uri = extras.getParcelable(EXTRA_BIND_URI);
            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
                throw new SecurityException("Only the system can pin/unpin slices");
            if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.myUid())) {
                getContext().enforceUriPermission(uri, permission.BIND_SLICE,
                        permission.BIND_SLICE, Binder.getCallingPid(), Binder.getCallingUid(),
                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
                        "Slice binding requires the permission BIND_SLICE");
            }
            handleUnpinSlice(uri);
        } else if (method.equals(METHOD_GET_DESCENDANTS)) {
@@ -401,27 +370,14 @@ public abstract class SliceProvider extends ContentProvider {
        }
    }

    private Slice handleBindSlice(Uri sliceUri, List<SliceSpec> supportedSpecs,
            String callingPkg) {
        // This can be removed once Slice#bindSlice is removed and everyone is using
        // SliceManager#bindSlice.
        String pkg = callingPkg != null ? callingPkg
                : getContext().getPackageManager().getNameForUid(Binder.getCallingUid());
        if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.myUid())) {
            try {
                mSliceManager.enforceSlicePermission(sliceUri, pkg,
                        Binder.getCallingPid(), Binder.getCallingUid());
            } catch (SecurityException e) {
                return createPermissionSlice(getContext(), sliceUri, pkg);
            }
        }
    private Slice handleBindSlice(Uri sliceUri, List<SliceSpec> supportedSpecs) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            return onBindSliceStrict(sliceUri, supportedSpecs, pkg);
            return onBindSliceStrict(sliceUri, supportedSpecs);
        } else {
            CountDownLatch latch = new CountDownLatch(1);
            Slice[] output = new Slice[1];
            Handler.getMain().post(() -> {
                output[0] = onBindSliceStrict(sliceUri, supportedSpecs, pkg);
                output[0] = onBindSliceStrict(sliceUri, supportedSpecs);
                latch.countDown();
            });
            try {
@@ -433,66 +389,15 @@ public abstract class SliceProvider extends ContentProvider {
        }
    }

    /**
     * @hide
     */
    public static Slice createPermissionSlice(Context context, Uri sliceUri,
            String callingPackage) {
        return new Slice.Builder(sliceUri)
                .addAction(createPermissionIntent(context, sliceUri, callingPackage),
                        new Slice.Builder(sliceUri.buildUpon().appendPath("permission").build())
                                .addText(getPermissionString(context, callingPackage), null)
                                .build())
                .addHints(Slice.HINT_LIST_ITEM)
                .build();
    }

    /**
     * @hide
     */
    public static PendingIntent createPermissionIntent(Context context, Uri sliceUri,
            String callingPackage) {
        Intent intent = new Intent(SliceManager.ACTION_REQUEST_SLICE_PERMISSION);
        intent.setComponent(new ComponentName("com.android.systemui",
                "com.android.systemui.SlicePermissionActivity"));
        intent.putExtra(EXTRA_BIND_URI, sliceUri);
        intent.putExtra(EXTRA_PKG, callingPackage);
        intent.putExtra(EXTRA_PROVIDER_PKG, context.getPackageName());
        // Unique pending intent.
        intent.setData(sliceUri.buildUpon().appendQueryParameter("package", callingPackage)
                .build());

        return PendingIntent.getActivity(context, 0, intent, 0);
    }

    /**
     * @hide
     */
    public static CharSequence getPermissionString(Context context, String callingPackage) {
        PackageManager pm = context.getPackageManager();
        try {
            return context.getString(
                    com.android.internal.R.string.slices_permission_request,
                    pm.getApplicationInfo(callingPackage, 0).loadLabel(pm),
                    context.getApplicationInfo().loadLabel(pm));
        } catch (NameNotFoundException e) {
            // This shouldn't be possible since the caller is verified.
            throw new RuntimeException("Unknown calling app", e);
        }
    }

    private Slice onBindSliceStrict(Uri sliceUri, List<SliceSpec> supportedSpecs,
            String callingPackage) {
    private Slice onBindSliceStrict(Uri sliceUri, List<SliceSpec> supportedSpecs) {
        ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
        try {
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                    .detectAll()
                    .penaltyDeath()
                    .build());
            mBindingPkg = callingPackage;
            return onBindSlice(sliceUri, supportedSpecs);
        } finally {
            mBindingPkg = null;
            StrictMode.setThreadPolicy(oldPolicy);
        }
    }
+1 −5
Original line number Diff line number Diff line
@@ -3192,10 +3192,6 @@
    <permission android:name="android.permission.BIND_APPWIDGET"
        android:protectionLevel="signature|privileged" />

    <!-- @hide Allows sysui to manage user grants of slice permissions. -->
    <permission android:name="android.permission.MANAGE_SLICE_PERMISSIONS"
        android:protectionLevel="signature" />

    <!-- Allows an application to bind app's slices and get their
         content. This content will be surfaced to the
         user and not to leave the device.
Loading