Copy the list before passing to deliverAlarms
Downstream code from deliverAlarmsLocked can cause removeLocked or removeImpl to be called which changes the size of the list. Test: atest FrameworksMockingServicesTests:com.android.server.alarm Bug: 175701084 Change-Id: I5228c323bb9698864c467e9e4c400459ca404b3c Merged-In: I5228c323bb9698864c467e9e4c400459ca404b3c
This commit is contained in:
@@ -3369,7 +3369,8 @@ class AlarmManagerService extends SystemService {
|
|||||||
if (mMaxDelayTime < thisDelayTime) {
|
if (mMaxDelayTime < thisDelayTime) {
|
||||||
mMaxDelayTime = thisDelayTime;
|
mMaxDelayTime = thisDelayTime;
|
||||||
}
|
}
|
||||||
deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
|
final ArrayList<Alarm> triggerList = new ArrayList<>(mPendingNonWakeupAlarms);
|
||||||
|
deliverAlarmsLocked(triggerList, nowELAPSED);
|
||||||
mPendingNonWakeupAlarms.clear();
|
mPendingNonWakeupAlarms.clear();
|
||||||
}
|
}
|
||||||
if (mNonInteractiveStartTime > 0) {
|
if (mNonInteractiveStartTime > 0) {
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ import org.mockito.MockitoSession;
|
|||||||
import org.mockito.quality.Strictness;
|
import org.mockito.quality.Strictness;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@Presubmit
|
@Presubmit
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -1077,6 +1078,38 @@ public class AlarmManagerServiceTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This tests that all non wakeup alarms are sent even when the mPendingNonWakeupAlarms gets
|
||||||
|
* modified before the send is complete. This avoids bugs like b/175701084.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void allNonWakeupAlarmsSentAtomically() throws Exception {
|
||||||
|
final int numAlarms = 5;
|
||||||
|
final AtomicInteger alarmsFired = new AtomicInteger(0);
|
||||||
|
for (int i = 0; i < numAlarms; i++) {
|
||||||
|
final IAlarmListener listener = new IAlarmListener.Stub() {
|
||||||
|
@Override
|
||||||
|
public void doAlarm(IAlarmCompleteListener callback) throws RemoteException {
|
||||||
|
alarmsFired.incrementAndGet();
|
||||||
|
mService.mPendingNonWakeupAlarms.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
setTestAlarmWithListener(ELAPSED_REALTIME, mNowElapsedTest + i + 5, listener);
|
||||||
|
}
|
||||||
|
doReturn(true).when(mService).checkAllowNonWakeupDelayLocked(anyLong());
|
||||||
|
// Advance time past all expirations.
|
||||||
|
mNowElapsedTest += numAlarms + 5;
|
||||||
|
mTestTimer.expire();
|
||||||
|
assertEquals(numAlarms, mService.mPendingNonWakeupAlarms.size());
|
||||||
|
|
||||||
|
// All of these alarms should be sent on interactive state change to true
|
||||||
|
mService.interactiveStateChangedLocked(false);
|
||||||
|
mService.interactiveStateChangedLocked(true);
|
||||||
|
|
||||||
|
assertEquals(numAlarms, alarmsFired.get());
|
||||||
|
assertEquals(0, mService.mPendingNonWakeupAlarms.size());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void alarmCountOnPendingNonWakeupAlarmsRemoved() throws Exception {
|
public void alarmCountOnPendingNonWakeupAlarmsRemoved() throws Exception {
|
||||||
final int numAlarms = 10;
|
final int numAlarms = 10;
|
||||||
|
|||||||
Reference in New Issue
Block a user