diff --git a/core/api/system-current.txt b/core/api/system-current.txt index b2f57248402f5..ab3feeb9cd17b 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -9948,7 +9948,8 @@ package android.permission { method @IntRange(from=0) @RequiresPermission(anyOf={android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, android.Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS}) public int getRuntimePermissionsVersion(); method @NonNull public java.util.List getSplitPermissions(); method @RequiresPermission(anyOf={android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, android.Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS}) public void setRuntimePermissionsVersion(@IntRange(from=0) int); - method @RequiresPermission(android.Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) public void startOneTimePermissionSession(@NonNull String, long, int, int); + method @Deprecated @RequiresPermission(android.Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) public void startOneTimePermissionSession(@NonNull String, long, int, int); + method @RequiresPermission(android.Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) public void startOneTimePermissionSession(@NonNull String, long, long, int, int); method @RequiresPermission(android.Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) public void stopOneTimePermissionSession(@NonNull String); field @RequiresPermission(android.Manifest.permission.START_REVIEW_PERMISSION_DECISIONS) public static final String ACTION_REVIEW_PERMISSION_DECISIONS = "android.permission.action.REVIEW_PERMISSION_DECISIONS"; field public static final int PERMISSION_GRANTED = 0; // 0x0 diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl index 1c0320e9a86e6..619c8705ddae8 100644 --- a/core/java/android/permission/IPermissionManager.aidl +++ b/core/java/android/permission/IPermissionManager.aidl @@ -79,7 +79,8 @@ interface IPermissionManager { void revokeOwnPermissionsOnKill(String packageName, in List permissions); void startOneTimePermissionSession(String packageName, int userId, long timeout, - int importanceToResetTimer, int importanceToKeepSessionAlive); + long revokeAfterKilledDelay, 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 0cf06aa364ecd..a0c3c2be8dc76 100644 --- a/core/java/android/permission/PermissionControllerManager.java +++ b/core/java/android/permission/PermissionControllerManager.java @@ -913,15 +913,15 @@ public final class PermissionControllerManager { * * @param packageName The name of the package for which the permissions will be revoked. * @param permissions List of permissions to be revoked. - * @param callback Callback called when the revocation request has been completed. * - * @see Context#revokeOwnPermissionsOnKill(Collection) + * @see Context#revokeOwnPermissionsOnKill(java.util.Collection) * * @hide */ public void revokeOwnPermissionsOnKill(@NonNull String packageName, - @NonNull List permissions, AndroidFuture callback) { + @NonNull List permissions) { mRemoteService.postAsync(service -> { + AndroidFuture callback = new AndroidFuture<>(); service.revokeOwnPermissionsOnKill(packageName, permissions, callback); return callback; }).whenComplete((result, err) -> { diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java index 8d9f82b04b545..0ce36f7a9a35d 100644 --- a/core/java/android/permission/PermissionControllerService.java +++ b/core/java/android/permission/PermissionControllerService.java @@ -291,7 +291,7 @@ public abstract class PermissionControllerService extends Service { /** * Called when a package is considered inactive based on the criteria given by - * {@link PermissionManager#startOneTimePermissionSession(String, long, int, int)}. + * {@link PermissionManager#startOneTimePermissionSession(String, long, long, int, int)}. * This method is called at the end of a one-time permission session * * @param packageName The package that has been inactive diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index 15f13eb89cb9e..12fa0ddfc648a 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -20,6 +20,7 @@ import static android.os.Build.VERSION_CODES.S; import android.Manifest; import android.annotation.CheckResult; +import android.annotation.DurationMillisLong; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; @@ -1281,6 +1282,22 @@ public final class PermissionManager { } } + /** + * Starts a one-time permission session for a given package. + * @see #startOneTimePermissionSession(String, long, long, int, int) + * @hide + * @deprecated Use {@link #startOneTimePermissionSession(String, long, long, int, int)} instead + */ + @Deprecated + @SystemApi + @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) + public void startOneTimePermissionSession(@NonNull String packageName, long timeoutMillis, + @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, + @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) { + startOneTimePermissionSession(packageName, timeoutMillis, -1, + importanceToResetTimer, importanceToKeepSessionAlive); + } + /** * 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 @@ -1301,25 +1318,33 @@ public final class PermissionManager { * {@link PermissionControllerService#onOneTimePermissionSessionTimeout(String)} is invoked. *

*

- * 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. + * Note that if there is currently an active session for a package a new one isn't created but + * each parameter of the existing one will be updated to the more aggressive of both sessions. + * This means that durations will be set to the shortest parameter and importances will be set + * to the lowest one. *

* @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 revokeAfterKilledDelayMillis Number of milliseconds to wait before revoking on the + * event an app is terminated. Set to -1 to use default + * value for the device. * @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 + * session alive * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) - public void startOneTimePermissionSession(@NonNull String packageName, long timeoutMillis, + public void startOneTimePermissionSession(@NonNull String packageName, + @DurationMillisLong long timeoutMillis, + @DurationMillisLong long revokeAfterKilledDelayMillis, @ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer, @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) { try { mPermissionManager.startOneTimePermissionSession(packageName, mContext.getUserId(), - timeoutMillis, importanceToResetTimer, importanceToKeepSessionAlive); + timeoutMillis, revokeAfterKilledDelayMillis, importanceToResetTimer, + importanceToKeepSessionAlive); } catch (RemoteException e) { e.rethrowFromSystemServer(); } diff --git a/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java b/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java index d455be7e4a694..46fde4b59d8bd 100644 --- a/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java +++ b/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java @@ -108,14 +108,18 @@ public class OneTimePermissionUserManager { *

* @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 revokeAfterKilledDelayMillis Number of milliseconds to wait after the process dies + * before ending the session. Set to -1 to use default value + * for the device. * @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 + * session alive * * @hide */ void startPackageOneTimeSession(@NonNull String packageName, long timeoutMillis, - int importanceToResetTimer, int importanceToKeepSessionAlive) { + long revokeAfterKilledDelayMillis, int importanceToResetTimer, + int importanceToKeepSessionAlive) { int uid; try { uid = mContext.getPackageManager().getPackageUid(packageName, 0); @@ -126,11 +130,15 @@ public class OneTimePermissionUserManager { synchronized (mLock) { PackageInactivityListener listener = mListeners.get(uid); - if (listener == null) { - listener = new PackageInactivityListener(uid, packageName, timeoutMillis, + if (listener != null) { + listener.updateSessionParameters(timeoutMillis, revokeAfterKilledDelayMillis, importanceToResetTimer, importanceToKeepSessionAlive); - mListeners.put(uid, listener); + return; } + listener = new PackageInactivityListener(uid, packageName, timeoutMillis, + revokeAfterKilledDelayMillis, importanceToResetTimer, + importanceToKeepSessionAlive); + mListeners.put(uid, listener); } } @@ -158,18 +166,6 @@ public class OneTimePermissionUserManager { } } - /** - * The delay to wait before revoking on the event an app is terminated. Recommended to be long - * enough so that apps don't lose permission on an immediate restart - */ - private long getKilledDelayMillis(boolean isSelfRevokedPermissionSession) { - if (isSelfRevokedPermissionSession) { - return 0; - } - return DeviceConfig.getLong(DeviceConfig.NAMESPACE_PERMISSIONS, - PROPERTY_KILLED_DELAY_CONFIG_KEY, DEFAULT_KILLED_DELAY_MILLIS); - } - /** * Register to listen for Uids being uninstalled. This must be done outside of the * PermissionManagerService lock. @@ -178,18 +174,6 @@ public class OneTimePermissionUserManager { mContext.registerReceiver(mUninstallListener, new IntentFilter(Intent.ACTION_UID_REMOVED)); } - void setSelfRevokedPermissionSession(int uid) { - synchronized (mLock) { - PackageInactivityListener listener = mListeners.get(uid); - if (listener == null) { - Log.e(LOG_TAG, "Could not set session for uid " + uid - + " as self-revoke session: session not found"); - return; - } - listener.setSelfRevokedPermissionSession(); - } - } - /** * A class which watches a package for inactivity and notifies the permission controller when * the package becomes inactive @@ -200,11 +184,11 @@ public class OneTimePermissionUserManager { private final int mUid; private final @NonNull String mPackageName; - private final long mTimeout; - private final int mImportanceToResetTimer; - private final int mImportanceToKeepSessionAlive; + private long mTimeout; + private long mRevokeAfterKilledDelay; + private int mImportanceToResetTimer; + private int mImportanceToKeepSessionAlive; - private boolean mIsSelfRevokedPermissionSession; private boolean mIsAlarmSet; private boolean mIsFinished; @@ -218,16 +202,23 @@ public class OneTimePermissionUserManager { private final Object mToken = new Object(); private PackageInactivityListener(int uid, @NonNull String packageName, long timeout, - int importanceToResetTimer, int importanceToKeepSessionAlive) { + long revokeAfterkilledDelay, int importanceToResetTimer, + int importanceToKeepSessionAlive) { Log.i(LOG_TAG, "Start tracking " + packageName + ". uid=" + uid + " timeout=" + timeout + + " killedDelay=" + revokeAfterkilledDelay + " importanceToResetTimer=" + importanceToResetTimer + " importanceToKeepSessionAlive=" + importanceToKeepSessionAlive); mUid = uid; mPackageName = packageName; mTimeout = timeout; + mRevokeAfterKilledDelay = revokeAfterkilledDelay == -1 + ? DeviceConfig.getLong( + DeviceConfig.NAMESPACE_PERMISSIONS, PROPERTY_KILLED_DELAY_CONFIG_KEY, + DEFAULT_KILLED_DELAY_MILLIS) + : revokeAfterkilledDelay; mImportanceToResetTimer = importanceToResetTimer; mImportanceToKeepSessionAlive = importanceToKeepSessionAlive; @@ -247,6 +238,28 @@ public class OneTimePermissionUserManager { onImportanceChanged(mUid, mActivityManager.getPackageImportance(packageName)); } + public void updateSessionParameters(long timeoutMillis, long revokeAfterKilledDelayMillis, + int importanceToResetTimer, int importanceToKeepSessionAlive) { + synchronized (mInnerLock) { + mTimeout = Math.min(mTimeout, timeoutMillis); + mRevokeAfterKilledDelay = Math.min(mRevokeAfterKilledDelay, + revokeAfterKilledDelayMillis == -1 + ? DeviceConfig.getLong( + DeviceConfig.NAMESPACE_PERMISSIONS, + PROPERTY_KILLED_DELAY_CONFIG_KEY, DEFAULT_KILLED_DELAY_MILLIS) + : revokeAfterKilledDelayMillis); + mImportanceToResetTimer = Math.min(importanceToResetTimer, mImportanceToResetTimer); + mImportanceToKeepSessionAlive = Math.min(importanceToKeepSessionAlive, + mImportanceToKeepSessionAlive); + Log.v(LOG_TAG, + "Updated params for " + mPackageName + ". timeout=" + mTimeout + + " killedDelay=" + mRevokeAfterKilledDelay + + " importanceToResetTimer=" + mImportanceToResetTimer + + " importanceToKeepSessionAlive=" + mImportanceToKeepSessionAlive); + onImportanceChanged(mUid, mActivityManager.getPackageImportance(mPackageName)); + } + } + private void onImportanceChanged(int uid, int importance) { if (uid != mUid) { return; @@ -271,7 +284,7 @@ public class OneTimePermissionUserManager { } onImportanceChanged(mUid, imp); } - }, mToken, getKilledDelayMillis(mIsSelfRevokedPermissionSession)); + }, mToken, mRevokeAfterKilledDelay); return; } if (importance > mImportanceToResetTimer) { @@ -306,14 +319,6 @@ public class OneTimePermissionUserManager { } } - /** - * Marks the session as a self-revoke session, which does not delay the revocation when - * the app is restarting. - */ - public void setSelfRevokedPermissionSession() { - mIsSelfRevokedPermissionSession = true; - } - /** * Set the alarm which will callback when the package is inactive */ diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index edc0e3d64c423..695d6dd0bc766 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -68,7 +68,6 @@ import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; -import com.android.internal.infra.AndroidFuture; import com.android.internal.util.Preconditions; import com.android.internal.util.function.TriFunction; import com.android.server.LocalServices; @@ -388,7 +387,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { @Override public void startOneTimePermissionSession(String packageName, @UserIdInt int userId, - long timeoutMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) { + long timeoutMillis, long revokeAfterKilledDelayMillis, int importanceToResetTimer, + int importanceToKeepSessionAlive) { mContext.enforceCallingOrSelfPermission( Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS @@ -398,7 +398,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { final long token = Binder.clearCallingIdentity(); try { getOneTimePermissionUserManager(userId).startPackageOneTimeSession(packageName, - timeoutMillis, importanceToResetTimer, importanceToKeepSessionAlive); + timeoutMillis, revokeAfterKilledDelayMillis, importanceToResetTimer, + importanceToKeepSessionAlive); } finally { Binder.restoreCallingIdentity(token); } @@ -563,16 +564,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { @Override public void revokeOwnPermissionsOnKill(@NonNull String packageName, @NonNull List permissions) { - final int callingUid = Binder.getCallingUid(); - final int callingUserId = UserHandle.getUserId(callingUid); - AndroidFuture future = new AndroidFuture<>(); - future.whenComplete((result, err) -> { - if (err == null) { - getOneTimePermissionUserManager(callingUserId) - .setSelfRevokedPermissionSession(callingUid); - } - }); - mPermissionManagerServiceImpl.revokeOwnPermissionsOnKill(packageName, permissions, future); + mPermissionManagerServiceImpl.revokeOwnPermissionsOnKill(packageName, permissions); } @Override diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java index db9c1b56e4d87..ed351fd4aef91 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java @@ -108,7 +108,6 @@ import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.compat.IPlatformCompat; -import com.android.internal.infra.AndroidFuture; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.os.RoSystemProperties; @@ -1592,8 +1591,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt } @Override - public void revokeOwnPermissionsOnKill(String packageName, List permissions, - AndroidFuture callback) { + public void revokeOwnPermissionsOnKill(String packageName, List permissions) { final int callingUid = Binder.getCallingUid(); int callingUserId = UserHandle.getUserId(callingUid); int targetPackageUid = mPackageManagerInt.getPackageUid(packageName, 0, callingUserId); @@ -1608,8 +1606,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt + permName + " because it does not hold that permission"); } } - mPermissionControllerManager.revokeOwnPermissionsOnKill(packageName, permissions, - callback); + mPermissionControllerManager.revokeOwnPermissionsOnKill(packageName, permissions); } private boolean mayManageRolePermission(int uid) { diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java index 91c558b2f35ee..b558e3dee6233 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java @@ -27,7 +27,6 @@ import android.content.pm.permission.SplitPermissionInfoParcelable; import android.permission.IOnPermissionsChangeListener; import android.permission.PermissionManagerInternal; -import com.android.internal.infra.AndroidFuture; import com.android.server.pm.parsing.pkg.AndroidPackage; import java.io.FileDescriptor; @@ -344,10 +343,8 @@ public interface PermissionManagerServiceInterface extends PermissionManagerInte * * @param packageName The name of the package for which the permissions will be revoked. * @param permissions List of permissions to be revoked. - * @param callback Callback called when the revocation request has been completed. */ - void revokeOwnPermissionsOnKill(String packageName, List permissions, - AndroidFuture callback); + void revokeOwnPermissionsOnKill(String packageName, List permissions); /** * Get whether you should show UI with rationale for requesting a permission. You should do this