Loading core/java/android/app/PendingIntent.java +6 −1 Original line number Diff line number Diff line Loading @@ -1257,7 +1257,12 @@ public final class PendingIntent implements Parcelable { return b != null ? new PendingIntent(b, in.getClassCookie(PendingIntent.class)) : null; } /*package*/ PendingIntent(IIntentSender target) { /** * Creates a PendingIntent with the given target. * @param target the backing IIntentSender * @hide */ public PendingIntent(IIntentSender target) { mTarget = target; } Loading services/core/java/com/android/server/AlarmManagerInternal.java +8 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import android.app.PendingIntent; public interface AlarmManagerInternal { // Some other components in the system server need to know about // broadcast alarms currently in flight Loading @@ -30,4 +32,10 @@ public interface AlarmManagerInternal { boolean isIdling(); public void removeAlarmsForUid(int uid); public void registerInFlightListener(InFlightListener callback); /** * Removes any alarm with the given pending intent with equality determined using * {@link android.app.PendingIntent#equals(java.lang.Object) PendingIntent.equals} */ void remove(PendingIntent rec); } services/core/java/com/android/server/AlarmManagerService.java +10 −21 Original line number Diff line number Diff line Loading @@ -210,7 +210,6 @@ class AlarmManagerService extends SystemService { IAlarmListener mTimeTickTrigger; PendingIntent mDateChangeSender; Random mRandom; PendingIntent.CancelListener mOperationCancelListener; boolean mInteractive = true; long mNonInteractiveStartTime; long mNonInteractiveTime; Loading Loading @@ -1498,7 +1497,6 @@ class AlarmManagerService extends SystemService { synchronized (mLock) { mHandler = new AlarmHandler(); mOperationCancelListener = (intent) -> removeImpl(intent, null); mConstants = new Constants(mHandler); mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW); Loading Loading @@ -1750,9 +1748,6 @@ class AlarmManagerService extends SystemService { } else { maxElapsed = triggerElapsed + windowLength; } if (operation != null) { operation.registerCancelListener(mOperationCancelListener); } synchronized (mLock) { if (DEBUG_BATCH) { Slog.v(TAG, "set(" + operation + ") : type=" + type Loading @@ -1765,8 +1760,6 @@ class AlarmManagerService extends SystemService { "Maximum limit of concurrent alarms " + mConstants.MAX_ALARMS_PER_UID + " reached for uid: " + UserHandle.formatUid(callingUid) + ", callingPackage: " + callingPackage; mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, operation).sendToTarget(); Slog.w(TAG, errorMsg); throw new IllegalStateException(errorMsg); } Loading @@ -1787,8 +1780,6 @@ class AlarmManagerService extends SystemService { if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) { Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a + " -- package not allowed to start"); mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, operation).sendToTarget(); return; } } catch (RemoteException e) { Loading Loading @@ -2041,6 +2032,11 @@ class AlarmManagerService extends SystemService { } } @Override public void remove(PendingIntent pi) { mHandler.obtainMessage(AlarmHandler.REMOVE_FOR_CANCELED, pi).sendToTarget(); } @Override public void registerInFlightListener(InFlightListener callback) { synchronized (mLock) { Loading Loading @@ -2146,8 +2142,6 @@ class AlarmManagerService extends SystemService { synchronized (mLock) { removeLocked(operation, listener); } mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, operation).sendToTarget(); } @Override Loading Loading @@ -4151,7 +4145,7 @@ class AlarmManagerService extends SystemService { public static final int APP_STANDBY_BUCKET_CHANGED = 5; public static final int APP_STANDBY_PAROLE_CHANGED = 6; public static final int REMOVE_FOR_STOPPED = 7; public static final int UNREGISTER_CANCEL_LISTENER = 8; public static final int REMOVE_FOR_CANCELED = 8; AlarmHandler() { super(Looper.myLooper()); Loading Loading @@ -4234,10 +4228,10 @@ class AlarmManagerService extends SystemService { } break; case UNREGISTER_CANCEL_LISTENER: final PendingIntent pi = (PendingIntent) msg.obj; if (pi != null) { pi.unregisterCancelListener(mOperationCancelListener); case REMOVE_FOR_CANCELED: final PendingIntent operation = (PendingIntent) msg.obj; synchronized (mLock) { removeLocked(operation, null); } break; Loading Loading @@ -4696,11 +4690,6 @@ class AlarmManagerService extends SystemService { Intent.EXTRA_ALARM_COUNT, alarm.count), mDeliveryTracker, mHandler, null, allowWhileIdle ? mIdleOptions : null); if (alarm.repeatInterval == 0) { // Keep the listener for repeating alarms until they get cancelled mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, alarm.operation).sendToTarget(); } } catch (PendingIntent.CanceledException e) { if (alarm.repeatInterval > 0) { // This IntentSender is no longer valid, but this Loading services/core/java/com/android/server/am/PendingIntentController.java +3 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.util.Slog; import com.android.internal.os.IResultReceiver; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.AlarmManagerInternal; import com.android.server.LocalServices; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.SafeActivityOptions; Loading Loading @@ -293,6 +294,8 @@ public class PendingIntentController { PendingIntentController::handlePendingIntentCancelled, this, callbacks); mH.sendMessage(m); } final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class); ami.remove(new PendingIntent(rec)); } private void handlePendingIntentCancelled(RemoteCallbackList<IResultReceiver> callbacks) { Loading services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java +18 −14 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow; Loading @@ -35,6 +36,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.AlarmManagerService.ACTIVE_INDEX; import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED; import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_PAROLE_CHANGED; import static com.android.server.AlarmManagerService.AlarmHandler.REMOVE_FOR_CANCELED; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION; Loading Loading @@ -79,9 +81,9 @@ import android.provider.Settings; import android.util.Log; import android.util.SparseArray; import androidx.test.filters.FlakyTest; import androidx.test.runner.AndroidJUnit4; import com.android.dx.mockito.inline.extended.MockedVoidMethod; import com.android.internal.annotations.GuardedBy; import org.junit.After; Loading Loading @@ -166,7 +168,6 @@ public class AlarmManagerServiceTest { } public class Injector extends AlarmManagerService.Injector { boolean mIsAutomotiveOverride; Injector(Context context) { super(context); Loading Loading @@ -256,6 +257,9 @@ public class AlarmManagerServiceTest { .when(() -> LocalServices.getService(DeviceIdleController.LocalService.class)); doReturn(mUsageStatsManagerInternal).when( () -> LocalServices.getService(UsageStatsManagerInternal.class)); doCallRealMethod().when((MockedVoidMethod) () -> LocalServices.addService(eq(AlarmManagerInternal.class), any())); doCallRealMethod().when(() -> LocalServices.getService(AlarmManagerInternal.class)); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong())) .thenReturn(STANDBY_BUCKET_ACTIVE); Loading Loading @@ -443,7 +447,6 @@ public class AlarmManagerServiceTest { assertEquals(expectedTriggerTime, mTestTimer.getElapsed()); } @FlakyTest(bugId = 130313408) @Test public void testEarliestAlarmSet() { final PendingIntent pi6 = getNewMockPendingIntent(); Loading Loading @@ -661,11 +664,15 @@ public class AlarmManagerServiceTest { anyLong())).thenReturn(bucket); mAppStandbyListener.onAppIdleStateChanged(TEST_CALLING_PACKAGE, UserHandle.getUserId(TEST_CALLING_UID), false, bucket, 0); assertAndHandleMessageSync(APP_STANDBY_BUCKET_CHANGED); } private void assertAndHandleMessageSync(int what) { final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture()); final Message lastMessage = messageCaptor.getValue(); assertEquals("Unexpected message send to handler", lastMessage.what, APP_STANDBY_BUCKET_CHANGED); what); mService.mHandler.handleMessage(lastMessage); } Loading Loading @@ -725,12 +732,7 @@ public class AlarmManagerServiceTest { private void assertAndHandleParoleChanged(boolean parole) { mAppStandbyListener.onParoleStateChanged(parole); final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture()); final Message lastMessage = messageCaptor.getValue(); assertEquals("Unexpected message send to handler", lastMessage.what, APP_STANDBY_PAROLE_CHANGED); mService.mHandler.handleMessage(lastMessage); assertAndHandleMessageSync(APP_STANDBY_PAROLE_CHANGED); } @Test Loading Loading @@ -1033,12 +1035,13 @@ public class AlarmManagerServiceTest { } @Test public void alarmCountOnPendingIntentCancel() { public void alarmCountOnRemoveForCanceled() { final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class); final PendingIntent pi = getNewMockPendingIntent(); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 123, pi); verify(pi).registerCancelListener(mService.mOperationCancelListener); setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 12345, pi); assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); mService.mOperationCancelListener.onCancelled(pi); ami.remove(pi); assertAndHandleMessageSync(REMOVE_FOR_CANCELED); assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); } Loading @@ -1047,5 +1050,6 @@ public class AlarmManagerServiceTest { if (mMockingSession != null) { mMockingSession.finishMocking(); } LocalServices.removeServiceForTest(AlarmManagerInternal.class); } } Loading
core/java/android/app/PendingIntent.java +6 −1 Original line number Diff line number Diff line Loading @@ -1257,7 +1257,12 @@ public final class PendingIntent implements Parcelable { return b != null ? new PendingIntent(b, in.getClassCookie(PendingIntent.class)) : null; } /*package*/ PendingIntent(IIntentSender target) { /** * Creates a PendingIntent with the given target. * @param target the backing IIntentSender * @hide */ public PendingIntent(IIntentSender target) { mTarget = target; } Loading
services/core/java/com/android/server/AlarmManagerInternal.java +8 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server; import android.app.PendingIntent; public interface AlarmManagerInternal { // Some other components in the system server need to know about // broadcast alarms currently in flight Loading @@ -30,4 +32,10 @@ public interface AlarmManagerInternal { boolean isIdling(); public void removeAlarmsForUid(int uid); public void registerInFlightListener(InFlightListener callback); /** * Removes any alarm with the given pending intent with equality determined using * {@link android.app.PendingIntent#equals(java.lang.Object) PendingIntent.equals} */ void remove(PendingIntent rec); }
services/core/java/com/android/server/AlarmManagerService.java +10 −21 Original line number Diff line number Diff line Loading @@ -210,7 +210,6 @@ class AlarmManagerService extends SystemService { IAlarmListener mTimeTickTrigger; PendingIntent mDateChangeSender; Random mRandom; PendingIntent.CancelListener mOperationCancelListener; boolean mInteractive = true; long mNonInteractiveStartTime; long mNonInteractiveTime; Loading Loading @@ -1498,7 +1497,6 @@ class AlarmManagerService extends SystemService { synchronized (mLock) { mHandler = new AlarmHandler(); mOperationCancelListener = (intent) -> removeImpl(intent, null); mConstants = new Constants(mHandler); mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW); Loading Loading @@ -1750,9 +1748,6 @@ class AlarmManagerService extends SystemService { } else { maxElapsed = triggerElapsed + windowLength; } if (operation != null) { operation.registerCancelListener(mOperationCancelListener); } synchronized (mLock) { if (DEBUG_BATCH) { Slog.v(TAG, "set(" + operation + ") : type=" + type Loading @@ -1765,8 +1760,6 @@ class AlarmManagerService extends SystemService { "Maximum limit of concurrent alarms " + mConstants.MAX_ALARMS_PER_UID + " reached for uid: " + UserHandle.formatUid(callingUid) + ", callingPackage: " + callingPackage; mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, operation).sendToTarget(); Slog.w(TAG, errorMsg); throw new IllegalStateException(errorMsg); } Loading @@ -1787,8 +1780,6 @@ class AlarmManagerService extends SystemService { if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) { Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a + " -- package not allowed to start"); mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, operation).sendToTarget(); return; } } catch (RemoteException e) { Loading Loading @@ -2041,6 +2032,11 @@ class AlarmManagerService extends SystemService { } } @Override public void remove(PendingIntent pi) { mHandler.obtainMessage(AlarmHandler.REMOVE_FOR_CANCELED, pi).sendToTarget(); } @Override public void registerInFlightListener(InFlightListener callback) { synchronized (mLock) { Loading Loading @@ -2146,8 +2142,6 @@ class AlarmManagerService extends SystemService { synchronized (mLock) { removeLocked(operation, listener); } mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, operation).sendToTarget(); } @Override Loading Loading @@ -4151,7 +4145,7 @@ class AlarmManagerService extends SystemService { public static final int APP_STANDBY_BUCKET_CHANGED = 5; public static final int APP_STANDBY_PAROLE_CHANGED = 6; public static final int REMOVE_FOR_STOPPED = 7; public static final int UNREGISTER_CANCEL_LISTENER = 8; public static final int REMOVE_FOR_CANCELED = 8; AlarmHandler() { super(Looper.myLooper()); Loading Loading @@ -4234,10 +4228,10 @@ class AlarmManagerService extends SystemService { } break; case UNREGISTER_CANCEL_LISTENER: final PendingIntent pi = (PendingIntent) msg.obj; if (pi != null) { pi.unregisterCancelListener(mOperationCancelListener); case REMOVE_FOR_CANCELED: final PendingIntent operation = (PendingIntent) msg.obj; synchronized (mLock) { removeLocked(operation, null); } break; Loading Loading @@ -4696,11 +4690,6 @@ class AlarmManagerService extends SystemService { Intent.EXTRA_ALARM_COUNT, alarm.count), mDeliveryTracker, mHandler, null, allowWhileIdle ? mIdleOptions : null); if (alarm.repeatInterval == 0) { // Keep the listener for repeating alarms until they get cancelled mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER, alarm.operation).sendToTarget(); } } catch (PendingIntent.CanceledException e) { if (alarm.repeatInterval > 0) { // This IntentSender is no longer valid, but this Loading
services/core/java/com/android/server/am/PendingIntentController.java +3 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.util.Slog; import com.android.internal.os.IResultReceiver; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.AlarmManagerInternal; import com.android.server.LocalServices; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.SafeActivityOptions; Loading Loading @@ -293,6 +294,8 @@ public class PendingIntentController { PendingIntentController::handlePendingIntentCancelled, this, callbacks); mH.sendMessage(m); } final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class); ami.remove(new PendingIntent(rec)); } private void handlePendingIntentCancelled(RemoteCallbackList<IResultReceiver> callbacks) { Loading
services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java +18 −14 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow; Loading @@ -35,6 +36,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.AlarmManagerService.ACTIVE_INDEX; import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED; import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_PAROLE_CHANGED; import static com.android.server.AlarmManagerService.AlarmHandler.REMOVE_FOR_CANCELED; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME; import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION; Loading Loading @@ -79,9 +81,9 @@ import android.provider.Settings; import android.util.Log; import android.util.SparseArray; import androidx.test.filters.FlakyTest; import androidx.test.runner.AndroidJUnit4; import com.android.dx.mockito.inline.extended.MockedVoidMethod; import com.android.internal.annotations.GuardedBy; import org.junit.After; Loading Loading @@ -166,7 +168,6 @@ public class AlarmManagerServiceTest { } public class Injector extends AlarmManagerService.Injector { boolean mIsAutomotiveOverride; Injector(Context context) { super(context); Loading Loading @@ -256,6 +257,9 @@ public class AlarmManagerServiceTest { .when(() -> LocalServices.getService(DeviceIdleController.LocalService.class)); doReturn(mUsageStatsManagerInternal).when( () -> LocalServices.getService(UsageStatsManagerInternal.class)); doCallRealMethod().when((MockedVoidMethod) () -> LocalServices.addService(eq(AlarmManagerInternal.class), any())); doCallRealMethod().when(() -> LocalServices.getService(AlarmManagerInternal.class)); when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong())) .thenReturn(STANDBY_BUCKET_ACTIVE); Loading Loading @@ -443,7 +447,6 @@ public class AlarmManagerServiceTest { assertEquals(expectedTriggerTime, mTestTimer.getElapsed()); } @FlakyTest(bugId = 130313408) @Test public void testEarliestAlarmSet() { final PendingIntent pi6 = getNewMockPendingIntent(); Loading Loading @@ -661,11 +664,15 @@ public class AlarmManagerServiceTest { anyLong())).thenReturn(bucket); mAppStandbyListener.onAppIdleStateChanged(TEST_CALLING_PACKAGE, UserHandle.getUserId(TEST_CALLING_UID), false, bucket, 0); assertAndHandleMessageSync(APP_STANDBY_BUCKET_CHANGED); } private void assertAndHandleMessageSync(int what) { final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture()); final Message lastMessage = messageCaptor.getValue(); assertEquals("Unexpected message send to handler", lastMessage.what, APP_STANDBY_BUCKET_CHANGED); what); mService.mHandler.handleMessage(lastMessage); } Loading Loading @@ -725,12 +732,7 @@ public class AlarmManagerServiceTest { private void assertAndHandleParoleChanged(boolean parole) { mAppStandbyListener.onParoleStateChanged(parole); final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture()); final Message lastMessage = messageCaptor.getValue(); assertEquals("Unexpected message send to handler", lastMessage.what, APP_STANDBY_PAROLE_CHANGED); mService.mHandler.handleMessage(lastMessage); assertAndHandleMessageSync(APP_STANDBY_PAROLE_CHANGED); } @Test Loading Loading @@ -1033,12 +1035,13 @@ public class AlarmManagerServiceTest { } @Test public void alarmCountOnPendingIntentCancel() { public void alarmCountOnRemoveForCanceled() { final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class); final PendingIntent pi = getNewMockPendingIntent(); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 123, pi); verify(pi).registerCancelListener(mService.mOperationCancelListener); setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 12345, pi); assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); mService.mOperationCancelListener.onCancelled(pi); ami.remove(pi); assertAndHandleMessageSync(REMOVE_FOR_CANCELED); assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); } Loading @@ -1047,5 +1050,6 @@ public class AlarmManagerServiceTest { if (mMockingSession != null) { mMockingSession.finishMocking(); } LocalServices.removeServiceForTest(AlarmManagerInternal.class); } }