16b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock/* 26b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * Copyright (C) 2014 The Android Open Source Project 36b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * 46b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License"); 56b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * you may not use this file except in compliance with the License. 66b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * You may obtain a copy of the License at 76b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * 86b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * http://www.apache.org/licenses/LICENSE-2.0 96b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * 106b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * Unless required by applicable law or agreed to in writing, software 116b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS, 126b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * See the License for the specific language governing permissions and 146b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock * limitations under the License. 156b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock */ 166b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 176b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockpackage com.android.server.notification; 186b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 196b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.app.ActivityManager; 206b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.app.AlarmManager; 216b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.app.AlarmManager.AlarmClockInfo; 226b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.app.PendingIntent; 236b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.content.BroadcastReceiver; 246b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.content.Context; 256b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.content.Intent; 266b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.content.IntentFilter; 276b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.os.Handler; 286b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.os.Message; 296b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.os.PowerManager; 306b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.os.UserHandle; 316b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.text.format.DateFormat; 326b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.util.Log; 336b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.util.Slog; 346b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport android.util.TimeUtils; 356b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 366b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport com.android.server.notification.NotificationManagerService.DumpFilter; 376b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 386b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport java.io.PrintWriter; 396b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport java.util.ArrayList; 406b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockimport java.util.Locale; 416b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 426b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock/** Helper for tracking updates to the current user's next alarm. */ 436b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlockpublic class NextAlarmTracker { 446b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final String TAG = "NextAlarmTracker"; 456b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 466b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 476b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final String ACTION_TRIGGER = TAG + ".trigger"; 486b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final String EXTRA_TRIGGER = "trigger"; 496b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final int REQUEST_CODE = 100; 506b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 516b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final long SECONDS = 1000; 526b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final long MINUTES = 60 * SECONDS; 536b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final long NEXT_ALARM_UPDATE_DELAY = 1 * SECONDS; // treat clear+set as update 546b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final long EARLY = 5 * SECONDS; // fire early, ensure alarm stream is unmuted 556b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final long WAIT_AFTER_INIT = 5 * MINUTES;// for initial alarm re-registration 566b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final long WAIT_AFTER_BOOT = 20 * SECONDS; // for initial alarm re-registration 576b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 586b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private final Context mContext; 596b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private final H mHandler = new H(); 606b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); 616b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 626b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private long mInit; 636b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private boolean mRegistered; 646b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private AlarmManager mAlarmManager; 656b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private int mCurrentUserId; 666b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private long mScheduledAlarmTime; 676b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private long mBootCompleted; 686b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private PowerManager.WakeLock mWakeLock; 696b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 706b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public NextAlarmTracker(Context context) { 716b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mContext = context; 726b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 736b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 746b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public void dump(PrintWriter pw, DumpFilter filter) { 756b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock pw.println(" NextAlarmTracker:"); 766b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock pw.print(" len(mCallbacks)="); pw.println(mCallbacks.size()); 776b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock pw.print(" mRegistered="); pw.println(mRegistered); 786b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock pw.print(" mInit="); pw.println(mInit); 796b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock pw.print(" mBootCompleted="); pw.println(mBootCompleted); 806b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock pw.print(" mCurrentUserId="); pw.println(mCurrentUserId); 816b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock pw.print(" mScheduledAlarmTime="); pw.println(formatAlarmDebug(mScheduledAlarmTime)); 826b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock pw.print(" mWakeLock="); pw.println(mWakeLock); 836b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 846b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 856b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public void addCallback(Callback callback) { 866b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mCallbacks.add(callback); 876b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 886b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 896b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public void removeCallback(Callback callback) { 906b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mCallbacks.remove(callback); 916b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 926b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 936b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public int getCurrentUserId() { 946b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock return mCurrentUserId; 956b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 966b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 976b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public AlarmClockInfo getNextAlarm() { 986b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock return mAlarmManager.getNextAlarmClock(mCurrentUserId); 996b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1006b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1016b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public void onUserSwitched() { 1026b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock reset(); 1036b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1046b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1056b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public void init() { 1066b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 1076b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final PowerManager p = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 1086b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mWakeLock = p.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 1096b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mInit = System.currentTimeMillis(); 1106b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock reset(); 1116b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1126b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1136b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public void reset() { 1146b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (mRegistered) { 1156b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mContext.unregisterReceiver(mReceiver); 1166b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1176b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mCurrentUserId = ActivityManager.getCurrentUser(); 1186b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final IntentFilter filter = new IntentFilter(); 1196b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED); 1206b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock filter.addAction(ACTION_TRIGGER); 1216b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock filter.addAction(Intent.ACTION_TIME_CHANGED); 1226b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 1236b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock filter.addAction(Intent.ACTION_BOOT_COMPLETED); 1246b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mContext.registerReceiverAsUser(mReceiver, new UserHandle(mCurrentUserId), filter, null, 1256b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock null); 1266b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mRegistered = true; 1276b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock evaluate(); 1286b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1296b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1306b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public void destroy() { 1316b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (mRegistered) { 1326b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mContext.unregisterReceiver(mReceiver); 1336b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mRegistered = false; 1346b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1356b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1366b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1376b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public void evaluate() { 1386b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mHandler.postEvaluate(0); 1396b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1406b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1416b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private void fireEvaluate(AlarmClockInfo nextAlarm, long wakeupTime, boolean booted) { 1426b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock for (Callback callback : mCallbacks) { 1436b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock callback.onEvaluate(nextAlarm, wakeupTime, booted); 1446b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1456b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1466b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1476b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private void handleEvaluate() { 1486b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final AlarmClockInfo nextAlarm = mAlarmManager.getNextAlarmClock(mCurrentUserId); 1496b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final long triggerTime = getEarlyTriggerTime(nextAlarm); 1506b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final long now = System.currentTimeMillis(); 1516b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final boolean alarmUpcoming = triggerTime > now; 1526b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final boolean booted = isDoneWaitingAfterBoot(now); 1536b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (DEBUG) Slog.d(TAG, "handleEvaluate nextAlarm=" + formatAlarmDebug(triggerTime) 1546b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock + " alarmUpcoming=" + alarmUpcoming 1556b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock + " booted=" + booted); 1566b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock fireEvaluate(nextAlarm, triggerTime, booted); 1576b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (!booted) { 1586b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock // recheck after boot 1596b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final long recheckTime = (mBootCompleted > 0 ? mBootCompleted : now) + WAIT_AFTER_BOOT; 1606b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock rescheduleAlarm(recheckTime); 1616b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock return; 1626b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1636b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (alarmUpcoming) { 1646b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock // wake up just before the next alarm 1656b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock rescheduleAlarm(triggerTime); 1666b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1676b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1686b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1696b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public static long getEarlyTriggerTime(AlarmClockInfo alarm) { 1706b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock return alarm != null ? (alarm.getTriggerTime() - EARLY) : 0; 1716b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1726b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1736b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private boolean isDoneWaitingAfterBoot(long time) { 1746b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (mBootCompleted > 0) return (time - mBootCompleted) > WAIT_AFTER_BOOT; 1756b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (mInit > 0) return (time - mInit) > WAIT_AFTER_INIT; 1766b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock return true; 1776b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1786b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1793c984d67ebf07e1215c6b403f0e18e309f2604e9John Spurlock public static String formatDuration(long millis) { 1806b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final StringBuilder sb = new StringBuilder(); 1816b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock TimeUtils.formatDuration(millis, sb); 1826b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock return sb.toString(); 1836b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1846b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1856b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public String formatAlarm(AlarmClockInfo alarm) { 1866b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock return alarm != null ? formatAlarm(alarm.getTriggerTime()) : null; 1876b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1886b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1896b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private String formatAlarm(long time) { 1906b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock return formatAlarm(time, "Hm", "hma"); 1916b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1926b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1936b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private String formatAlarm(long time, String skeleton24, String skeleton12) { 1946b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final String skeleton = DateFormat.is24HourFormat(mContext) ? skeleton24 : skeleton12; 1956b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton); 1966b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock return DateFormat.format(pattern, time).toString(); 1976b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 1986b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 1993c984d67ebf07e1215c6b403f0e18e309f2604e9John Spurlock public String formatAlarmDebug(AlarmClockInfo alarm) { 2006b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock return formatAlarmDebug(alarm != null ? alarm.getTriggerTime() : 0); 2016b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 2026b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 2036b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public String formatAlarmDebug(long time) { 2046b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (time <= 0) return Long.toString(time); 2056b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock return String.format("%s (%s)", time, formatAlarm(time, "Hms", "hmsa")); 2066b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 2076b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 2086b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private void rescheduleAlarm(long time) { 2096b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (DEBUG) Slog.d(TAG, "rescheduleAlarm " + time); 2106b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final AlarmManager alarms = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 2116b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, REQUEST_CODE, 2126b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock new Intent(ACTION_TRIGGER) 2136b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock .addFlags(Intent.FLAG_RECEIVER_FOREGROUND) 2146b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock .putExtra(EXTRA_TRIGGER, time), 2156b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock PendingIntent.FLAG_UPDATE_CURRENT); 2166b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock alarms.cancel(pendingIntent); 2176b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mScheduledAlarmTime = time; 2186b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (time > 0) { 2196b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (DEBUG) Slog.d(TAG, String.format("Scheduling alarm for %s (in %s)", 2206b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock formatAlarmDebug(time), formatDuration(time - System.currentTimeMillis()))); 2216b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent); 2226b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 2236b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 2246b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 2256b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 2266b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock @Override 2276b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public void onReceive(Context context, Intent intent) { 2286b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock final String action = intent.getAction(); 2296b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (DEBUG) Slog.d(TAG, "onReceive " + action); 2306b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock long delay = 0; 2316b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (action.equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) { 2326b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock delay = NEXT_ALARM_UPDATE_DELAY; 2336b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (DEBUG) Slog.d(TAG, String.format(" next alarm for user %s: %s", 2346b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mCurrentUserId, 2356b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock formatAlarmDebug(mAlarmManager.getNextAlarmClock(mCurrentUserId)))); 2366b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 2376b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mBootCompleted = System.currentTimeMillis(); 2386b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 2396b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mHandler.postEvaluate(delay); 2406b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock mWakeLock.acquire(delay + 5000); // stay awake during evaluate 2416b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 2426b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock }; 2436b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 2446b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private class H extends Handler { 2456b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock private static final int MSG_EVALUATE = 1; 2466b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 2476b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public void postEvaluate(long delay) { 2486b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock removeMessages(MSG_EVALUATE); 2496b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock sendEmptyMessageDelayed(MSG_EVALUATE, delay); 2506b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 2516b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 2526b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock @Override 2536b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public void handleMessage(Message msg) { 2546b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock if (msg.what == MSG_EVALUATE) { 2556b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock handleEvaluate(); 2566b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 2576b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 2586b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 2596b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock 2606b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock public interface Callback { 2616b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock void onEvaluate(AlarmClockInfo nextAlarm, long wakeupTime, boolean booted); 2626b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock } 2636b0623a1129a7e1bc4949b7dca4fa133ff322c4aJohn Spurlock} 264