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
- * 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