diff --git a/api/current.txt b/api/current.txt index 5e7fa591385e0..d37d3d134e112 100644 --- a/api/current.txt +++ b/api/current.txt @@ -7289,6 +7289,7 @@ package android.app.slice { method public final java.lang.String getType(android.net.Uri); method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues); method public android.app.slice.Slice onBindSlice(android.net.Uri, java.util.List); + method public android.app.PendingIntent onCreatePermissionRequest(android.net.Uri); method public java.util.Collection onGetSliceDescendants(android.net.Uri); method public android.net.Uri onMapIntentToUri(android.content.Intent); method public void onSlicePinned(android.net.Uri); diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java index 67a72ec33fd82..1afe53d8a7b50 100644 --- a/core/java/android/app/slice/SliceManager.java +++ b/core/java/android/app/slice/SliceManager.java @@ -32,9 +32,11 @@ import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; +import android.os.UserHandle; import android.util.Log; import com.android.internal.util.Preconditions; @@ -392,6 +394,9 @@ public class SliceManager { */ public void enforceSlicePermission(Uri uri, String pkg, int pid, int uid) { try { + if (UserHandle.isSameApp(uid, Process.myUid())) { + return; + } if (pkg == null) { throw new SecurityException("No pkg specified"); } diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java index dd892937be71d..bf856b74f0675 100644 --- a/core/java/android/app/slice/SliceProvider.java +++ b/core/java/android/app/slice/SliceProvider.java @@ -37,7 +37,6 @@ import android.os.Handler; import android.os.Process; import android.os.StrictMode; import android.os.StrictMode.ThreadPolicy; -import android.os.UserHandle; import android.util.Log; import java.util.ArrayList; @@ -146,18 +145,6 @@ public abstract class SliceProvider extends ContentProvider { * @hide */ public static final String EXTRA_PROVIDER_PKG = "provider_pkg"; - /** - * @hide - */ - public static final String EXTRA_OVERRIDE_PKG = "override_pkg"; - /** - * @hide - */ - public static final String EXTRA_OVERRIDE_UID = "override_uid"; - /** - * @hide - */ - public static final String EXTRA_OVERRIDE_PID = "override_pid"; private static final boolean DEBUG = false; @@ -257,6 +244,23 @@ public abstract class SliceProvider extends ContentProvider { "This provider has not implemented intent to uri mapping"); } + /** + * Called when an app requests a slice it does not have write permission + * to the uri for. + *

+ * The return value will be the action on a slice that prompts the user that + * the calling app wants to show slices from this app. The default implementation + * launches a dialog that allows the user to grant access to this slice. Apps + * that do not want to allow this user grant, can override this and instead + * launch their own dialog with different behavior. + * + * @param sliceUri the Uri of the slice attempting to be bound. + * @see #getCallingPackage() + */ + public @NonNull PendingIntent onCreatePermissionRequest(Uri sliceUri) { + return createPermissionIntent(getContext(), sliceUri, getCallingPackage()); + } + @Override public final int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { @@ -312,17 +316,7 @@ public abstract class SliceProvider extends ContentProvider { String callingPackage = getCallingPackage(); int callingUid = Binder.getCallingUid(); int callingPid = Binder.getCallingPid(); - if (extras.containsKey(EXTRA_OVERRIDE_PKG)) { - if (Binder.getCallingUid() != Process.SYSTEM_UID) { - throw new SecurityException("Only the system can override calling pkg"); - } - // This is safe because we would grant SYSTEM_UID access to all slices - // and want to allow it to bind slices as if it were a less privileged app - // to check their permission levels. - callingPackage = extras.getString(EXTRA_OVERRIDE_PKG); - callingUid = extras.getInt(EXTRA_OVERRIDE_UID); - callingPid = extras.getInt(EXTRA_OVERRIDE_PID); - } + Slice s = handleBindSlice(uri, supportedSpecs, callingPackage, callingUid, callingPid); Bundle b = new Bundle(); b.putParcelable(EXTRA_SLICE, s); @@ -406,13 +400,11 @@ public abstract class SliceProvider extends ContentProvider { // SliceManager#bindSlice. String pkg = callingPkg != null ? callingPkg : getContext().getPackageManager().getNameForUid(callingUid); - if (!UserHandle.isSameApp(callingUid, Process.myUid())) { - try { - mSliceManager.enforceSlicePermission(sliceUri, pkg, - callingPid, callingUid); - } catch (SecurityException e) { - return createPermissionSlice(getContext(), sliceUri, pkg); - } + try { + mSliceManager.enforceSlicePermission(sliceUri, pkg, + callingPid, callingUid); + } catch (SecurityException e) { + return createPermissionSlice(getContext(), sliceUri, pkg); } mCallback = "onBindSlice"; Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR); @@ -426,10 +418,18 @@ public abstract class SliceProvider extends ContentProvider { /** * @hide */ - public static Slice createPermissionSlice(Context context, Uri sliceUri, + public Slice createPermissionSlice(Context context, Uri sliceUri, String callingPackage) { + PendingIntent action; + mCallback = "onCreatePermissionRequest"; + Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR); + try { + action = onCreatePermissionRequest(sliceUri); + } finally { + Handler.getMain().removeCallbacks(mAnr); + } return new Slice.Builder(sliceUri) - .addAction(createPermissionIntent(context, sliceUri, callingPackage), + .addAction(action, new Slice.Builder(sliceUri.buildUpon().appendPath("permission").build()) .addText(getPermissionString(context, callingPackage), null, Collections.emptyList())