Loading core/java/android/permission/IPermissionManager.aidl +1 −2 Original line number Diff line number Diff line Loading @@ -77,8 +77,7 @@ interface IPermissionManager { List<SplitPermissionInfoParcelable> getSplitPermissions(); void startOneTimePermissionSession(String packageName, int userId, long timeout, long revokeAfterKilledDelay, int importanceToResetTimer, int importanceToKeepSessionAlive); long revokeAfterKilledDelay); @EnforcePermission("MANAGE_ONE_TIME_PERMISSION_SESSIONS") void stopOneTimePermissionSession(String packageName, int userId); Loading core/java/android/permission/PermissionManager.java +1 −2 Original line number Diff line number Diff line Loading @@ -1371,8 +1371,7 @@ public final class PermissionManager { @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) { try { mPermissionManager.startOneTimePermissionSession(packageName, mContext.getUserId(), timeoutMillis, revokeAfterKilledDelayMillis, importanceToResetTimer, importanceToKeepSessionAlive); timeoutMillis, revokeAfterKilledDelayMillis); } catch (RemoteException e) { e.rethrowFromSystemServer(); } Loading services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java +112 −119 Original line number Diff line number Diff line Loading @@ -16,17 +16,18 @@ package com.android.server.pm.permission; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.AlarmManager; import android.app.IActivityManager; import android.app.IUidObserver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Handler; import android.os.RemoteException; import android.permission.PermissionControllerManager; import android.provider.DeviceConfig; import android.util.Log; Loading @@ -48,7 +49,7 @@ public class OneTimePermissionUserManager { "one_time_permissions_killed_delay_millis"; private final @NonNull Context mContext; private final @NonNull ActivityManager mActivityManager; private final @NonNull IActivityManager mIActivityManager; private final @NonNull AlarmManager mAlarmManager; private final @NonNull PermissionControllerManager mPermissionControllerManager; Loading Loading @@ -78,50 +79,15 @@ public class OneTimePermissionUserManager { OneTimePermissionUserManager(@NonNull Context context) { mContext = context; mActivityManager = context.getSystemService(ActivityManager.class); mIActivityManager = ActivityManager.getService(); mAlarmManager = context.getSystemService(AlarmManager.class); mPermissionControllerManager = new PermissionControllerManager( mContext, PermissionThread.getHandler()); mHandler = context.getMainThreadHandler(); } /** * 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 PermissionControllerService#onNotifyOneTimePermissionSessionTimeout * 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 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 * * @hide */ void startPackageOneTimeSession(@NonNull String packageName, long timeoutMillis, long revokeAfterKilledDelayMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) { long revokeAfterKilledDelayMillis) { int uid; try { uid = mContext.getPackageManager().getPackageUid(packageName, 0); Loading @@ -133,13 +99,11 @@ public class OneTimePermissionUserManager { synchronized (mLock) { PackageInactivityListener listener = mListeners.get(uid); if (listener != null) { listener.updateSessionParameters(timeoutMillis, revokeAfterKilledDelayMillis, importanceToResetTimer, importanceToKeepSessionAlive); listener.updateSessionParameters(timeoutMillis, revokeAfterKilledDelayMillis); return; } listener = new PackageInactivityListener(uid, packageName, timeoutMillis, revokeAfterKilledDelayMillis, importanceToResetTimer, importanceToKeepSessionAlive); revokeAfterKilledDelayMillis); mListeners.put(uid, listener); } } Loading Loading @@ -184,34 +148,58 @@ public class OneTimePermissionUserManager { private static final long TIMER_INACTIVE = -1; private static final int STATE_GONE = 0; private static final int STATE_TIMER = 1; private static final int STATE_ACTIVE = 2; private final int mUid; private final @NonNull String mPackageName; private long mTimeout; private long mRevokeAfterKilledDelay; private int mImportanceToResetTimer; private int mImportanceToKeepSessionAlive; private boolean mIsAlarmSet; private boolean mIsFinished; private long mTimerStart = TIMER_INACTIVE; private final ActivityManager.OnUidImportanceListener mStartTimerListener; private final ActivityManager.OnUidImportanceListener mSessionKillableListener; private final ActivityManager.OnUidImportanceListener mGoneListener; private final Object mInnerLock = new Object(); private final Object mToken = new Object(); private final IUidObserver.Stub mObserver = new IUidObserver.Stub() { @Override public void onUidGone(int uid, boolean disabled) { if (uid == mUid) { PackageInactivityListener.this.updateUidState(STATE_GONE); } } private PackageInactivityListener(int uid, @NonNull String packageName, long timeout, long revokeAfterkilledDelay, int importanceToResetTimer, int importanceToKeepSessionAlive) { @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { if (uid == mUid) { if (procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE && procState != ActivityManager.PROCESS_STATE_NONEXISTENT) { PackageInactivityListener.this.updateUidState(STATE_TIMER); } else { PackageInactivityListener.this.updateUidState(STATE_ACTIVE); } } } public void onUidActive(int uid) { } public void onUidIdle(int uid, boolean disabled) { } public void onUidProcAdjChanged(int uid) { } public void onUidCachedChanged(int uid, boolean cached) { } }; private PackageInactivityListener(int uid, @NonNull String packageName, long timeout, long revokeAfterkilledDelay) { Log.i(LOG_TAG, "Start tracking " + packageName + ". uid=" + uid + " timeout=" + timeout + " killedDelay=" + revokeAfterkilledDelay + " importanceToResetTimer=" + importanceToResetTimer + " importanceToKeepSessionAlive=" + importanceToKeepSessionAlive); + " killedDelay=" + revokeAfterkilledDelay); mUid = uid; mPackageName = packageName; Loading @@ -221,27 +209,24 @@ public class OneTimePermissionUserManager { DeviceConfig.NAMESPACE_PERMISSIONS, PROPERTY_KILLED_DELAY_CONFIG_KEY, DEFAULT_KILLED_DELAY_MILLIS) : revokeAfterkilledDelay; mImportanceToResetTimer = importanceToResetTimer; mImportanceToKeepSessionAlive = importanceToKeepSessionAlive; mStartTimerListener = (changingUid, importance) -> onImportanceChanged(changingUid, importance); mSessionKillableListener = (changingUid, importance) -> onImportanceChanged(changingUid, importance); mGoneListener = (changingUid, importance) -> onImportanceChanged(changingUid, importance); mActivityManager.addOnUidImportanceListener(mStartTimerListener, importanceToResetTimer); mActivityManager.addOnUidImportanceListener(mSessionKillableListener, importanceToKeepSessionAlive); mActivityManager.addOnUidImportanceListener(mGoneListener, IMPORTANCE_CACHED); try { mIActivityManager.registerUidObserver(mObserver, ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_PROCSTATE, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, null); } catch (RemoteException e) { Log.e(LOG_TAG, "Couldn't check uid proc state", e); // Can't register uid observer, just revoke immediately synchronized (mInnerLock) { onPackageInactiveLocked(); } } onImportanceChanged(mUid, mActivityManager.getPackageImportance(packageName)); updateUidState(); } public void updateSessionParameters(long timeoutMillis, long revokeAfterKilledDelayMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) { public void updateSessionParameters(long timeoutMillis, long revokeAfterKilledDelayMillis) { synchronized (mInnerLock) { mTimeout = Math.min(mTimeout, timeoutMillis); mRevokeAfterKilledDelay = Math.min(mRevokeAfterKilledDelay, Loading @@ -250,63 +235,79 @@ public class OneTimePermissionUserManager { 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)); + " killedDelay=" + mRevokeAfterKilledDelay); updateUidState(); } } private void onImportanceChanged(int uid, int importance) { if (uid != mUid) { return; private int getCurrentState() { try { return getStateFromProcState(mIActivityManager.getUidProcessState(mUid, null)); } catch (RemoteException e) { Log.e(LOG_TAG, "Couldn't check uid proc state", e); } return STATE_GONE; } private int getStateFromProcState(int procState) { if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) { return STATE_GONE; } else { if (procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { return STATE_TIMER; } else { return STATE_ACTIVE; } } } private void updateUidState() { updateUidState(getCurrentState()); } Log.v(LOG_TAG, "Importance changed for " + mPackageName + " (" + mUid + ")." + " importance=" + importance); private void updateUidState(int state) { Log.v(LOG_TAG, "Updating state for " + mPackageName + " (" + mUid + ")." + " state=" + state); synchronized (mInnerLock) { // Remove any pending inactivity callback mHandler.removeCallbacksAndMessages(mToken); if (importance > IMPORTANCE_CACHED) { if (state == STATE_GONE) { if (mRevokeAfterKilledDelay == 0) { onPackageInactiveLocked(); return; } // Delay revocation in case app is restarting mHandler.postDelayed(() -> { int imp = mActivityManager.getUidImportance(mUid); if (imp > IMPORTANCE_CACHED) { int currentState; synchronized (mInnerLock) { currentState = getCurrentState(); if (currentState == STATE_GONE) { onPackageInactiveLocked(); } else { return; } } if (DEBUG) { Log.d(LOG_TAG, "No longer gone after delayed revocation. " + "Rechecking for " + mPackageName + " (" + mUid + ")."); } onImportanceChanged(mUid, imp); + "Rechecking for " + mPackageName + " (" + mUid + ")."); } updateUidState(currentState); }, mToken, mRevokeAfterKilledDelay); return; } if (importance > mImportanceToResetTimer) { } else if (state == STATE_TIMER) { if (mTimerStart == TIMER_INACTIVE) { if (DEBUG) { Log.d(LOG_TAG, "Start the timer for " + mPackageName + " (" + mUid + ")."); } mTimerStart = System.currentTimeMillis(); setAlarmLocked(); } } else { } else if (state == STATE_ACTIVE) { mTimerStart = TIMER_INACTIVE; } if (importance > mImportanceToKeepSessionAlive) { setAlarmLocked(); } else { cancelAlarmLocked(); } } Loading @@ -320,19 +321,9 @@ public class OneTimePermissionUserManager { mIsFinished = true; cancelAlarmLocked(); try { mActivityManager.removeOnUidImportanceListener(mStartTimerListener); } catch (IllegalArgumentException e) { Log.e(LOG_TAG, "Could not remove start timer listener", e); } try { mActivityManager.removeOnUidImportanceListener(mSessionKillableListener); } catch (IllegalArgumentException e) { Log.e(LOG_TAG, "Could not remove session killable listener", e); } try { mActivityManager.removeOnUidImportanceListener(mGoneListener); } catch (IllegalArgumentException e) { Log.e(LOG_TAG, "Could not remove gone listener", e); mIActivityManager.unregisterUidObserver(mObserver); } catch (RemoteException e) { Log.e(LOG_TAG, "Unable to unregister uid observer.", e); } } } Loading Loading @@ -396,9 +387,11 @@ public class OneTimePermissionUserManager { mPermissionControllerManager.notifyOneTimePermissionSessionTimeout( mPackageName); }); mActivityManager.removeOnUidImportanceListener(mStartTimerListener); mActivityManager.removeOnUidImportanceListener(mSessionKillableListener); mActivityManager.removeOnUidImportanceListener(mGoneListener); try { mIActivityManager.unregisterUidObserver(mObserver); } catch (RemoteException e) { Log.e(LOG_TAG, "Unable to unregister uid observer.", e); } synchronized (mLock) { mListeners.remove(mUid); } Loading services/core/java/com/android/server/pm/permission/PermissionManagerService.java +2 −4 Original line number Diff line number Diff line Loading @@ -385,8 +385,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { @Override public void startOneTimePermissionSession(String packageName, @UserIdInt int userId, long timeoutMillis, long revokeAfterKilledDelayMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) { long timeoutMillis, long revokeAfterKilledDelayMillis) { mContext.enforceCallingOrSelfPermission( Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS Loading @@ -396,8 +395,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { final long token = Binder.clearCallingIdentity(); try { getOneTimePermissionUserManager(userId).startPackageOneTimeSession(packageName, timeoutMillis, revokeAfterKilledDelayMillis, importanceToResetTimer, importanceToKeepSessionAlive); timeoutMillis, revokeAfterKilledDelayMillis); } finally { Binder.restoreCallingIdentity(token); } Loading Loading
core/java/android/permission/IPermissionManager.aidl +1 −2 Original line number Diff line number Diff line Loading @@ -77,8 +77,7 @@ interface IPermissionManager { List<SplitPermissionInfoParcelable> getSplitPermissions(); void startOneTimePermissionSession(String packageName, int userId, long timeout, long revokeAfterKilledDelay, int importanceToResetTimer, int importanceToKeepSessionAlive); long revokeAfterKilledDelay); @EnforcePermission("MANAGE_ONE_TIME_PERMISSION_SESSIONS") void stopOneTimePermissionSession(String packageName, int userId); Loading
core/java/android/permission/PermissionManager.java +1 −2 Original line number Diff line number Diff line Loading @@ -1371,8 +1371,7 @@ public final class PermissionManager { @ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) { try { mPermissionManager.startOneTimePermissionSession(packageName, mContext.getUserId(), timeoutMillis, revokeAfterKilledDelayMillis, importanceToResetTimer, importanceToKeepSessionAlive); timeoutMillis, revokeAfterKilledDelayMillis); } catch (RemoteException e) { e.rethrowFromSystemServer(); } Loading
services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java +112 −119 Original line number Diff line number Diff line Loading @@ -16,17 +16,18 @@ package com.android.server.pm.permission; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.AlarmManager; import android.app.IActivityManager; import android.app.IUidObserver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Handler; import android.os.RemoteException; import android.permission.PermissionControllerManager; import android.provider.DeviceConfig; import android.util.Log; Loading @@ -48,7 +49,7 @@ public class OneTimePermissionUserManager { "one_time_permissions_killed_delay_millis"; private final @NonNull Context mContext; private final @NonNull ActivityManager mActivityManager; private final @NonNull IActivityManager mIActivityManager; private final @NonNull AlarmManager mAlarmManager; private final @NonNull PermissionControllerManager mPermissionControllerManager; Loading Loading @@ -78,50 +79,15 @@ public class OneTimePermissionUserManager { OneTimePermissionUserManager(@NonNull Context context) { mContext = context; mActivityManager = context.getSystemService(ActivityManager.class); mIActivityManager = ActivityManager.getService(); mAlarmManager = context.getSystemService(AlarmManager.class); mPermissionControllerManager = new PermissionControllerManager( mContext, PermissionThread.getHandler()); mHandler = context.getMainThreadHandler(); } /** * 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 PermissionControllerService#onNotifyOneTimePermissionSessionTimeout * 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 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 * * @hide */ void startPackageOneTimeSession(@NonNull String packageName, long timeoutMillis, long revokeAfterKilledDelayMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) { long revokeAfterKilledDelayMillis) { int uid; try { uid = mContext.getPackageManager().getPackageUid(packageName, 0); Loading @@ -133,13 +99,11 @@ public class OneTimePermissionUserManager { synchronized (mLock) { PackageInactivityListener listener = mListeners.get(uid); if (listener != null) { listener.updateSessionParameters(timeoutMillis, revokeAfterKilledDelayMillis, importanceToResetTimer, importanceToKeepSessionAlive); listener.updateSessionParameters(timeoutMillis, revokeAfterKilledDelayMillis); return; } listener = new PackageInactivityListener(uid, packageName, timeoutMillis, revokeAfterKilledDelayMillis, importanceToResetTimer, importanceToKeepSessionAlive); revokeAfterKilledDelayMillis); mListeners.put(uid, listener); } } Loading Loading @@ -184,34 +148,58 @@ public class OneTimePermissionUserManager { private static final long TIMER_INACTIVE = -1; private static final int STATE_GONE = 0; private static final int STATE_TIMER = 1; private static final int STATE_ACTIVE = 2; private final int mUid; private final @NonNull String mPackageName; private long mTimeout; private long mRevokeAfterKilledDelay; private int mImportanceToResetTimer; private int mImportanceToKeepSessionAlive; private boolean mIsAlarmSet; private boolean mIsFinished; private long mTimerStart = TIMER_INACTIVE; private final ActivityManager.OnUidImportanceListener mStartTimerListener; private final ActivityManager.OnUidImportanceListener mSessionKillableListener; private final ActivityManager.OnUidImportanceListener mGoneListener; private final Object mInnerLock = new Object(); private final Object mToken = new Object(); private final IUidObserver.Stub mObserver = new IUidObserver.Stub() { @Override public void onUidGone(int uid, boolean disabled) { if (uid == mUid) { PackageInactivityListener.this.updateUidState(STATE_GONE); } } private PackageInactivityListener(int uid, @NonNull String packageName, long timeout, long revokeAfterkilledDelay, int importanceToResetTimer, int importanceToKeepSessionAlive) { @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { if (uid == mUid) { if (procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE && procState != ActivityManager.PROCESS_STATE_NONEXISTENT) { PackageInactivityListener.this.updateUidState(STATE_TIMER); } else { PackageInactivityListener.this.updateUidState(STATE_ACTIVE); } } } public void onUidActive(int uid) { } public void onUidIdle(int uid, boolean disabled) { } public void onUidProcAdjChanged(int uid) { } public void onUidCachedChanged(int uid, boolean cached) { } }; private PackageInactivityListener(int uid, @NonNull String packageName, long timeout, long revokeAfterkilledDelay) { Log.i(LOG_TAG, "Start tracking " + packageName + ". uid=" + uid + " timeout=" + timeout + " killedDelay=" + revokeAfterkilledDelay + " importanceToResetTimer=" + importanceToResetTimer + " importanceToKeepSessionAlive=" + importanceToKeepSessionAlive); + " killedDelay=" + revokeAfterkilledDelay); mUid = uid; mPackageName = packageName; Loading @@ -221,27 +209,24 @@ public class OneTimePermissionUserManager { DeviceConfig.NAMESPACE_PERMISSIONS, PROPERTY_KILLED_DELAY_CONFIG_KEY, DEFAULT_KILLED_DELAY_MILLIS) : revokeAfterkilledDelay; mImportanceToResetTimer = importanceToResetTimer; mImportanceToKeepSessionAlive = importanceToKeepSessionAlive; mStartTimerListener = (changingUid, importance) -> onImportanceChanged(changingUid, importance); mSessionKillableListener = (changingUid, importance) -> onImportanceChanged(changingUid, importance); mGoneListener = (changingUid, importance) -> onImportanceChanged(changingUid, importance); mActivityManager.addOnUidImportanceListener(mStartTimerListener, importanceToResetTimer); mActivityManager.addOnUidImportanceListener(mSessionKillableListener, importanceToKeepSessionAlive); mActivityManager.addOnUidImportanceListener(mGoneListener, IMPORTANCE_CACHED); try { mIActivityManager.registerUidObserver(mObserver, ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_PROCSTATE, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, null); } catch (RemoteException e) { Log.e(LOG_TAG, "Couldn't check uid proc state", e); // Can't register uid observer, just revoke immediately synchronized (mInnerLock) { onPackageInactiveLocked(); } } onImportanceChanged(mUid, mActivityManager.getPackageImportance(packageName)); updateUidState(); } public void updateSessionParameters(long timeoutMillis, long revokeAfterKilledDelayMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) { public void updateSessionParameters(long timeoutMillis, long revokeAfterKilledDelayMillis) { synchronized (mInnerLock) { mTimeout = Math.min(mTimeout, timeoutMillis); mRevokeAfterKilledDelay = Math.min(mRevokeAfterKilledDelay, Loading @@ -250,63 +235,79 @@ public class OneTimePermissionUserManager { 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)); + " killedDelay=" + mRevokeAfterKilledDelay); updateUidState(); } } private void onImportanceChanged(int uid, int importance) { if (uid != mUid) { return; private int getCurrentState() { try { return getStateFromProcState(mIActivityManager.getUidProcessState(mUid, null)); } catch (RemoteException e) { Log.e(LOG_TAG, "Couldn't check uid proc state", e); } return STATE_GONE; } private int getStateFromProcState(int procState) { if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) { return STATE_GONE; } else { if (procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { return STATE_TIMER; } else { return STATE_ACTIVE; } } } private void updateUidState() { updateUidState(getCurrentState()); } Log.v(LOG_TAG, "Importance changed for " + mPackageName + " (" + mUid + ")." + " importance=" + importance); private void updateUidState(int state) { Log.v(LOG_TAG, "Updating state for " + mPackageName + " (" + mUid + ")." + " state=" + state); synchronized (mInnerLock) { // Remove any pending inactivity callback mHandler.removeCallbacksAndMessages(mToken); if (importance > IMPORTANCE_CACHED) { if (state == STATE_GONE) { if (mRevokeAfterKilledDelay == 0) { onPackageInactiveLocked(); return; } // Delay revocation in case app is restarting mHandler.postDelayed(() -> { int imp = mActivityManager.getUidImportance(mUid); if (imp > IMPORTANCE_CACHED) { int currentState; synchronized (mInnerLock) { currentState = getCurrentState(); if (currentState == STATE_GONE) { onPackageInactiveLocked(); } else { return; } } if (DEBUG) { Log.d(LOG_TAG, "No longer gone after delayed revocation. " + "Rechecking for " + mPackageName + " (" + mUid + ")."); } onImportanceChanged(mUid, imp); + "Rechecking for " + mPackageName + " (" + mUid + ")."); } updateUidState(currentState); }, mToken, mRevokeAfterKilledDelay); return; } if (importance > mImportanceToResetTimer) { } else if (state == STATE_TIMER) { if (mTimerStart == TIMER_INACTIVE) { if (DEBUG) { Log.d(LOG_TAG, "Start the timer for " + mPackageName + " (" + mUid + ")."); } mTimerStart = System.currentTimeMillis(); setAlarmLocked(); } } else { } else if (state == STATE_ACTIVE) { mTimerStart = TIMER_INACTIVE; } if (importance > mImportanceToKeepSessionAlive) { setAlarmLocked(); } else { cancelAlarmLocked(); } } Loading @@ -320,19 +321,9 @@ public class OneTimePermissionUserManager { mIsFinished = true; cancelAlarmLocked(); try { mActivityManager.removeOnUidImportanceListener(mStartTimerListener); } catch (IllegalArgumentException e) { Log.e(LOG_TAG, "Could not remove start timer listener", e); } try { mActivityManager.removeOnUidImportanceListener(mSessionKillableListener); } catch (IllegalArgumentException e) { Log.e(LOG_TAG, "Could not remove session killable listener", e); } try { mActivityManager.removeOnUidImportanceListener(mGoneListener); } catch (IllegalArgumentException e) { Log.e(LOG_TAG, "Could not remove gone listener", e); mIActivityManager.unregisterUidObserver(mObserver); } catch (RemoteException e) { Log.e(LOG_TAG, "Unable to unregister uid observer.", e); } } } Loading Loading @@ -396,9 +387,11 @@ public class OneTimePermissionUserManager { mPermissionControllerManager.notifyOneTimePermissionSessionTimeout( mPackageName); }); mActivityManager.removeOnUidImportanceListener(mStartTimerListener); mActivityManager.removeOnUidImportanceListener(mSessionKillableListener); mActivityManager.removeOnUidImportanceListener(mGoneListener); try { mIActivityManager.unregisterUidObserver(mObserver); } catch (RemoteException e) { Log.e(LOG_TAG, "Unable to unregister uid observer.", e); } synchronized (mLock) { mListeners.remove(mUid); } Loading
services/core/java/com/android/server/pm/permission/PermissionManagerService.java +2 −4 Original line number Diff line number Diff line Loading @@ -385,8 +385,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { @Override public void startOneTimePermissionSession(String packageName, @UserIdInt int userId, long timeoutMillis, long revokeAfterKilledDelayMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) { long timeoutMillis, long revokeAfterKilledDelayMillis) { mContext.enforceCallingOrSelfPermission( Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS, "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS Loading @@ -396,8 +395,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { final long token = Binder.clearCallingIdentity(); try { getOneTimePermissionUserManager(userId).startPackageOneTimeSession(packageName, timeoutMillis, revokeAfterKilledDelayMillis, importanceToResetTimer, importanceToKeepSessionAlive); timeoutMillis, revokeAfterKilledDelayMillis); } finally { Binder.restoreCallingIdentity(token); } Loading