diff options
| author | Evan Severson <evanseverson@google.com> | 2019-12-19 22:04:40 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2019-12-19 22:04:40 +0000 |
| commit | 7f1ce8f9035ddb09a820f286b3ca6776587d8db7 (patch) | |
| tree | fb43feaa634c5de3996e4de26462a3b2d6b229c7 /core/java/android | |
| parent | 34824d8167c00adfc30d63e7a4a1dcbb5238ace4 (diff) | |
| parent | b252d8bdbf378065ff209cb2135b3324136d226f (diff) | |
Merge "Create system server component for one-time permissions"
Diffstat (limited to 'core/java/android')
6 files changed, 122 insertions, 2 deletions
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 21c9739dd1ee..ee27f4f8345f 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3243,6 +3243,15 @@ public abstract class PackageManager { public static final int FLAG_PERMISSION_REVOKED_COMPAT = FLAG_PERMISSION_REVOKE_ON_UPGRADE; /** + * Permission flag: The permission is one-time and should be revoked automatically on app + * inactivity + * + * @hide + */ + @SystemApi + public static final int FLAG_PERMISSION_ONE_TIME = 1 << 16; + + /** * Permission flags: Bitwise or of all permission flags allowing an * exemption for a restricted permission. * @hide @@ -3283,7 +3292,8 @@ public abstract class PackageManager { | FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT | FLAG_PERMISSION_APPLY_RESTRICTION | FLAG_PERMISSION_GRANTED_BY_ROLE - | FLAG_PERMISSION_REVOKED_COMPAT; + | FLAG_PERMISSION_REVOKED_COMPAT + | FLAG_PERMISSION_ONE_TIME; /** * Injected activity in app that forwards user to setting activity of that app. @@ -4063,7 +4073,8 @@ public abstract class PackageManager { FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT, FLAG_PERMISSION_APPLY_RESTRICTION, FLAG_PERMISSION_GRANTED_BY_ROLE, - FLAG_PERMISSION_REVOKED_COMPAT + FLAG_PERMISSION_REVOKED_COMPAT, + FLAG_PERMISSION_ONE_TIME }) @Retention(RetentionPolicy.SOURCE) public @interface PermissionFlags {} @@ -7164,6 +7175,7 @@ public abstract class PackageManager { case FLAG_PERMISSION_APPLY_RESTRICTION: return "APPLY_RESTRICTION"; case FLAG_PERMISSION_GRANTED_BY_ROLE: return "GRANTED_BY_ROLE"; case FLAG_PERMISSION_REVOKED_COMPAT: return "REVOKED_COMPAT"; + case FLAG_PERMISSION_ONE_TIME: return "ONE_TIME"; default: return Integer.toString(flag); } } diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl index 26c1ec170834..0483514e6297 100644 --- a/core/java/android/permission/IPermissionController.aidl +++ b/core/java/android/permission/IPermissionController.aidl @@ -43,4 +43,5 @@ oneway interface IPermissionController { String permission, int grantState, in AndroidFuture callback); void grantOrUpgradeDefaultRuntimePermissions(in AndroidFuture callback); void updateUserSensitive(in AndroidFuture callback); + void notifyOneTimePermissionSessionTimeout(String packageName); } diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl index 60c88116f804..2615c98a6d5e 100644 --- a/core/java/android/permission/IPermissionManager.aidl +++ b/core/java/android/permission/IPermissionManager.aidl @@ -20,6 +20,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.pm.permission.SplitPermissionInfoParcelable; +import android.os.UserHandle; import android.permission.IOnPermissionsChangeListener; /** @@ -100,4 +101,9 @@ interface IPermissionManager { boolean isPermissionRevokedByPolicy(String permName, String packageName, int userId); List<SplitPermissionInfoParcelable> getSplitPermissions(); + + void startOneTimePermissionSession(String packageName, int userId, long timeout, + int importanceToResetTimer, int importanceToKeepSessionAlive); + + void stopOneTimePermissionSession(String packageName, int userId); } diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java index 421e29ed0542..2a1857fd0027 100644 --- a/core/java/android/permission/PermissionControllerManager.java +++ b/core/java/android/permission/PermissionControllerManager.java @@ -636,4 +636,18 @@ public final class PermissionControllerManager { return future; }); } + + /** + * Called when a package that has permissions registered as "one-time" is considered + * inactive. + * + * @param packageName The package which became inactive + * + * @hide + */ + @RequiresPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) + public void notifyOneTimePermissionSessionTimeout(@NonNull String packageName) { + mRemoteService.run( + service -> service.notifyOneTimePermissionSessionTimeout(packageName)); + } } diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java index f9146637c8cb..5d4561c21e55 100644 --- a/core/java/android/permission/PermissionControllerService.java +++ b/core/java/android/permission/PermissionControllerService.java @@ -240,6 +240,18 @@ public abstract class PermissionControllerService extends Service { @NonNull String permission, @PermissionGrantState int grantState, @NonNull Consumer<Boolean> callback); + /** + * Called when a package is considered inactive based on the criteria given by + * {@link PermissionManager#startOneTimePermissionSession(String, long, int, int)}. + * This method is called at the end of a one-time permission session + * + * @param packageName The package that has been inactive + */ + @BinderThread + public void onOneTimePermissionSessionTimeout(@NonNull String packageName) { + throw new AbstractMethodError("Must be overridden in implementing class"); + } + @Override public final @NonNull IBinder onBind(Intent intent) { return new IPermissionController.Stub() { @@ -452,6 +464,15 @@ public abstract class PermissionControllerService extends Service { onUpdateUserSensitivePermissionFlags(); callback.complete(null); } + + @Override + public void notifyOneTimePermissionSessionTimeout(String packageName) { + enforceSomePermissionsGrantedToCaller( + Manifest.permission.REVOKE_RUNTIME_PERMISSIONS); + packageName = Preconditions.checkNotNull(packageName, + "packageName cannot be null"); + onOneTimePermissionSessionTimeout(packageName); + } }; } } diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index 09286feee6b9..a3215a47fd62 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -25,6 +25,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; +import android.app.ActivityManager; import android.app.ActivityThread; import android.content.Context; import android.content.pm.IPackageManager; @@ -284,4 +285,69 @@ public final class PermissionManager { mSplitPermissionInfoParcelable = parcelable; } } + + /** + * Starts a one-time permission session for a given package. A one-time permission session is + * ended if app becomes inactive. Inactivity is defined as the package's uid importance level + * staying > importanceToResetTimer for timeoutMillis milliseconds. If the package's uid + * importance level goes <= importanceToResetTimer then the timer is reset and doesn't start + * until going > importanceToResetTimer. + * <p> + * When this timeoutMillis is reached if the importance level is <= importanceToKeepSessionAlive + * then the session is extended until either the importance goes above + * importanceToKeepSessionAlive which will end the session or <= importanceToResetTimer which + * will continue the session and reset the timer. + * </p> + * <p> + * Importance levels are defined in {@link android.app.ActivityManager.RunningAppProcessInfo}. + * </p> + * <p> + * Once the session ends + * {@link PermissionControllerService#onOneTimePermissionSessionTimeout(String)} is invoked. + * </p> + * <p> + * Note that if there is currently an active session for a package a new one isn't created and + * the existing one isn't changed. + * </p> + * @param packageName The package to start a one-time permission session for + * @param timeoutMillis Number of milliseconds for an app to be in an inactive state + * @param importanceToResetTimer The least important level to uid must be to reset the timer + * @param importanceToKeepSessionAlive The least important level the uid must be to keep the + * session alive + * + * @hide + */ + @SystemApi + @RequiresPermission(allOf = {Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, + Manifest.permission.PACKAGE_USAGE_STATS}) + public void startOneTimePermissionSession(@NonNull String packageName, long timeoutMillis, + @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, + @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) { + try { + mPermissionManager.startOneTimePermissionSession(packageName, mContext.getUserId(), + timeoutMillis, importanceToResetTimer, importanceToKeepSessionAlive); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * Stops the one-time permission session for the package. The callback to the end of session is + * not invoked. If there is no one-time session for the package then nothing happens. + * + * @param packageName Package to stop the one-time permission session for + * + * @hide + */ + @SystemApi + @RequiresPermission(allOf = {Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, + Manifest.permission.PACKAGE_USAGE_STATS}) + public void stopOneTimePermissionSession(@NonNull String packageName) { + try { + mPermissionManager.stopOneTimePermissionSession(packageName, + mContext.getUserId()); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } } |
