Loading services/java/com/android/server/AlarmManagerService.java +99 −38 Original line number Original line Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.util.Pair; import android.util.Slog; import android.util.Slog; import android.util.TimeUtils; import android.util.TimeUtils; import java.io.ByteArrayOutputStream; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.text.SimpleDateFormat; Loading Loading @@ -81,7 +82,8 @@ class AlarmManagerService extends IAlarmManager.Stub { private static final String TAG = "AlarmManager"; private static final String TAG = "AlarmManager"; private static final String ClockReceiver_TAG = "ClockReceiver"; private static final String ClockReceiver_TAG = "ClockReceiver"; private static final boolean localLOGV = false; private static final boolean localLOGV = false; private static final boolean DEBUG_BATCH = localLOGV || true; private static final boolean DEBUG_BATCH = localLOGV || false; private static final boolean DEBUG_VALIDATE = localLOGV || true; private static final int ALARM_EVENT = 1; private static final int ALARM_EVENT = 1; private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; Loading Loading @@ -367,14 +369,18 @@ class AlarmManagerService extends IAlarmManager.Stub { // The RTC clock has moved arbitrarily, so we need to recalculate all the batching // The RTC clock has moved arbitrarily, so we need to recalculate all the batching void rebatchAllAlarms() { void rebatchAllAlarms() { if (DEBUG_BATCH) { Slog.v(TAG, "RTC changed; rebatching"); } synchronized (mLock) { synchronized (mLock) { rebatchAllAlarmsLocked(true); } } void rebatchAllAlarmsLocked(boolean doValidate) { ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone(); ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone(); mAlarmBatches.clear(); mAlarmBatches.clear(); final long nowElapsed = SystemClock.elapsedRealtime(); final long nowElapsed = SystemClock.elapsedRealtime(); for (Batch batch : oldSet) { final int oldBatches = oldSet.size(); for (int batchNum = 0; batchNum < oldBatches; batchNum++) { Batch batch = oldSet.get(batchNum); final int N = batch.size(); final int N = batch.size(); for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) { Alarm a = batch.get(i); Alarm a = batch.get(i); Loading @@ -382,18 +388,8 @@ class AlarmManagerService extends IAlarmManager.Stub { long maxElapsed = (a.whenElapsed == a.maxWhen) long maxElapsed = (a.whenElapsed == a.maxWhen) ? whenElapsed ? whenElapsed : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval); : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval); if (batch.standalone) { // this will also be the only alarm in the batch a = new Alarm(a.type, a.when, whenElapsed, maxElapsed, a.repeatInterval, a.operation); Batch newBatch = new Batch(a); newBatch.standalone = true; addBatchLocked(mAlarmBatches, newBatch); } else { setImplLocked(a.type, a.when, whenElapsed, maxElapsed, setImplLocked(a.type, a.when, whenElapsed, maxElapsed, a.repeatInterval, a.operation, false); a.repeatInterval, a.operation, batch.standalone, doValidate); } } } } } } } } Loading Loading @@ -544,23 +540,20 @@ class AlarmManagerService extends IAlarmManager.Stub { + " interval=" + interval + " standalone=" + isStandalone); + " interval=" + interval + " standalone=" + isStandalone); } } setImplLocked(type, triggerAtTime, triggerElapsed, maxElapsed, setImplLocked(type, triggerAtTime, triggerElapsed, maxElapsed, interval, operation, isStandalone); interval, operation, isStandalone, true); } } } } private void setImplLocked(int type, long when, long whenElapsed, long maxWhen, long interval, private void setImplLocked(int type, long when, long whenElapsed, long maxWhen, long interval, PendingIntent operation, boolean isStandalone) { PendingIntent operation, boolean isStandalone, boolean doValidate) { Alarm a = new Alarm(type, when, whenElapsed, maxWhen, interval, operation); Alarm a = new Alarm(type, when, whenElapsed, maxWhen, interval, operation); removeLocked(operation); removeLocked(operation); final boolean reschedule; boolean reschedule; int whichBatch = (isStandalone) ? -1 : attemptCoalesceLocked(whenElapsed, maxWhen); int whichBatch = (isStandalone) ? -1 : attemptCoalesceLocked(whenElapsed, maxWhen); if (whichBatch < 0) { if (whichBatch < 0) { Batch batch = new Batch(a); Batch batch = new Batch(a); batch.standalone = isStandalone; batch.standalone = isStandalone; if (DEBUG_BATCH) { Slog.v(TAG, "Starting new alarm batch " + batch); } reschedule = addBatchLocked(mAlarmBatches, batch); reschedule = addBatchLocked(mAlarmBatches, batch); } else { } else { Batch batch = mAlarmBatches.get(whichBatch); Batch batch = mAlarmBatches.get(whichBatch); Loading @@ -573,11 +566,52 @@ class AlarmManagerService extends IAlarmManager.Stub { } } } } if (DEBUG_VALIDATE) { if (doValidate && validateConsistencyLocked()) { rebatchAllAlarmsLocked(false); reschedule = true; } } if (reschedule) { if (reschedule) { rescheduleKernelAlarmsLocked(); rescheduleKernelAlarmsLocked(); } } } } private void logBatchesLocked() { ByteArrayOutputStream bs = new ByteArrayOutputStream(2048); PrintWriter pw = new PrintWriter(bs); final long nowRTC = System.currentTimeMillis(); final long nowELAPSED = SystemClock.elapsedRealtime(); final int NZ = mAlarmBatches.size(); for (int iz = 0; iz < NZ; iz++) { Batch bz = mAlarmBatches.get(iz); Slog.v(TAG, "Batch " + iz + ": " + bz); dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC); Slog.v(TAG, bs.toString()); bs.reset(); } } private boolean validateConsistencyLocked() { if (DEBUG_VALIDATE) { long lastTime = Long.MIN_VALUE; final int N = mAlarmBatches.size(); for (int i = 0; i < N; i++) { Batch b = mAlarmBatches.get(i); if (b.start >= lastTime) { // duplicate start times are okay because of standalone batches lastTime = b.start; } else { Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order"); logBatchesLocked(); return false; } } } return true; } private Batch findFirstWakeupBatchLocked() { private Batch findFirstWakeupBatchLocked() { final int N = mAlarmBatches.size(); final int N = mAlarmBatches.size(); for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) { Loading Loading @@ -663,33 +697,60 @@ class AlarmManagerService extends IAlarmManager.Stub { } } public void removeLocked(PendingIntent operation) { public void removeLocked(PendingIntent operation) { boolean didRemove = false; for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); Batch b = mAlarmBatches.get(i); b.remove(operation); didRemove |= b.remove(operation); if (b.size() == 0) { if (b.size() == 0) { mAlarmBatches.remove(i); mAlarmBatches.remove(i); } } } } if (didRemove) { if (DEBUG_BATCH) { Slog.v(TAG, "remove(operation) changed bounds; rebatching"); } rebatchAllAlarmsLocked(true); rescheduleKernelAlarmsLocked(); } } } public void removeLocked(String packageName) { public void removeLocked(String packageName) { boolean didRemove = false; for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); Batch b = mAlarmBatches.get(i); b.remove(packageName); didRemove |= b.remove(packageName); if (b.size() == 0) { if (b.size() == 0) { mAlarmBatches.remove(i); mAlarmBatches.remove(i); } } } } if (didRemove) { if (DEBUG_BATCH) { Slog.v(TAG, "remove(package) changed bounds; rebatching"); } rebatchAllAlarmsLocked(true); rescheduleKernelAlarmsLocked(); } } } public void removeUserLocked(int userHandle) { public void removeUserLocked(int userHandle) { boolean didRemove = false; for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); Batch b = mAlarmBatches.get(i); b.remove(userHandle); didRemove |= b.remove(userHandle); if (b.size() == 0) { if (b.size() == 0) { mAlarmBatches.remove(i); mAlarmBatches.remove(i); } } } } if (didRemove) { if (DEBUG_BATCH) { Slog.v(TAG, "remove(user) changed bounds; rebatching"); } rebatchAllAlarmsLocked(true); rescheduleKernelAlarmsLocked(); } } } public boolean lookForPackageLocked(String packageName) { public boolean lookForPackageLocked(String packageName) { Loading Loading @@ -962,7 +1023,7 @@ class AlarmManagerService extends IAlarmManager.Stub { final long nextElapsed = alarm.whenElapsed + delta; final long nextElapsed = alarm.whenElapsed + delta; setImplLocked(alarm.type, alarm.when + delta, nextElapsed, setImplLocked(alarm.type, alarm.when + delta, nextElapsed, maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval), maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval), alarm.repeatInterval, alarm.operation, batch.standalone); alarm.repeatInterval, alarm.operation, batch.standalone, true); } } } } Loading Loading @@ -1067,7 +1128,7 @@ class AlarmManagerService extends IAlarmManager.Stub { if ((result & TIME_CHANGED_MASK) != 0) { if ((result & TIME_CHANGED_MASK) != 0) { if (DEBUG_BATCH) { if (DEBUG_BATCH) { Slog.v(TAG, "Time changed notification from kernel"); Slog.v(TAG, "Time changed notification from kernel; rebatching"); } } remove(mTimeTickSender); remove(mTimeTickSender); rebatchAllAlarms(); rebatchAllAlarms(); Loading Loading
services/java/com/android/server/AlarmManagerService.java +99 −38 Original line number Original line Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.util.Pair; import android.util.Slog; import android.util.Slog; import android.util.TimeUtils; import android.util.TimeUtils; import java.io.ByteArrayOutputStream; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.text.SimpleDateFormat; Loading Loading @@ -81,7 +82,8 @@ class AlarmManagerService extends IAlarmManager.Stub { private static final String TAG = "AlarmManager"; private static final String TAG = "AlarmManager"; private static final String ClockReceiver_TAG = "ClockReceiver"; private static final String ClockReceiver_TAG = "ClockReceiver"; private static final boolean localLOGV = false; private static final boolean localLOGV = false; private static final boolean DEBUG_BATCH = localLOGV || true; private static final boolean DEBUG_BATCH = localLOGV || false; private static final boolean DEBUG_VALIDATE = localLOGV || true; private static final int ALARM_EVENT = 1; private static final int ALARM_EVENT = 1; private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; private static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; Loading Loading @@ -367,14 +369,18 @@ class AlarmManagerService extends IAlarmManager.Stub { // The RTC clock has moved arbitrarily, so we need to recalculate all the batching // The RTC clock has moved arbitrarily, so we need to recalculate all the batching void rebatchAllAlarms() { void rebatchAllAlarms() { if (DEBUG_BATCH) { Slog.v(TAG, "RTC changed; rebatching"); } synchronized (mLock) { synchronized (mLock) { rebatchAllAlarmsLocked(true); } } void rebatchAllAlarmsLocked(boolean doValidate) { ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone(); ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone(); mAlarmBatches.clear(); mAlarmBatches.clear(); final long nowElapsed = SystemClock.elapsedRealtime(); final long nowElapsed = SystemClock.elapsedRealtime(); for (Batch batch : oldSet) { final int oldBatches = oldSet.size(); for (int batchNum = 0; batchNum < oldBatches; batchNum++) { Batch batch = oldSet.get(batchNum); final int N = batch.size(); final int N = batch.size(); for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) { Alarm a = batch.get(i); Alarm a = batch.get(i); Loading @@ -382,18 +388,8 @@ class AlarmManagerService extends IAlarmManager.Stub { long maxElapsed = (a.whenElapsed == a.maxWhen) long maxElapsed = (a.whenElapsed == a.maxWhen) ? whenElapsed ? whenElapsed : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval); : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval); if (batch.standalone) { // this will also be the only alarm in the batch a = new Alarm(a.type, a.when, whenElapsed, maxElapsed, a.repeatInterval, a.operation); Batch newBatch = new Batch(a); newBatch.standalone = true; addBatchLocked(mAlarmBatches, newBatch); } else { setImplLocked(a.type, a.when, whenElapsed, maxElapsed, setImplLocked(a.type, a.when, whenElapsed, maxElapsed, a.repeatInterval, a.operation, false); a.repeatInterval, a.operation, batch.standalone, doValidate); } } } } } } } } Loading Loading @@ -544,23 +540,20 @@ class AlarmManagerService extends IAlarmManager.Stub { + " interval=" + interval + " standalone=" + isStandalone); + " interval=" + interval + " standalone=" + isStandalone); } } setImplLocked(type, triggerAtTime, triggerElapsed, maxElapsed, setImplLocked(type, triggerAtTime, triggerElapsed, maxElapsed, interval, operation, isStandalone); interval, operation, isStandalone, true); } } } } private void setImplLocked(int type, long when, long whenElapsed, long maxWhen, long interval, private void setImplLocked(int type, long when, long whenElapsed, long maxWhen, long interval, PendingIntent operation, boolean isStandalone) { PendingIntent operation, boolean isStandalone, boolean doValidate) { Alarm a = new Alarm(type, when, whenElapsed, maxWhen, interval, operation); Alarm a = new Alarm(type, when, whenElapsed, maxWhen, interval, operation); removeLocked(operation); removeLocked(operation); final boolean reschedule; boolean reschedule; int whichBatch = (isStandalone) ? -1 : attemptCoalesceLocked(whenElapsed, maxWhen); int whichBatch = (isStandalone) ? -1 : attemptCoalesceLocked(whenElapsed, maxWhen); if (whichBatch < 0) { if (whichBatch < 0) { Batch batch = new Batch(a); Batch batch = new Batch(a); batch.standalone = isStandalone; batch.standalone = isStandalone; if (DEBUG_BATCH) { Slog.v(TAG, "Starting new alarm batch " + batch); } reschedule = addBatchLocked(mAlarmBatches, batch); reschedule = addBatchLocked(mAlarmBatches, batch); } else { } else { Batch batch = mAlarmBatches.get(whichBatch); Batch batch = mAlarmBatches.get(whichBatch); Loading @@ -573,11 +566,52 @@ class AlarmManagerService extends IAlarmManager.Stub { } } } } if (DEBUG_VALIDATE) { if (doValidate && validateConsistencyLocked()) { rebatchAllAlarmsLocked(false); reschedule = true; } } if (reschedule) { if (reschedule) { rescheduleKernelAlarmsLocked(); rescheduleKernelAlarmsLocked(); } } } } private void logBatchesLocked() { ByteArrayOutputStream bs = new ByteArrayOutputStream(2048); PrintWriter pw = new PrintWriter(bs); final long nowRTC = System.currentTimeMillis(); final long nowELAPSED = SystemClock.elapsedRealtime(); final int NZ = mAlarmBatches.size(); for (int iz = 0; iz < NZ; iz++) { Batch bz = mAlarmBatches.get(iz); Slog.v(TAG, "Batch " + iz + ": " + bz); dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC); Slog.v(TAG, bs.toString()); bs.reset(); } } private boolean validateConsistencyLocked() { if (DEBUG_VALIDATE) { long lastTime = Long.MIN_VALUE; final int N = mAlarmBatches.size(); for (int i = 0; i < N; i++) { Batch b = mAlarmBatches.get(i); if (b.start >= lastTime) { // duplicate start times are okay because of standalone batches lastTime = b.start; } else { Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order"); logBatchesLocked(); return false; } } } return true; } private Batch findFirstWakeupBatchLocked() { private Batch findFirstWakeupBatchLocked() { final int N = mAlarmBatches.size(); final int N = mAlarmBatches.size(); for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) { Loading Loading @@ -663,33 +697,60 @@ class AlarmManagerService extends IAlarmManager.Stub { } } public void removeLocked(PendingIntent operation) { public void removeLocked(PendingIntent operation) { boolean didRemove = false; for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); Batch b = mAlarmBatches.get(i); b.remove(operation); didRemove |= b.remove(operation); if (b.size() == 0) { if (b.size() == 0) { mAlarmBatches.remove(i); mAlarmBatches.remove(i); } } } } if (didRemove) { if (DEBUG_BATCH) { Slog.v(TAG, "remove(operation) changed bounds; rebatching"); } rebatchAllAlarmsLocked(true); rescheduleKernelAlarmsLocked(); } } } public void removeLocked(String packageName) { public void removeLocked(String packageName) { boolean didRemove = false; for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); Batch b = mAlarmBatches.get(i); b.remove(packageName); didRemove |= b.remove(packageName); if (b.size() == 0) { if (b.size() == 0) { mAlarmBatches.remove(i); mAlarmBatches.remove(i); } } } } if (didRemove) { if (DEBUG_BATCH) { Slog.v(TAG, "remove(package) changed bounds; rebatching"); } rebatchAllAlarmsLocked(true); rescheduleKernelAlarmsLocked(); } } } public void removeUserLocked(int userHandle) { public void removeUserLocked(int userHandle) { boolean didRemove = false; for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); Batch b = mAlarmBatches.get(i); b.remove(userHandle); didRemove |= b.remove(userHandle); if (b.size() == 0) { if (b.size() == 0) { mAlarmBatches.remove(i); mAlarmBatches.remove(i); } } } } if (didRemove) { if (DEBUG_BATCH) { Slog.v(TAG, "remove(user) changed bounds; rebatching"); } rebatchAllAlarmsLocked(true); rescheduleKernelAlarmsLocked(); } } } public boolean lookForPackageLocked(String packageName) { public boolean lookForPackageLocked(String packageName) { Loading Loading @@ -962,7 +1023,7 @@ class AlarmManagerService extends IAlarmManager.Stub { final long nextElapsed = alarm.whenElapsed + delta; final long nextElapsed = alarm.whenElapsed + delta; setImplLocked(alarm.type, alarm.when + delta, nextElapsed, setImplLocked(alarm.type, alarm.when + delta, nextElapsed, maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval), maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval), alarm.repeatInterval, alarm.operation, batch.standalone); alarm.repeatInterval, alarm.operation, batch.standalone, true); } } } } Loading Loading @@ -1067,7 +1128,7 @@ class AlarmManagerService extends IAlarmManager.Stub { if ((result & TIME_CHANGED_MASK) != 0) { if ((result & TIME_CHANGED_MASK) != 0) { if (DEBUG_BATCH) { if (DEBUG_BATCH) { Slog.v(TAG, "Time changed notification from kernel"); Slog.v(TAG, "Time changed notification from kernel; rebatching"); } } remove(mTimeTickSender); remove(mTimeTickSender); rebatchAllAlarms(); rebatchAllAlarms(); Loading