diff options
| author | 2018-01-21 13:14:37 +0000 | |
|---|---|---|
| committer | 2018-01-21 13:14:37 +0000 | |
| commit | 6ebcfe310919af87b87b534e149a22523aba0e2f (patch) | |
| tree | 584bfbb9e616158818bf2e5eb9586b938fe3a0d8 | |
| parent | 6e3be007786a8b0cc46b50f96438f2860f7f868b (diff) | |
| parent | 1214c878a839d99b1b29c8c31fc93af2ba949338 (diff) | |
Merge "Revert "Slices permission model""
| -rw-r--r-- | core/java/android/app/slice/ISliceManager.aidl | 2 | ||||
| -rw-r--r-- | core/java/android/app/slice/Slice.java | 7 | ||||
| -rw-r--r-- | core/java/android/app/slice/SliceManager.java | 65 | ||||
| -rw-r--r-- | core/java/android/app/slice/SliceProvider.java | 145 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 6 | ||||
| -rw-r--r-- | core/res/res/values/strings.xml | 4 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 1 | ||||
| -rw-r--r-- | packages/SystemUI/AndroidManifest.xml | 13 | ||||
| -rw-r--r-- | packages/SystemUI/res/layout/slice_permission_request.xml | 50 | ||||
| -rw-r--r-- | packages/SystemUI/res/values/strings.xml | 16 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java | 88 | ||||
| -rw-r--r-- | services/core/java/com/android/server/slice/PinnedSliceState.java | 52 | ||||
| -rw-r--r-- | services/core/java/com/android/server/slice/SliceManagerService.java | 90 | ||||
| -rw-r--r-- | services/tests/uiservicestests/AndroidManifest.xml | 1 | ||||
| -rw-r--r-- | services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java | 10 |
15 files changed, 61 insertions, 489 deletions
diff --git a/core/java/android/app/slice/ISliceManager.aidl b/core/java/android/app/slice/ISliceManager.aidl index 4461b16fe15c..5f0e542f4b12 100644 --- a/core/java/android/app/slice/ISliceManager.aidl +++ b/core/java/android/app/slice/ISliceManager.aidl @@ -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); } diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java index 5bd3440d09f8..6093a4a02fbe 100644 --- a/core/java/android/app/slice/Slice.java +++ b/core/java/android/app/slice/Slice.java @@ -156,13 +156,6 @@ public final class Slice implements Parcelable { */ 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. */ public static final String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE"; diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java index 09c420c3e66a..74864cb1a371 100644 --- a/core/java/android/app/slice/SliceManager.java +++ b/core/java/android/app/slice/SliceManager.java @@ -53,34 +53,12 @@ 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 */ public SliceManager(Context context, Handler handler) throws ServiceNotFoundException { @@ -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; @@ -380,45 +358,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. */ public interface SliceCallback { diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java index 8ffacf5280c1..aa41f14d8cb5 100644 --- a/core/java/android/app/slice/SliceProvider.java +++ b/core/java/android/app/slice/SliceProvider.java @@ -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); } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 990c574f5f6c..e4e46f6d0a8f 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3192,14 +3192,10 @@ <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. - <p>Not for use by third-party applications.--> + <p>Not for use by third-party applications. --> <permission android:name="android.permission.BIND_SLICE" android:protectionLevel="signature|privileged|development" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 0c844c9deb9d..2cfe919fb8f5 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4817,8 +4817,4 @@ <string name="harmful_app_warning_launch_anyway">Launch anyway</string> <!-- Title for the harmful app warning dialog. --> <string name="harmful_app_warning_title">Uninstall harmful app?</string> - - <!-- Text describing a permission request for one app to show another app's - slices [CHAR LIMIT=NONE] --> - <string name="slices_permission_request"><xliff:g id="app" example="Example App">%1$s</xliff:g> wants to show <xliff:g id="app_2" example="Other Example App">%2$s</xliff:g> slices</string> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 03a800d8bd6f..5309115f37bb 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3227,5 +3227,4 @@ <java-symbol type="string" name="config_defaultAssistantAccessPackage" /> <java-symbol type="bool" name="config_supportBluetoothPersistedState" /> - <java-symbol type="string" name="slices_permission_request" /> </resources> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 80ac82576d13..aa2cdbb7730f 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -121,7 +121,7 @@ <uses-permission android:name="android.permission.TRUST_LISTENER" /> <uses-permission android:name="android.permission.USE_FINGERPRINT" /> <uses-permission android:name="android.permission.RESET_FINGERPRINT_LOCKOUT" /> - <uses-permission android:name="android.permission.MANAGE_SLICE_PERMISSIONS" /> + <uses-permission android:name="android.permission.BIND_SLICE" /> <!-- Needed for WallpaperManager.clear in ImageWallpaper.updateWallpaperLocked --> <uses-permission android:name="android.permission.SET_WALLPAPER"/> @@ -435,16 +435,6 @@ android:launchMode="singleTop" androidprv:alwaysFocusable="true" /> - <!-- started from SliceProvider --> - <activity android:name=".SlicePermissionActivity" - android:theme="@style/Theme.SystemUI.Dialog.Alert" - android:finishOnCloseSystemDialogs="true" - android:excludeFromRecents="true"> - <intent-filter> - <action android:name="android.intent.action.REQUEST_SLICE_PERMISSION" /> - </intent-filter> - </activity> - <!-- platform logo easter egg activity --> <activity android:name=".DessertCase" @@ -582,7 +572,6 @@ <provider android:name=".keyguard.KeyguardSliceProvider" android:authorities="com.android.systemui.keyguard" - android:grantUriPermissions="true" android:exported="true"> </provider> diff --git a/packages/SystemUI/res/layout/slice_permission_request.xml b/packages/SystemUI/res/layout/slice_permission_request.xml deleted file mode 100644 index cdb2a91a73d2..000000000000 --- a/packages/SystemUI/res/layout/slice_permission_request.xml +++ /dev/null @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<!-- Extends LinearLayout --> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingStart="16dp" - android:paddingEnd="16dp" - android:orientation="vertical"> - - <TextView - android:id="@+id/text2" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingTop="8dp" - android:paddingStart="8dp" - android:textAppearance="?android:attr/textAppearanceMedium" - android:text="@string/slice_permission_text_1" /> - - <TextView - android:id="@+id/text1" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingStart="8dp" - android:textAppearance="?android:attr/textAppearanceMedium" - android:paddingBottom="16dp" - android:text="@string/slice_permission_text_2" /> - - <CheckBox - android:id="@+id/slice_permission_checkbox" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/slice_permission_checkbox" /> - -</LinearLayout> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 199ccfcaeaa2..99ba36965231 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2067,21 +2067,5 @@ <string name="touch_filtered_warning">Because an app is obscuring a permission request, Settings can’t verify your response.</string> - <!-- Title of prompt requesting access to display slices [CHAR LIMIT=NONE] --> - <string name="slice_permission_title">Allow <xliff:g id="app" example="Example App">%1$s</xliff:g> to show <xliff:g id="app_2" example="Other Example App">%2$s</xliff:g> slices?</string> - - <!-- Description of what kind of access is given to a slice host [CHAR LIMIT=NONE] --> - <string name="slice_permission_text_1"> - It can read information from <xliff:g id="app" example="Example App">%1$s</xliff:g></string> - <!-- Description of what kind of access is given to a slice host [CHAR LIMIT=NONE] --> - <string name="slice_permission_text_2"> - It can take actions inside <xliff:g id="app" example="Example App">%1$s</xliff:g></string> - - <!-- Text on checkbox allowing the app to show slices from all apps [CHAR LIMIT=NONE] --> - <string name="slice_permission_checkbox">Allow <xliff:g id="app" example="Example App">%1$s</xliff:g> to show slices from any app</string> - - <!-- Option to grant the slice permission request on the screen [CHAR LIMIT=15] --> - <string name="slice_permission_allow">Allow</string> - - <!-- Option to grant the slice permission request on the screen [CHAR LIMIT=15] --> - <string name="slice_permission_deny">Deny</string> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java deleted file mode 100644 index 302face14c1a..000000000000 --- a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package com.android.systemui; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.slice.SliceManager; -import android.app.slice.SliceProvider; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.DialogInterface.OnDismissListener; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.net.Uri; -import android.os.Bundle; -import android.util.Log; -import android.widget.CheckBox; -import android.widget.TextView; - -public class SlicePermissionActivity extends Activity implements OnClickListener, - OnDismissListener { - - private static final String TAG = "SlicePermissionActivity"; - - private CheckBox mAllCheckbox; - - private Uri mUri; - private String mCallingPkg; - private String mProviderPkg; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mUri = getIntent().getParcelableExtra(SliceProvider.EXTRA_BIND_URI); - mCallingPkg = getIntent().getStringExtra(SliceProvider.EXTRA_PKG); - mProviderPkg = getIntent().getStringExtra(SliceProvider.EXTRA_PROVIDER_PKG); - - try { - PackageManager pm = getPackageManager(); - CharSequence app1 = pm.getApplicationInfo(mCallingPkg, 0).loadLabel(pm); - CharSequence app2 = pm.getApplicationInfo(mProviderPkg, 0).loadLabel(pm); - AlertDialog dialog = new AlertDialog.Builder(this) - .setTitle(getString(R.string.slice_permission_title, app1, app2)) - .setView(R.layout.slice_permission_request) - .setNegativeButton(R.string.slice_permission_deny, this) - .setPositiveButton(R.string.slice_permission_allow, this) - .setOnDismissListener(this) - .show(); - TextView t1 = dialog.getWindow().getDecorView().findViewById(R.id.text1); - t1.setText(getString(R.string.slice_permission_text_1, app2)); - TextView t2 = dialog.getWindow().getDecorView().findViewById(R.id.text2); - t2.setText(getString(R.string.slice_permission_text_2, app2)); - mAllCheckbox = dialog.getWindow().getDecorView().findViewById( - R.id.slice_permission_checkbox); - mAllCheckbox.setText(getString(R.string.slice_permission_checkbox, app1)); - } catch (NameNotFoundException e) { - Log.e(TAG, "Couldn't find package", e); - finish(); - } - } - - @Override - public void onClick(DialogInterface dialog, int which) { - if (which == DialogInterface.BUTTON_POSITIVE) { - getSystemService(SliceManager.class).grantPermissionFromUser(mUri, mCallingPkg, - mAllCheckbox.isChecked()); - } - finish(); - } - - @Override - public void onDismiss(DialogInterface dialog) { - finish(); - } -} diff --git a/services/core/java/com/android/server/slice/PinnedSliceState.java b/services/core/java/com/android/server/slice/PinnedSliceState.java index 09f6da92939c..cf930f5cc6b7 100644 --- a/services/core/java/com/android/server/slice/PinnedSliceState.java +++ b/services/core/java/com/android/server/slice/PinnedSliceState.java @@ -22,7 +22,6 @@ import android.content.ContentProviderClient; import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; -import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -52,8 +51,6 @@ public class PinnedSliceState { private final ArraySet<ISliceListener> mListeners = new ArraySet<>(); @GuardedBy("mLock") private SliceSpec[] mSupportedSpecs = null; - @GuardedBy("mLock") - private final ArrayMap<ISliceListener, String> mPkgMap = new ArrayMap<>(); public PinnedSliceState(SliceManagerService service, Uri uri) { mService = service; @@ -105,19 +102,17 @@ public class PinnedSliceState { mService.getHandler().post(this::handleBind); } - public void addSliceListener(ISliceListener listener, String pkg, SliceSpec[] specs) { + public void addSliceListener(ISliceListener listener, SliceSpec[] specs) { synchronized (mLock) { if (mListeners.add(listener) && mListeners.size() == 1) { mService.listen(mUri); } - mPkgMap.put(listener, pkg); mergeSpecs(specs); } } public boolean removeSliceListener(ISliceListener listener) { synchronized (mLock) { - mPkgMap.remove(listener); if (mListeners.remove(listener) && mListeners.size() == 0) { mService.unlisten(mUri); } @@ -160,16 +155,25 @@ public class PinnedSliceState { } private void handleBind() { - Slice cachedSlice = doBind(null); + Slice s; + try (ContentProviderClient client = getClient()) { + Bundle extras = new Bundle(); + extras.putParcelable(SliceProvider.EXTRA_BIND_URI, mUri); + extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, + new ArrayList<>(Arrays.asList(mSupportedSpecs))); + final Bundle res; + try { + res = client.call(SliceProvider.METHOD_SLICE, null, extras); + } catch (RemoteException e) { + Log.e(TAG, "Unable to bind slice " + mUri, e); + return; + } + if (res == null) return; + Bundle.setDefusable(res, true); + s = res.getParcelable(SliceProvider.EXTRA_SLICE); + } synchronized (mLock) { mListeners.removeIf(l -> { - Slice s = cachedSlice; - if (s == null || s.hasHint(Slice.HINT_CALLER_NEEDED)) { - s = doBind(mPkgMap.get(l)); - } - if (s == null) { - return true; - } try { l.onSliceUpdated(s); return false; @@ -185,26 +189,6 @@ public class PinnedSliceState { } } - private Slice doBind(String overridePkg) { - try (ContentProviderClient client = getClient()) { - Bundle extras = new Bundle(); - extras.putParcelable(SliceProvider.EXTRA_BIND_URI, mUri); - extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, - new ArrayList<>(Arrays.asList(mSupportedSpecs))); - extras.putString(SliceProvider.EXTRA_OVERRIDE_PKG, overridePkg); - final Bundle res; - try { - res = client.call(SliceProvider.METHOD_SLICE, null, extras); - } catch (RemoteException e) { - Log.e(TAG, "Unable to bind slice " + mUri, e); - return null; - } - if (res == null) return null; - Bundle.setDefusable(res, true); - return res.getParcelable(SliceProvider.EXTRA_SLICE); - } - } - private void handleSendPinned() { try (ContentProviderClient client = getClient()) { Bundle b = new Bundle(); diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java index 68a7608834a0..2d9e772a6b0c 100644 --- a/services/core/java/com/android/server/slice/SliceManagerService.java +++ b/services/core/java/com/android/server/slice/SliceManagerService.java @@ -23,12 +23,10 @@ import android.Manifest.permission; import android.app.AppOpsManager; import android.app.slice.ISliceListener; import android.app.slice.ISliceManager; -import android.app.slice.SliceManager; import android.app.slice.SliceSpec; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.database.ContentObserver; @@ -39,7 +37,6 @@ import android.os.Looper; import android.os.Process; import android.os.RemoteException; import android.util.ArrayMap; -import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.GuardedBy; @@ -66,8 +63,6 @@ public class SliceManagerService extends ISliceManager.Stub { @GuardedBy("mLock") private final ArrayMap<Uri, PinnedSliceState> mPinnedSlicesByUri = new ArrayMap<>(); - @GuardedBy("mLock") - private final ArraySet<SliceGrant> mUserGrants = new ArraySet<>(); private final Handler mHandler; private final ContentObserver mObserver; @@ -116,7 +111,7 @@ public class SliceManagerService extends ISliceManager.Stub { verifyCaller(pkg); uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier()); enforceAccess(pkg, uri); - getOrCreatePinnedSlice(uri).addSliceListener(listener, pkg, specs); + getOrCreatePinnedSlice(uri).addSliceListener(listener, specs); } @Override @@ -161,43 +156,6 @@ public class SliceManagerService extends ISliceManager.Stub { return getPinnedSlice(uri).getSpecs(); } - @Override - public int checkSlicePermission(Uri uri, String pkg, int pid, int uid) throws RemoteException { - if (mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION) - == PackageManager.PERMISSION_GRANTED) { - return SliceManager.PERMISSION_GRANTED; - } - if (hasFullSliceAccess(pkg, uid)) { - return SliceManager.PERMISSION_GRANTED; - } - synchronized (mLock) { - if (mUserGrants.contains(new SliceGrant(uri, pkg))) { - return SliceManager.PERMISSION_USER_GRANTED; - } - } - return SliceManager.PERMISSION_DENIED; - } - - @Override - public void grantPermissionFromUser(Uri uri, String pkg, String callingPkg, boolean allSlices) { - verifyCaller(callingPkg); - getContext().enforceCallingOrSelfPermission(permission.MANAGE_SLICE_PERMISSIONS, - "Slice granting requires MANAGE_SLICE_PERMISSIONS"); - if (allSlices) { - // TODO: Manage full access grants. - } else { - synchronized (mLock) { - mUserGrants.add(new SliceGrant(uri, pkg)); - } - long ident = Binder.clearCallingIdentity(); - try { - mContext.getContentResolver().notifyChange(uri, null); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - /// ----- internal code ----- void removePinnedSlice(Uri uri) { synchronized (mLock) { @@ -245,11 +203,10 @@ public class SliceManagerService extends ISliceManager.Stub { } private void enforceAccess(String pkg, Uri uri) { - if (!hasFullSliceAccess(pkg, Binder.getCallingUid())) { - getContext().enforceUriPermission(uri, Binder.getCallingPid(), Binder.getCallingUid(), - Intent.FLAG_GRANT_WRITE_URI_PERMISSION, - "Slice binding requires permission to the Uri"); - } + 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"); int user = Binder.getCallingUserHandle().getIdentifier(); if (getUserIdFromUri(uri, user) != user) { getContext().enforceCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL, @@ -273,14 +230,8 @@ public class SliceManagerService extends ISliceManager.Stub { } private boolean hasFullSliceAccess(String pkg, int userId) { - long ident = Binder.clearCallingIdentity(); - try { - boolean ret = isDefaultHomeApp(pkg, userId) || isAssistant(pkg, userId) - || isGrantedFullAccess(pkg, userId); - return ret; - } finally { - Binder.restoreCallingIdentity(ident); - } + return isDefaultHomeApp(pkg, userId) || isAssistant(pkg, userId) + || isGrantedFullAccess(pkg, userId); } private boolean isAssistant(String pkg, int userId) { @@ -308,8 +259,7 @@ public class SliceManagerService extends ISliceManager.Stub { private boolean isDefaultHomeApp(String pkg, int userId) { String defaultHome = getDefaultHome(userId); - - return pkg != null && Objects.equals(pkg, defaultHome); + return Objects.equals(pkg, defaultHome); } // Based on getDefaultHome in ShortcutService. @@ -351,7 +301,7 @@ public class SliceManagerService extends ISliceManager.Stub { lastPriority = ri.priority; } } - return detected != null ? detected.getPackageName() : null; + return detected.getPackageName(); } finally { Binder.restoreCallingIdentity(token); } @@ -399,26 +349,4 @@ public class SliceManagerService extends ISliceManager.Stub { mService.onStopUser(userHandle); } } - - private class SliceGrant { - private final Uri mUri; - private final String mPkg; - - public SliceGrant(Uri uri, String pkg) { - mUri = uri; - mPkg = pkg; - } - - @Override - public int hashCode() { - return mUri.hashCode() + mPkg.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof SliceGrant)) return false; - SliceGrant other = (SliceGrant) obj; - return Objects.equals(other.mUri, mUri) && Objects.equals(other.mPkg, mPkg); - } - } } diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml index 347557291427..f022dcf376a6 100644 --- a/services/tests/uiservicestests/AndroidManifest.xml +++ b/services/tests/uiservicestests/AndroidManifest.xml @@ -25,7 +25,6 @@ <uses-permission android:name="android.permission.ACCESS_NOTIFICATIONS" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" /> - <uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java index aada68273af0..ce328c29f01c 100644 --- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java +++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java @@ -149,7 +149,7 @@ public class PinnedSliceStateTest extends UiServiceTestCase { ISliceListener listener = mock(ISliceListener.class); assertFalse(mPinnedSliceManager.isPinned()); - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS); + mPinnedSliceManager.addSliceListener(listener, FIRST_SPECS); assertTrue(mPinnedSliceManager.isPinned()); assertTrue(mPinnedSliceManager.removeSliceListener(listener)); @@ -162,9 +162,9 @@ public class PinnedSliceStateTest extends UiServiceTestCase { ISliceListener listener2 = mock(ISliceListener.class); assertFalse(mPinnedSliceManager.isPinned()); - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS); + mPinnedSliceManager.addSliceListener(listener, FIRST_SPECS); assertTrue(mPinnedSliceManager.isPinned()); - mPinnedSliceManager.addSliceListener(listener2, mContext.getPackageName(), FIRST_SPECS); + mPinnedSliceManager.addSliceListener(listener2, FIRST_SPECS); assertFalse(mPinnedSliceManager.removeSliceListener(listener)); assertTrue(mPinnedSliceManager.removeSliceListener(listener2)); @@ -176,7 +176,7 @@ public class PinnedSliceStateTest extends UiServiceTestCase { ISliceListener listener = mock(ISliceListener.class); assertFalse(mPinnedSliceManager.isPinned()); - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS); + mPinnedSliceManager.addSliceListener(listener, FIRST_SPECS); assertTrue(mPinnedSliceManager.isPinned()); mPinnedSliceManager.pin("pkg", FIRST_SPECS); @@ -199,7 +199,7 @@ public class PinnedSliceStateTest extends UiServiceTestCase { assertFalse(mPinnedSliceManager.isPinned()); - mPinnedSliceManager.addSliceListener(listener, mContext.getPackageName(), FIRST_SPECS); + mPinnedSliceManager.addSliceListener(listener, FIRST_SPECS); mPinnedSliceManager.onChange(); TestableLooper.get(this).processAllMessages(); |