Loading apex/jobscheduler/framework/java/android/app/AlarmManager.java +29 −1 Original line number Diff line number Diff line Loading @@ -311,6 +311,15 @@ public class AlarmManager { @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) public static final long SCHEDULE_EXACT_ALARM_DOES_NOT_ELEVATE_BUCKET = 262645982L; /** * Exact alarms expecting a {@link OnAlarmListener} callback will be dropped when the calling * app goes into cached state. * * @hide */ @ChangeId public static final long EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED = 265195908L; @UnsupportedAppUsage private final IAlarmManager mService; private final Context mContext; Loading Loading @@ -808,13 +817,24 @@ public class AlarmManager { * The OnAlarmListener's {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. * <p> * This API should only be used to set alarms that are relevant in the context of the app's * current lifecycle, as the {@link OnAlarmListener} instance supplied is only valid as long as * the process is alive, and the system can clean up the app process as soon as it is out of * lifecycle. To schedule alarms that fire reliably even after the current lifecycle completes, * and wakes up the app if required, use any of the other scheduling APIs that accept a * {@link PendingIntent} instance. * * <p class="note"><strong>Note:</strong> * <p> * On previous android versions {@link Build.VERSION_CODES#S} and * {@link Build.VERSION_CODES#TIRAMISU}, apps targeting SDK level 31 or higher needed to hold * the {@link Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM} permission to use * this API, unless the app was exempt from battery restrictions. * * <p class="note"><strong>Note:</strong> * Starting with android version {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the system will * explicitly drop any alarms set via this API when the calling app goes out of lifecycle. * */ public void setExact(@AlarmType int type, long triggerAtMillis, @Nullable String tag, @NonNull OnAlarmListener listener, @Nullable Handler targetHandler) { Loading Loading @@ -984,6 +1004,10 @@ public class AlarmManager { * allowlist. This can be set, for example, by marking the app as {@code <allow-in-power-save>} * within the system config. * * <p class="note"><strong>Note:</strong> * Starting with android version {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the system will * explicitly drop any alarms set via this API when the calling app goes out of lifecycle. * * @param type type of alarm * @param triggerAtMillis The exact time in milliseconds, that the alarm should be delivered, * expressed in the appropriate clock's units (depending on the alarm Loading Loading @@ -1295,6 +1319,10 @@ public class AlarmManager { * * <p> See {@link #setExactAndAllowWhileIdle(int, long, PendingIntent)} for more details. * * <p class="note"><strong>Note:</strong> * Starting with android version {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the system will * explicitly drop any alarms set via this API when the calling app goes out of lifecycle. * * @param type type of alarm * @param triggerAtMillis The exact time in milliseconds, that the alarm should be delivered, * expressed in the appropriate clock's units (depending on the alarm Loading apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java +25 −1 Original line number Diff line number Diff line Loading @@ -425,6 +425,12 @@ public class AppStateTrackerImpl implements AppStateTracker { */ public void removeAlarmsForUid(int uid) { } /** * Called when a uid goes into cached, so its alarms using a listener should be removed. */ public void removeListenerAlarmsForCachedUid(int uid) { } } public AppStateTrackerImpl(Context context, Looper looper) { Loading Loading @@ -496,7 +502,8 @@ public class AppStateTrackerImpl implements AppStateTracker { mIActivityManager.registerUidObserver(new UidObserver(), ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_ACTIVE, | ActivityManager.UID_OBSERVER_ACTIVE | ActivityManager.UID_OBSERVER_CACHED, ActivityManager.PROCESS_STATE_UNKNOWN, null); mAppOpsService.startWatchingMode(TARGET_OP, null, new AppOpsWatcher()); Loading Loading @@ -731,6 +738,7 @@ public class AppStateTrackerImpl implements AppStateTracker { @Override public void onUidCachedChanged(int uid, boolean cached) { mHandler.onUidCachedChanged(uid, cached); } @Override Loading Loading @@ -800,6 +808,7 @@ public class AppStateTrackerImpl implements AppStateTracker { private static final int MSG_ON_UID_ACTIVE = 12; private static final int MSG_ON_UID_GONE = 13; private static final int MSG_ON_UID_IDLE = 14; private static final int MSG_ON_UID_CACHED = 15; MyHandler(Looper looper) { super(looper); Loading Loading @@ -860,6 +869,12 @@ public class AppStateTrackerImpl implements AppStateTracker { obtainMessage(MSG_ON_UID_IDLE, uid, disabled ? 1 : 0).sendToTarget(); } public void onUidCachedChanged(int uid, boolean cached) { if (cached) { obtainMessage(MSG_ON_UID_CACHED, uid, 0).sendToTarget(); } } @Override public void handleMessage(Message msg) { switch (msg.what) { Loading Loading @@ -953,6 +968,15 @@ public class AppStateTrackerImpl implements AppStateTracker { handleUidDisabled(msg.arg1); } return; case MSG_ON_UID_CACHED: handleUidCached(msg.arg1); return; } } private void handleUidCached(int uid) { for (Listener l : cloneListeners()) { l.removeListenerAlarmsForCachedUid(uid); } } Loading apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +30 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.alarm; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.AlarmManager.ELAPSED_REALTIME; import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; import static android.app.AlarmManager.EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED; import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE; import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_COMPAT; import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; Loading Loading @@ -57,6 +58,8 @@ import static com.android.server.alarm.Alarm.TARE_POLICY_INDEX; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_ALARM_CANCELLED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_DATA_CLEARED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_EXACT_PERMISSION_REVOKED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_LISTENER_BINDER_DIED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_LISTENER_CACHED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_PI_CANCELLED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_UNDEFINED; Loading Loading @@ -610,6 +613,8 @@ public class AlarmManagerService extends SystemService { static final int REMOVE_REASON_EXACT_PERMISSION_REVOKED = 2; static final int REMOVE_REASON_DATA_CLEARED = 3; static final int REMOVE_REASON_PI_CANCELLED = 4; static final int REMOVE_REASON_LISTENER_BINDER_DIED = 5; static final int REMOVE_REASON_LISTENER_CACHED = 6; final String mTag; final long mWhenRemovedElapsed; Loading Loading @@ -639,6 +644,10 @@ public class AlarmManagerService extends SystemService { return "data_cleared"; case REMOVE_REASON_PI_CANCELLED: return "pi_cancelled"; case REMOVE_REASON_LISTENER_BINDER_DIED: return "listener_binder_died"; case REMOVE_REASON_LISTENER_CACHED: return "listener_cached"; default: return "unknown:" + reason; } Loading Loading @@ -1892,7 +1901,9 @@ public class AlarmManagerService extends SystemService { @Override public void binderDied(IBinder who) { final IAlarmListener listener = IAlarmListener.Stub.asInterface(who); removeImpl(null, listener); synchronized (mLock) { removeLocked(null, listener, REMOVE_REASON_LISTENER_BINDER_DIED); } } }; Loading Loading @@ -5444,6 +5455,24 @@ public class AlarmManagerService extends SystemService { removeForStoppedLocked(uid); } } @Override public void removeListenerAlarmsForCachedUid(int uid) { if (!CompatChanges.isChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, uid)) { return; } synchronized (mLock) { removeAlarmsInternalLocked(a -> { if (a.uid != uid || a.listener == null || a.windowLength != 0) { return false; } // TODO (b/265195908): Change to a .w once we have some data on breakages. Slog.wtf(TAG, "Alarm " + a.listenerTag + " being removed for " + a.packageName + " because the app went into cached state"); return true; }, REMOVE_REASON_LISTENER_CACHED); } } }; private final BroadcastStats getStatsLocked(PendingIntent pi) { Loading services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java +97 −1 Original line number Diff line number Diff line Loading @@ -271,7 +271,8 @@ public class AppStateTrackerTest { verify(mMockIActivityManager).registerUidObserver( uidObserverArgumentCaptor.capture(), eq(ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_ACTIVE), | ActivityManager.UID_OBSERVER_ACTIVE | ActivityManager.UID_OBSERVER_CACHED), eq(ActivityManager.PROCESS_STATE_UNKNOWN), isNull()); verify(mMockIAppOpsService).startWatchingMode( Loading Loading @@ -1364,6 +1365,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidGone(UID_10_1, true); Loading @@ -1381,6 +1384,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(1)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidActive(UID_10_1); Loading @@ -1398,6 +1403,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidIdle(UID_10_1, true); Loading @@ -1415,8 +1422,49 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(1)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidCachedChanged(UID_10_1, true); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); verify(l, times(0)).updateAllJobs(); verify(l, times(0)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateBackgroundRestrictedForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateAllAlarms(); verify(l, times(0)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(1)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidCachedChanged(UID_10_1, false); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); verify(l, times(0)).updateAllJobs(); verify(l, times(0)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateBackgroundRestrictedForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateAllAlarms(); verify(l, times(0)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); // Without battery saver. mPowerSaveMode = false; mPowerSaveObserver.accept(getPowerSaveState()); Loading @@ -1433,6 +1481,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidActive(UID_10_1); Loading @@ -1450,6 +1500,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidGone(UID_10_1, true); Loading @@ -1467,6 +1519,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(1)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidActive(UID_10_1); Loading @@ -1484,6 +1538,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidIdle(UID_10_1, true); Loading @@ -1501,6 +1557,46 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(1)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidCachedChanged(UID_10_1, true); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); verify(l, times(0)).updateAllJobs(); verify(l, times(0)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateBackgroundRestrictedForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateAllAlarms(); verify(l, times(0)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(1)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidCachedChanged(UID_10_1, false); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); verify(l, times(0)).updateAllJobs(); verify(l, times(0)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateBackgroundRestrictedForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateAllAlarms(); verify(l, times(0)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); } Loading services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +109 −56 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
apex/jobscheduler/framework/java/android/app/AlarmManager.java +29 −1 Original line number Diff line number Diff line Loading @@ -311,6 +311,15 @@ public class AlarmManager { @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) public static final long SCHEDULE_EXACT_ALARM_DOES_NOT_ELEVATE_BUCKET = 262645982L; /** * Exact alarms expecting a {@link OnAlarmListener} callback will be dropped when the calling * app goes into cached state. * * @hide */ @ChangeId public static final long EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED = 265195908L; @UnsupportedAppUsage private final IAlarmManager mService; private final Context mContext; Loading Loading @@ -808,13 +817,24 @@ public class AlarmManager { * The OnAlarmListener's {@link OnAlarmListener#onAlarm() onAlarm()} method will be * invoked via the specified target Handler, or on the application's main looper * if {@code null} is passed as the {@code targetHandler} parameter. * <p> * This API should only be used to set alarms that are relevant in the context of the app's * current lifecycle, as the {@link OnAlarmListener} instance supplied is only valid as long as * the process is alive, and the system can clean up the app process as soon as it is out of * lifecycle. To schedule alarms that fire reliably even after the current lifecycle completes, * and wakes up the app if required, use any of the other scheduling APIs that accept a * {@link PendingIntent} instance. * * <p class="note"><strong>Note:</strong> * <p> * On previous android versions {@link Build.VERSION_CODES#S} and * {@link Build.VERSION_CODES#TIRAMISU}, apps targeting SDK level 31 or higher needed to hold * the {@link Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM} permission to use * this API, unless the app was exempt from battery restrictions. * * <p class="note"><strong>Note:</strong> * Starting with android version {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the system will * explicitly drop any alarms set via this API when the calling app goes out of lifecycle. * */ public void setExact(@AlarmType int type, long triggerAtMillis, @Nullable String tag, @NonNull OnAlarmListener listener, @Nullable Handler targetHandler) { Loading Loading @@ -984,6 +1004,10 @@ public class AlarmManager { * allowlist. This can be set, for example, by marking the app as {@code <allow-in-power-save>} * within the system config. * * <p class="note"><strong>Note:</strong> * Starting with android version {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the system will * explicitly drop any alarms set via this API when the calling app goes out of lifecycle. * * @param type type of alarm * @param triggerAtMillis The exact time in milliseconds, that the alarm should be delivered, * expressed in the appropriate clock's units (depending on the alarm Loading Loading @@ -1295,6 +1319,10 @@ public class AlarmManager { * * <p> See {@link #setExactAndAllowWhileIdle(int, long, PendingIntent)} for more details. * * <p class="note"><strong>Note:</strong> * Starting with android version {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the system will * explicitly drop any alarms set via this API when the calling app goes out of lifecycle. * * @param type type of alarm * @param triggerAtMillis The exact time in milliseconds, that the alarm should be delivered, * expressed in the appropriate clock's units (depending on the alarm Loading
apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java +25 −1 Original line number Diff line number Diff line Loading @@ -425,6 +425,12 @@ public class AppStateTrackerImpl implements AppStateTracker { */ public void removeAlarmsForUid(int uid) { } /** * Called when a uid goes into cached, so its alarms using a listener should be removed. */ public void removeListenerAlarmsForCachedUid(int uid) { } } public AppStateTrackerImpl(Context context, Looper looper) { Loading Loading @@ -496,7 +502,8 @@ public class AppStateTrackerImpl implements AppStateTracker { mIActivityManager.registerUidObserver(new UidObserver(), ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_ACTIVE, | ActivityManager.UID_OBSERVER_ACTIVE | ActivityManager.UID_OBSERVER_CACHED, ActivityManager.PROCESS_STATE_UNKNOWN, null); mAppOpsService.startWatchingMode(TARGET_OP, null, new AppOpsWatcher()); Loading Loading @@ -731,6 +738,7 @@ public class AppStateTrackerImpl implements AppStateTracker { @Override public void onUidCachedChanged(int uid, boolean cached) { mHandler.onUidCachedChanged(uid, cached); } @Override Loading Loading @@ -800,6 +808,7 @@ public class AppStateTrackerImpl implements AppStateTracker { private static final int MSG_ON_UID_ACTIVE = 12; private static final int MSG_ON_UID_GONE = 13; private static final int MSG_ON_UID_IDLE = 14; private static final int MSG_ON_UID_CACHED = 15; MyHandler(Looper looper) { super(looper); Loading Loading @@ -860,6 +869,12 @@ public class AppStateTrackerImpl implements AppStateTracker { obtainMessage(MSG_ON_UID_IDLE, uid, disabled ? 1 : 0).sendToTarget(); } public void onUidCachedChanged(int uid, boolean cached) { if (cached) { obtainMessage(MSG_ON_UID_CACHED, uid, 0).sendToTarget(); } } @Override public void handleMessage(Message msg) { switch (msg.what) { Loading Loading @@ -953,6 +968,15 @@ public class AppStateTrackerImpl implements AppStateTracker { handleUidDisabled(msg.arg1); } return; case MSG_ON_UID_CACHED: handleUidCached(msg.arg1); return; } } private void handleUidCached(int uid) { for (Listener l : cloneListeners()) { l.removeListenerAlarmsForCachedUid(uid); } } Loading
apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +30 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.alarm; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.AlarmManager.ELAPSED_REALTIME; import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; import static android.app.AlarmManager.EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED; import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE; import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_COMPAT; import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; Loading Loading @@ -57,6 +58,8 @@ import static com.android.server.alarm.Alarm.TARE_POLICY_INDEX; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_ALARM_CANCELLED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_DATA_CLEARED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_EXACT_PERMISSION_REVOKED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_LISTENER_BINDER_DIED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_LISTENER_CACHED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_PI_CANCELLED; import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_UNDEFINED; Loading Loading @@ -610,6 +613,8 @@ public class AlarmManagerService extends SystemService { static final int REMOVE_REASON_EXACT_PERMISSION_REVOKED = 2; static final int REMOVE_REASON_DATA_CLEARED = 3; static final int REMOVE_REASON_PI_CANCELLED = 4; static final int REMOVE_REASON_LISTENER_BINDER_DIED = 5; static final int REMOVE_REASON_LISTENER_CACHED = 6; final String mTag; final long mWhenRemovedElapsed; Loading Loading @@ -639,6 +644,10 @@ public class AlarmManagerService extends SystemService { return "data_cleared"; case REMOVE_REASON_PI_CANCELLED: return "pi_cancelled"; case REMOVE_REASON_LISTENER_BINDER_DIED: return "listener_binder_died"; case REMOVE_REASON_LISTENER_CACHED: return "listener_cached"; default: return "unknown:" + reason; } Loading Loading @@ -1892,7 +1901,9 @@ public class AlarmManagerService extends SystemService { @Override public void binderDied(IBinder who) { final IAlarmListener listener = IAlarmListener.Stub.asInterface(who); removeImpl(null, listener); synchronized (mLock) { removeLocked(null, listener, REMOVE_REASON_LISTENER_BINDER_DIED); } } }; Loading Loading @@ -5444,6 +5455,24 @@ public class AlarmManagerService extends SystemService { removeForStoppedLocked(uid); } } @Override public void removeListenerAlarmsForCachedUid(int uid) { if (!CompatChanges.isChangeEnabled(EXACT_LISTENER_ALARMS_DROPPED_ON_CACHED, uid)) { return; } synchronized (mLock) { removeAlarmsInternalLocked(a -> { if (a.uid != uid || a.listener == null || a.windowLength != 0) { return false; } // TODO (b/265195908): Change to a .w once we have some data on breakages. Slog.wtf(TAG, "Alarm " + a.listenerTag + " being removed for " + a.packageName + " because the app went into cached state"); return true; }, REMOVE_REASON_LISTENER_CACHED); } } }; private final BroadcastStats getStatsLocked(PendingIntent pi) { Loading
services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java +97 −1 Original line number Diff line number Diff line Loading @@ -271,7 +271,8 @@ public class AppStateTrackerTest { verify(mMockIActivityManager).registerUidObserver( uidObserverArgumentCaptor.capture(), eq(ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_ACTIVE), | ActivityManager.UID_OBSERVER_ACTIVE | ActivityManager.UID_OBSERVER_CACHED), eq(ActivityManager.PROCESS_STATE_UNKNOWN), isNull()); verify(mMockIAppOpsService).startWatchingMode( Loading Loading @@ -1364,6 +1365,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidGone(UID_10_1, true); Loading @@ -1381,6 +1384,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(1)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidActive(UID_10_1); Loading @@ -1398,6 +1403,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidIdle(UID_10_1, true); Loading @@ -1415,8 +1422,49 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(1)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidCachedChanged(UID_10_1, true); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); verify(l, times(0)).updateAllJobs(); verify(l, times(0)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateBackgroundRestrictedForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateAllAlarms(); verify(l, times(0)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(1)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidCachedChanged(UID_10_1, false); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); verify(l, times(0)).updateAllJobs(); verify(l, times(0)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateBackgroundRestrictedForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateAllAlarms(); verify(l, times(0)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); // Without battery saver. mPowerSaveMode = false; mPowerSaveObserver.accept(getPowerSaveState()); Loading @@ -1433,6 +1481,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidActive(UID_10_1); Loading @@ -1450,6 +1500,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidGone(UID_10_1, true); Loading @@ -1467,6 +1519,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(1)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidActive(UID_10_1); Loading @@ -1484,6 +1538,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidIdle(UID_10_1, true); Loading @@ -1501,6 +1557,46 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(1)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidCachedChanged(UID_10_1, true); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); verify(l, times(0)).updateAllJobs(); verify(l, times(0)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateBackgroundRestrictedForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateAllAlarms(); verify(l, times(0)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(1)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); mIUidObserver.onUidCachedChanged(UID_10_1, false); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); verify(l, times(0)).updateAllJobs(); verify(l, times(0)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateBackgroundRestrictedForUidPackage(anyInt(), anyString(), anyBoolean()); verify(l, times(0)).updateAllAlarms(); verify(l, times(0)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); verify(l, times(0)).removeAlarmsForUid(UID_10_1); verify(l, times(0)).removeListenerAlarmsForCachedUid(UID_10_1); reset(l); } Loading
services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +109 −56 File changed.Preview size limit exceeded, changes collapsed. Show changes