From 52153f4c0540a991b5b7214f4f14b5a891479a3c Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Tue, 11 Aug 2015 08:59:12 -0700 Subject: Add GTS test to ensure valid default permission grants - framework The platform grants runtime permissions by default to apps on the system image that provide core device use cases which a user expects to work out-of-the-box. We are now adding a test to ensure that OEMs cannot pregrant premissions on non approved components. bug:23043018 Change-Id: Id76717cce0ee59678956bd0be347d3c045fe4c51 --- core/java/android/app/IUiAutomationConnection.aidl | 2 + core/java/android/app/UiAutomation.java | 57 ++++++++++++++++++++++ core/java/android/app/UiAutomationConnection.java | 36 ++++++++++++++ .../java/com/android/internal/util/ArrayUtils.java | 23 +++++++++ 4 files changed, 118 insertions(+) (limited to 'core') diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl index 474154b..2caec369 100644 --- a/core/java/android/app/IUiAutomationConnection.aidl +++ b/core/java/android/app/IUiAutomationConnection.aidl @@ -43,6 +43,8 @@ interface IUiAutomationConnection { void clearWindowAnimationFrameStats(); WindowAnimationFrameStats getWindowAnimationFrameStats(); void executeShellCommand(String command, in ParcelFileDescriptor fd); + void grantRuntimePermission(String packageName, String permission, int userId); + void revokeRuntimePermission(String packageName, String permission, int userId); // Called from the system process. oneway void shutdown(); diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index a8494fb..efed2e0 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java @@ -30,6 +30,7 @@ import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.SystemClock; +import android.os.UserHandle; import android.util.Log; import android.view.Display; import android.view.InputEvent; @@ -846,6 +847,62 @@ public final class UiAutomation { } /** + * Grants a runtime permission to a package for a user. + * @param packageName The package to which to grant. + * @param permission The permission to grant. + * @return Whether granting succeeded. + * + * @hide + */ + public boolean grantRuntimePermission(String packageName, String permission, + UserHandle userHandle) { + synchronized (mLock) { + throwIfNotConnectedLocked(); + } + try { + if (DEBUG) { + Log.i(LOG_TAG, "Granting runtime permission"); + } + // Calling out without a lock held. + mUiAutomationConnection.grantRuntimePermission(packageName, + permission, userHandle.getIdentifier()); + // TODO: The package manager API should return boolean. + return true; + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error granting runtime permission", re); + } + return false; + } + + /** + * Revokes a runtime permission from a package for a user. + * @param packageName The package from which to revoke. + * @param permission The permission to revoke. + * @return Whether revoking succeeded. + * + * @hide + */ + public boolean revokeRuntimePermission(String packageName, String permission, + UserHandle userHandle) { + synchronized (mLock) { + throwIfNotConnectedLocked(); + } + try { + if (DEBUG) { + Log.i(LOG_TAG, "Revoking runtime permission"); + } + // Calling out without a lock held. + mUiAutomationConnection.revokeRuntimePermission(packageName, + permission, userHandle.getIdentifier()); + // TODO: The package manager API should return boolean. + return true; + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error revoking runtime permission", re); + } + return false; + } + + /** * Executes a shell command. This method returs a file descriptor that points * to the standard output stream. The command execution is similar to running * "adb shell " from a host connected to the device. diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java index 39cd3bc..13e27e2 100644 --- a/core/java/android/app/UiAutomationConnection.java +++ b/core/java/android/app/UiAutomationConnection.java @@ -19,6 +19,7 @@ package android.app; import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.IAccessibilityServiceClient; import android.content.Context; +import android.content.pm.IPackageManager; import android.graphics.Bitmap; import android.hardware.input.InputManager; import android.os.Binder; @@ -60,6 +61,9 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager.Stub .asInterface(ServiceManager.getService(Service.ACCESSIBILITY_SERVICE)); + private final IPackageManager mPackageManager = IPackageManager.Stub + .asInterface(ServiceManager.getService("package")); + private final Object mLock = new Object(); private final Binder mToken = new Binder(); @@ -227,6 +231,38 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub { } @Override + public void grantRuntimePermission(String packageName, String permission, int userId) + throws RemoteException { + synchronized (mLock) { + throwIfCalledByNotTrustedUidLocked(); + throwIfShutdownLocked(); + throwIfNotConnectedLocked(); + } + final long identity = Binder.clearCallingIdentity(); + try { + mPackageManager.grantRuntimePermission(packageName, permission, userId); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public void revokeRuntimePermission(String packageName, String permission, int userId) + throws RemoteException { + synchronized (mLock) { + throwIfCalledByNotTrustedUidLocked(); + throwIfShutdownLocked(); + throwIfNotConnectedLocked(); + } + final long identity = Binder.clearCallingIdentity(); + try { + mPackageManager.revokeRuntimePermission(packageName, permission, userId); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override public void executeShellCommand(final String command, final ParcelFileDescriptor sink) throws RemoteException { synchronized (mLock) { diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index 9d0636a..f190d8c 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -294,6 +294,29 @@ public class ArrayUtils { } /** + * Removes value from given array if present, providing set-like behavior. + */ + public static @Nullable String[] removeString(@Nullable String[] cur, String val) { + if (cur == null) { + return null; + } + final int N = cur.length; + for (int i = 0; i < N; i++) { + if (Objects.equals(cur[i], val)) { + String[] ret = new String[N - 1]; + if (i > 0) { + System.arraycopy(cur, 0, ret, 0, i); + } + if (i < (N - 1)) { + System.arraycopy(cur, i + 1, ret, i, N - i - 1); + } + return ret; + } + } + return cur; + } + + /** * Adds value to given array if not already present, providing set-like * behavior. */ -- cgit v1.1