blob: 5b0dc0f6a0aacc70629ef97dca0022d464865a10 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080019import android.app.Activity;
Adrian Roosc42a1e12014-07-07 23:35:53 +020020import android.app.ActivityManager;
Christopher Tate57ceaaa2013-07-19 16:30:43 -070021import android.app.AlarmManager;
Christopher Tate14a7bb02015-10-01 10:24:31 -070022import android.app.AppOpsManager;
Dianne Hackborna750a632015-06-16 17:18:23 -070023import android.app.BroadcastOptions;
Christopher Tate14a7bb02015-10-01 10:24:31 -070024import android.app.IAlarmCompleteListener;
25import android.app.IAlarmListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.app.IAlarmManager;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070027import android.app.IUidObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.app.PendingIntent;
29import android.content.BroadcastReceiver;
Dianne Hackborna750a632015-06-16 17:18:23 -070030import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.content.Context;
32import android.content.Intent;
33import android.content.IntentFilter;
Christopher Tatebb9cce52017-04-18 14:19:43 -070034import android.content.pm.ApplicationInfo;
35import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.content.pm.PackageManager;
Christopher Tatebb9cce52017-04-18 14:19:43 -070037import android.content.pm.PackageManager.NameNotFoundException;
38import android.content.pm.PermissionInfo;
Dianne Hackborna750a632015-06-16 17:18:23 -070039import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.net.Uri;
41import android.os.Binder;
42import android.os.Bundle;
Christopher Tate247571462017-04-10 11:45:05 -070043import android.os.Environment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.os.Handler;
Adam Lesinski182f73f2013-12-05 16:48:06 -080045import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.os.Message;
47import android.os.PowerManager;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -070048import android.os.Process;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070049import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.os.SystemClock;
51import android.os.SystemProperties;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070052import android.os.UserHandle;
Christopher Tatec4a07d12012-04-06 14:19:13 -070053import android.os.WorkSource;
Adrian Roosc42a1e12014-07-07 23:35:53 +020054import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.text.TextUtils;
Adrian Roosc42a1e12014-07-07 23:35:53 +020056import android.text.format.DateFormat;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080057import android.util.ArrayMap;
Dianne Hackborna750a632015-06-16 17:18:23 -070058import android.util.KeyValueListParser;
Adrian Roosc42a1e12014-07-07 23:35:53 +020059import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080060import android.util.Slog;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080061import android.util.SparseArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +020062import android.util.SparseBooleanArray;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -070063import android.util.SparseLongArray;
Dianne Hackborn043fcd92010-10-06 14:27:34 -070064import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065
Christopher Tate4cb338d2013-07-26 13:11:31 -070066import java.io.ByteArrayOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import java.io.FileDescriptor;
68import java.io.PrintWriter;
Dianne Hackborn043fcd92010-10-06 14:27:34 -070069import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import java.util.ArrayList;
Dianne Hackborn81038902012-11-26 17:04:09 -080071import java.util.Arrays;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import java.util.Calendar;
73import java.util.Collections;
74import java.util.Comparator;
Mike Lockwood1f7b4132009-11-20 15:12:51 -050075import java.util.Date;
Christopher Tate1590f1e2014-10-02 17:27:57 -070076import java.util.HashMap;
Christopher Tate18a75f12013-07-01 18:18:59 -070077import java.util.LinkedList;
Adrian Roosc42a1e12014-07-07 23:35:53 +020078import java.util.Locale;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -070079import java.util.Random;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import java.util.TimeZone;
John Spurlock604a5ee2015-06-01 12:27:22 -040081import java.util.TreeSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082
Christopher Tatee0a22b32013-07-11 14:43:13 -070083import static android.app.AlarmManager.RTC_WAKEUP;
84import static android.app.AlarmManager.RTC;
85import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
86import static android.app.AlarmManager.ELAPSED_REALTIME;
87
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060088import com.android.internal.util.DumpUtils;
Dianne Hackborn81038902012-11-26 17:04:09 -080089import com.android.internal.util.LocalLog;
90
Adam Lesinski182f73f2013-12-05 16:48:06 -080091class AlarmManagerService extends SystemService {
Christopher Tatee0a22b32013-07-11 14:43:13 -070092 private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
93 private static final int RTC_MASK = 1 << RTC;
Adam Lesinski182f73f2013-12-05 16:48:06 -080094 private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -070095 private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
Adam Lesinski182f73f2013-12-05 16:48:06 -080096 static final int TIME_CHANGED_MASK = 1 << 16;
97 static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
Christopher Tateb8849c12011-02-08 13:39:01 -080098
Christopher Tatee0a22b32013-07-11 14:43:13 -070099 // Mask for testing whether a given alarm type is wakeup vs non-wakeup
Adam Lesinski182f73f2013-12-05 16:48:06 -0800100 static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
Christopher Tateb8849c12011-02-08 13:39:01 -0800101
Adam Lesinski182f73f2013-12-05 16:48:06 -0800102 static final String TAG = "AlarmManager";
Adam Lesinski182f73f2013-12-05 16:48:06 -0800103 static final boolean localLOGV = false;
104 static final boolean DEBUG_BATCH = localLOGV || false;
105 static final boolean DEBUG_VALIDATE = localLOGV || false;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200106 static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700107 static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
Makoto Onuki3e7d8452017-03-02 15:33:17 -0800108 static final boolean DEBUG_WAKELOCK = localLOGV || false;
Dianne Hackborn1e383822015-04-10 14:02:33 -0700109 static final boolean RECORD_ALARMS_IN_HISTORY = true;
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700110 static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800111 static final int ALARM_EVENT = 1;
112 static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
Adrian Roosc42a1e12014-07-07 23:35:53 +0200113
Christopher Tate14a7bb02015-10-01 10:24:31 -0700114 private final Intent mBackgroundIntent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800116 static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117
Adam Lesinski182f73f2013-12-05 16:48:06 -0800118 static final boolean WAKEUP_STATS = false;
Christopher Tate18a75f12013-07-01 18:18:59 -0700119
Christopher Tate24cd46f2016-02-02 14:28:01 -0800120 private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT =
121 new Intent(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)
122 .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Adrian Roosc42a1e12014-07-07 23:35:53 +0200123
Adam Lesinski182f73f2013-12-05 16:48:06 -0800124 final LocalLog mLog = new LocalLog(TAG);
Dianne Hackborn81038902012-11-26 17:04:09 -0800125
Christopher Tate14a7bb02015-10-01 10:24:31 -0700126 AppOpsManager mAppOps;
Dianne Hackborn627dfa12015-11-11 18:10:30 -0800127 DeviceIdleController.LocalService mLocalDeviceIdleController;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700128
Adam Lesinski182f73f2013-12-05 16:48:06 -0800129 final Object mLock = new Object();
Dianne Hackborn81038902012-11-26 17:04:09 -0800130
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -0800131 long mNativeData;
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800132 private long mNextWakeup;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700133 private long mNextNonWakeup;
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -0700134 private long mLastWakeupSet;
135 private long mLastWakeup;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800136 int mBroadcastRefCount = 0;
137 PowerManager.WakeLock mWakeLock;
Dianne Hackborna1bd7922014-03-21 11:07:11 -0700138 boolean mLastWakeLockUnimportantForLogging;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700139 ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
140 ArrayList<InFlight> mInFlight = new ArrayList<>();
Adam Lesinski182f73f2013-12-05 16:48:06 -0800141 final AlarmHandler mHandler = new AlarmHandler();
142 ClockReceiver mClockReceiver;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700143 InteractiveStateReceiver mInteractiveStateReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 private UninstallReceiver mUninstallReceiver;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700145 final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
Adam Lesinski182f73f2013-12-05 16:48:06 -0800146 PendingIntent mTimeTickSender;
147 PendingIntent mDateChangeSender;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700148 Random mRandom;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700149 boolean mInteractive = true;
150 long mNonInteractiveStartTime;
151 long mNonInteractiveTime;
152 long mLastAlarmDeliveryTime;
153 long mStartCurrentDelayTime;
154 long mNextNonWakeupDeliveryTime;
Dianne Hackbornc3527222015-05-13 14:03:20 -0700155 long mLastTimeChangeClockTime;
156 long mLastTimeChangeRealtime;
Dianne Hackborna750a632015-06-16 17:18:23 -0700157 long mAllowWhileIdleMinTime;
Dianne Hackborn998e6082014-09-11 19:13:23 -0700158 int mNumTimeChanged;
Dianne Hackborn81038902012-11-26 17:04:09 -0800159
Christopher Tatebb9cce52017-04-18 14:19:43 -0700160 // Bookkeeping about the identity of the "System UI" package, determined at runtime.
161
162 /**
163 * This permission must be defined by the canonical System UI package,
164 * with protection level "signature".
165 */
166 private static final String SYSTEM_UI_SELF_PERMISSION =
167 "android.permission.systemui.IDENTITY";
168
169 /**
170 * At boot we use SYSTEM_UI_SELF_PERMISSION to look up the definer's uid.
171 */
172 int mSystemUiUid;
173
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700174 /**
Dianne Hackborn262ae5c2016-02-10 16:28:29 -0800175 * The current set of user whitelisted apps for device idle mode, meaning these are allowed
176 * to freely schedule alarms.
177 */
178 int[] mDeviceIdleUserWhitelist = new int[0];
179
180 /**
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700181 * For each uid, this is the last time we dispatched an "allow while idle" alarm,
182 * used to determine the earliest we can dispatch the next such alarm.
183 */
184 final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
185
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700186 final static class IdleDispatchEntry {
187 int uid;
188 String pkg;
189 String tag;
190 String op;
191 long elapsedRealtime;
192 long argRealtime;
193 }
194 final ArrayList<IdleDispatchEntry> mAllowWhileIdleDispatches = new ArrayList();
195
Dianne Hackborna750a632015-06-16 17:18:23 -0700196 /**
197 * Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
198 */
199 Bundle mIdleOptions;
200
Jose Lima235510e2014-08-13 12:50:01 -0700201 private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
202 new SparseArray<>();
203 private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
204 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200205 private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
206 new SparseBooleanArray();
207 private boolean mNextAlarmClockMayChange;
208
209 // May only use on mHandler's thread, locking not required.
Jose Lima235510e2014-08-13 12:50:01 -0700210 private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
211 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200212
Dianne Hackborna750a632015-06-16 17:18:23 -0700213 /**
214 * All times are in milliseconds. These constants are kept synchronized with the system
215 * global Settings. Any access to this class or its fields should be done while
216 * holding the AlarmManagerService.mLock lock.
217 */
218 private final class Constants extends ContentObserver {
219 // Key names stored in the settings value.
220 private static final String KEY_MIN_FUTURITY = "min_futurity";
221 private static final String KEY_MIN_INTERVAL = "min_interval";
222 private static final String KEY_ALLOW_WHILE_IDLE_SHORT_TIME = "allow_while_idle_short_time";
223 private static final String KEY_ALLOW_WHILE_IDLE_LONG_TIME = "allow_while_idle_long_time";
224 private static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
225 = "allow_while_idle_whitelist_duration";
Christopher Tate14a7bb02015-10-01 10:24:31 -0700226 private static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
Dianne Hackborna750a632015-06-16 17:18:23 -0700227
228 private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
229 private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
Christopher Tateaa244da2015-08-27 15:57:57 -0700230 private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
Dianne Hackborn7682b262015-10-26 17:51:57 -0700231 private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000;
Dianne Hackborna750a632015-06-16 17:18:23 -0700232 private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
233
Christopher Tate14a7bb02015-10-01 10:24:31 -0700234 private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
235
Dianne Hackborna750a632015-06-16 17:18:23 -0700236 // Minimum futurity of a new alarm
237 public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
238
239 // Minimum alarm recurrence interval
240 public long MIN_INTERVAL = DEFAULT_MIN_INTERVAL;
241
242 // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
243 public long ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME;
244
245 // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
246 public long ALLOW_WHILE_IDLE_LONG_TIME = DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME;
247
248 // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
249 public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
250 = DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
251
Christopher Tate14a7bb02015-10-01 10:24:31 -0700252 // Direct alarm listener callback timeout
253 public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
254
Dianne Hackborna750a632015-06-16 17:18:23 -0700255 private ContentResolver mResolver;
256 private final KeyValueListParser mParser = new KeyValueListParser(',');
257 private long mLastAllowWhileIdleWhitelistDuration = -1;
258
259 public Constants(Handler handler) {
260 super(handler);
261 updateAllowWhileIdleMinTimeLocked();
262 updateAllowWhileIdleWhitelistDurationLocked();
263 }
264
265 public void start(ContentResolver resolver) {
266 mResolver = resolver;
267 mResolver.registerContentObserver(Settings.Global.getUriFor(
268 Settings.Global.ALARM_MANAGER_CONSTANTS), false, this);
269 updateConstants();
270 }
271
272 public void updateAllowWhileIdleMinTimeLocked() {
273 mAllowWhileIdleMinTime = mPendingIdleUntil != null
274 ? ALLOW_WHILE_IDLE_LONG_TIME : ALLOW_WHILE_IDLE_SHORT_TIME;
275 }
276
277 public void updateAllowWhileIdleWhitelistDurationLocked() {
278 if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
279 mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
280 BroadcastOptions opts = BroadcastOptions.makeBasic();
281 opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
282 mIdleOptions = opts.toBundle();
283 }
284 }
285
286 @Override
287 public void onChange(boolean selfChange, Uri uri) {
288 updateConstants();
289 }
290
291 private void updateConstants() {
292 synchronized (mLock) {
293 try {
294 mParser.setString(Settings.Global.getString(mResolver,
295 Settings.Global.ALARM_MANAGER_CONSTANTS));
296 } catch (IllegalArgumentException e) {
297 // Failed to parse the settings string, log this and move on
298 // with defaults.
Dianne Hackborn0ef403e2017-01-24 18:22:15 -0800299 Slog.e(TAG, "Bad alarm manager settings", e);
Dianne Hackborna750a632015-06-16 17:18:23 -0700300 }
301
302 MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
303 MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
304 ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
305 DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
306 ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME,
307 DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
308 ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong(
309 KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
310 DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700311 LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
312 DEFAULT_LISTENER_TIMEOUT);
Dianne Hackborna750a632015-06-16 17:18:23 -0700313
314 updateAllowWhileIdleMinTimeLocked();
315 updateAllowWhileIdleWhitelistDurationLocked();
316 }
317 }
318
319 void dump(PrintWriter pw) {
320 pw.println(" Settings:");
321
322 pw.print(" "); pw.print(KEY_MIN_FUTURITY); pw.print("=");
323 TimeUtils.formatDuration(MIN_FUTURITY, pw);
324 pw.println();
325
326 pw.print(" "); pw.print(KEY_MIN_INTERVAL); pw.print("=");
327 TimeUtils.formatDuration(MIN_INTERVAL, pw);
328 pw.println();
329
Christopher Tate14a7bb02015-10-01 10:24:31 -0700330 pw.print(" "); pw.print(KEY_LISTENER_TIMEOUT); pw.print("=");
331 TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
332 pw.println();
333
Dianne Hackborna750a632015-06-16 17:18:23 -0700334 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME); pw.print("=");
335 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw);
336 pw.println();
337
338 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME); pw.print("=");
339 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw);
340 pw.println();
341
342 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); pw.print("=");
343 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
344 pw.println();
345 }
346 }
347
348 final Constants mConstants;
349
Christopher Tate1590f1e2014-10-02 17:27:57 -0700350 // Alarm delivery ordering bookkeeping
351 static final int PRIO_TICK = 0;
352 static final int PRIO_WAKEUP = 1;
353 static final int PRIO_NORMAL = 2;
354
Dianne Hackborna750a632015-06-16 17:18:23 -0700355 final class PriorityClass {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700356 int seq;
357 int priority;
358
359 PriorityClass() {
360 seq = mCurrentSeq - 1;
361 priority = PRIO_NORMAL;
362 }
363 }
364
Dianne Hackborna750a632015-06-16 17:18:23 -0700365 final HashMap<String, PriorityClass> mPriorities = new HashMap<>();
Christopher Tate1590f1e2014-10-02 17:27:57 -0700366 int mCurrentSeq = 0;
367
Dianne Hackborna750a632015-06-16 17:18:23 -0700368 static final class WakeupEvent {
Christopher Tate18a75f12013-07-01 18:18:59 -0700369 public long when;
370 public int uid;
371 public String action;
372
373 public WakeupEvent(long theTime, int theUid, String theAction) {
374 when = theTime;
375 uid = theUid;
376 action = theAction;
377 }
378 }
379
Adam Lesinski182f73f2013-12-05 16:48:06 -0800380 final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
381 final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
Christopher Tate18a75f12013-07-01 18:18:59 -0700382
Adrian Roosc42a1e12014-07-07 23:35:53 +0200383 final class Batch {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700384 long start; // These endpoints are always in ELAPSED
385 long end;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700386 int flags; // Flags for alarms, such as FLAG_STANDALONE.
Christopher Tatee0a22b32013-07-11 14:43:13 -0700387
388 final ArrayList<Alarm> alarms = new ArrayList<Alarm>();
389
390 Batch() {
391 start = 0;
392 end = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700393 flags = 0;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700394 }
395
396 Batch(Alarm seed) {
397 start = seed.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700398 end = seed.maxWhenElapsed;
399 flags = seed.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700400 alarms.add(seed);
401 }
402
403 int size() {
404 return alarms.size();
405 }
406
407 Alarm get(int index) {
408 return alarms.get(index);
409 }
410
411 boolean canHold(long whenElapsed, long maxWhen) {
412 return (end >= whenElapsed) && (start <= maxWhen);
413 }
414
415 boolean add(Alarm alarm) {
416 boolean newStart = false;
417 // narrows the batch if necessary; presumes that canHold(alarm) is true
418 int index = Collections.binarySearch(alarms, alarm, sIncreasingTimeOrder);
419 if (index < 0) {
420 index = 0 - index - 1;
421 }
422 alarms.add(index, alarm);
423 if (DEBUG_BATCH) {
424 Slog.v(TAG, "Adding " + alarm + " to " + this);
425 }
426 if (alarm.whenElapsed > start) {
427 start = alarm.whenElapsed;
428 newStart = true;
429 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700430 if (alarm.maxWhenElapsed < end) {
431 end = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700432 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700433 flags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700434
435 if (DEBUG_BATCH) {
436 Slog.v(TAG, " => now " + this);
437 }
438 return newStart;
439 }
440
Christopher Tate14a7bb02015-10-01 10:24:31 -0700441 boolean remove(final PendingIntent operation, final IAlarmListener listener) {
442 if (operation == null && listener == null) {
443 if (localLOGV) {
444 Slog.w(TAG, "requested remove() of null operation",
445 new RuntimeException("here"));
446 }
447 return false;
448 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700449 boolean didRemove = false;
450 long newStart = 0; // recalculate endpoints as we go
451 long newEnd = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700452 int newFlags = 0;
Christopher Tateae269d52013-09-26 13:11:55 -0700453 for (int i = 0; i < alarms.size(); ) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700454 Alarm alarm = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700455 if (alarm.matches(operation, listener)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700456 alarms.remove(i);
457 didRemove = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200458 if (alarm.alarmClock != null) {
459 mNextAlarmClockMayChange = true;
460 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700461 } else {
462 if (alarm.whenElapsed > newStart) {
463 newStart = alarm.whenElapsed;
464 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700465 if (alarm.maxWhenElapsed < newEnd) {
466 newEnd = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700467 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700468 newFlags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700469 i++;
470 }
471 }
472 if (didRemove) {
473 // commit the new batch bounds
474 start = newStart;
475 end = newEnd;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700476 flags = newFlags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700477 }
478 return didRemove;
479 }
480
481 boolean remove(final String packageName) {
Christopher Tate14a7bb02015-10-01 10:24:31 -0700482 if (packageName == null) {
483 if (localLOGV) {
484 Slog.w(TAG, "requested remove() of null packageName",
485 new RuntimeException("here"));
486 }
487 return false;
488 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700489 boolean didRemove = false;
490 long newStart = 0; // recalculate endpoints as we go
491 long newEnd = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700492 int newFlags = 0;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700493 for (int i = alarms.size()-1; i >= 0; i--) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700494 Alarm alarm = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700495 if (alarm.matches(packageName)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700496 alarms.remove(i);
497 didRemove = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200498 if (alarm.alarmClock != null) {
499 mNextAlarmClockMayChange = true;
500 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700501 } else {
502 if (alarm.whenElapsed > newStart) {
503 newStart = alarm.whenElapsed;
504 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700505 if (alarm.maxWhenElapsed < newEnd) {
506 newEnd = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700507 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700508 newFlags |= alarm.flags;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700509 }
510 }
511 if (didRemove) {
512 // commit the new batch bounds
513 start = newStart;
514 end = newEnd;
515 flags = newFlags;
516 }
517 return didRemove;
518 }
519
520 boolean removeForStopped(final int uid) {
521 boolean didRemove = false;
522 long newStart = 0; // recalculate endpoints as we go
523 long newEnd = Long.MAX_VALUE;
524 int newFlags = 0;
525 for (int i = alarms.size()-1; i >= 0; i--) {
526 Alarm alarm = alarms.get(i);
527 try {
Dianne Hackbornc3af19a2017-01-20 17:00:44 -0800528 if (alarm.uid == uid && ActivityManager.getService().isAppStartModeDisabled(
529 uid, alarm.packageName)) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700530 alarms.remove(i);
531 didRemove = true;
532 if (alarm.alarmClock != null) {
533 mNextAlarmClockMayChange = true;
534 }
535 } else {
536 if (alarm.whenElapsed > newStart) {
537 newStart = alarm.whenElapsed;
538 }
539 if (alarm.maxWhenElapsed < newEnd) {
540 newEnd = alarm.maxWhenElapsed;
541 }
542 newFlags |= alarm.flags;
543 }
544 } catch (RemoteException e) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700545 }
546 }
547 if (didRemove) {
548 // commit the new batch bounds
549 start = newStart;
550 end = newEnd;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700551 flags = newFlags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700552 }
553 return didRemove;
554 }
555
556 boolean remove(final int userHandle) {
557 boolean didRemove = false;
558 long newStart = 0; // recalculate endpoints as we go
559 long newEnd = Long.MAX_VALUE;
Christopher Tateae269d52013-09-26 13:11:55 -0700560 for (int i = 0; i < alarms.size(); ) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700561 Alarm alarm = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700562 if (UserHandle.getUserId(alarm.creatorUid) == userHandle) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700563 alarms.remove(i);
564 didRemove = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200565 if (alarm.alarmClock != null) {
566 mNextAlarmClockMayChange = true;
567 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700568 } else {
569 if (alarm.whenElapsed > newStart) {
570 newStart = alarm.whenElapsed;
571 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700572 if (alarm.maxWhenElapsed < newEnd) {
573 newEnd = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700574 }
575 i++;
576 }
577 }
578 if (didRemove) {
579 // commit the new batch bounds
580 start = newStart;
581 end = newEnd;
582 }
583 return didRemove;
584 }
585
586 boolean hasPackage(final String packageName) {
587 final int N = alarms.size();
588 for (int i = 0; i < N; i++) {
589 Alarm a = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700590 if (a.matches(packageName)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700591 return true;
592 }
593 }
594 return false;
595 }
596
597 boolean hasWakeups() {
598 final int N = alarms.size();
599 for (int i = 0; i < N; i++) {
600 Alarm a = alarms.get(i);
601 // non-wakeup alarms are types 1 and 3, i.e. have the low bit set
602 if ((a.type & TYPE_NONWAKEUP_MASK) == 0) {
603 return true;
604 }
605 }
606 return false;
607 }
608
609 @Override
610 public String toString() {
611 StringBuilder b = new StringBuilder(40);
612 b.append("Batch{"); b.append(Integer.toHexString(this.hashCode()));
613 b.append(" num="); b.append(size());
614 b.append(" start="); b.append(start);
615 b.append(" end="); b.append(end);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700616 if (flags != 0) {
617 b.append(" flgs=0x");
618 b.append(Integer.toHexString(flags));
Christopher Tatee0a22b32013-07-11 14:43:13 -0700619 }
620 b.append('}');
621 return b.toString();
622 }
623 }
624
625 static class BatchTimeOrder implements Comparator<Batch> {
626 public int compare(Batch b1, Batch b2) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800627 long when1 = b1.start;
628 long when2 = b2.start;
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800629 if (when1 > when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700630 return 1;
631 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800632 if (when1 < when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700633 return -1;
634 }
635 return 0;
636 }
637 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800638
639 final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
640 @Override
641 public int compare(Alarm lhs, Alarm rhs) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700642 // priority class trumps everything. TICK < WAKEUP < NORMAL
643 if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
644 return -1;
645 } else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
646 return 1;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800647 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700648
649 // within each class, sort by nominal delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800650 if (lhs.whenElapsed < rhs.whenElapsed) {
651 return -1;
652 } else if (lhs.whenElapsed > rhs.whenElapsed) {
653 return 1;
654 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700655
656 // same priority class + same target delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800657 return 0;
658 }
659 };
660
Christopher Tate1590f1e2014-10-02 17:27:57 -0700661 void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
662 final int N = alarms.size();
663 for (int i = 0; i < N; i++) {
664 Alarm a = alarms.get(i);
665
666 final int alarmPrio;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700667 if (a.operation != null
668 && Intent.ACTION_TIME_TICK.equals(a.operation.getIntent().getAction())) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700669 alarmPrio = PRIO_TICK;
670 } else if (a.wakeup) {
671 alarmPrio = PRIO_WAKEUP;
672 } else {
673 alarmPrio = PRIO_NORMAL;
674 }
675
676 PriorityClass packagePrio = a.priorityClass;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700677 String alarmPackage = (a.operation != null)
678 ? a.operation.getCreatorPackage()
679 : a.packageName;
680 if (packagePrio == null) packagePrio = mPriorities.get(alarmPackage);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700681 if (packagePrio == null) {
682 packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
Christopher Tate14a7bb02015-10-01 10:24:31 -0700683 mPriorities.put(alarmPackage, packagePrio);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700684 }
685 a.priorityClass = packagePrio;
686
687 if (packagePrio.seq != mCurrentSeq) {
688 // first alarm we've seen in the current delivery generation from this package
689 packagePrio.priority = alarmPrio;
690 packagePrio.seq = mCurrentSeq;
691 } else {
692 // Multiple alarms from this package being delivered in this generation;
693 // bump the package's delivery class if it's warranted.
694 // TICK < WAKEUP < NORMAL
695 if (alarmPrio < packagePrio.priority) {
696 packagePrio.priority = alarmPrio;
697 }
698 }
699 }
700 }
701
Christopher Tatee0a22b32013-07-11 14:43:13 -0700702 // minimum recurrence period or alarm futurity for us to be able to fuzz it
Adam Lesinski182f73f2013-12-05 16:48:06 -0800703 static final long MIN_FUZZABLE_INTERVAL = 10000;
704 static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700705 final ArrayList<Batch> mAlarmBatches = new ArrayList<>();
706
707 // set to null if in idle mode; while in this mode, any alarms we don't want
708 // to run during this time are placed in mPendingWhileIdleAlarms
709 Alarm mPendingIdleUntil = null;
Dianne Hackbornf70faed2015-04-21 14:11:38 -0700710 Alarm mNextWakeFromIdle = null;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700711 ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
Christopher Tatee0a22b32013-07-11 14:43:13 -0700712
Jeff Brownb880d882014-02-10 19:47:07 -0800713 public AlarmManagerService(Context context) {
714 super(context);
Dianne Hackborna750a632015-06-16 17:18:23 -0700715 mConstants = new Constants(mHandler);
Jeff Brownb880d882014-02-10 19:47:07 -0800716 }
717
Christopher Tatee0a22b32013-07-11 14:43:13 -0700718 static long convertToElapsed(long when, int type) {
719 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
720 if (isRtc) {
721 when -= System.currentTimeMillis() - SystemClock.elapsedRealtime();
722 }
723 return when;
724 }
725
726 // Apply a heuristic to { recurrence interval, futurity of the trigger time } to
727 // calculate the end of our nominal delivery window for the alarm.
728 static long maxTriggerTime(long now, long triggerAtTime, long interval) {
729 // Current heuristic: batchable window is 75% of either the recurrence interval
730 // [for a periodic alarm] or of the time from now to the desired delivery time,
731 // with a minimum delay/interval of 10 seconds, under which we will simply not
732 // defer the alarm.
733 long futurity = (interval == 0)
734 ? (triggerAtTime - now)
735 : interval;
Christopher Tate57ceaaa2013-07-19 16:30:43 -0700736 if (futurity < MIN_FUZZABLE_INTERVAL) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700737 futurity = 0;
738 }
739 return triggerAtTime + (long)(.75 * futurity);
740 }
741
742 // returns true if the batch was added at the head
743 static boolean addBatchLocked(ArrayList<Batch> list, Batch newBatch) {
744 int index = Collections.binarySearch(list, newBatch, sBatchOrder);
745 if (index < 0) {
746 index = 0 - index - 1;
747 }
748 list.add(index, newBatch);
749 return (index == 0);
750 }
751
Christopher Tate385e4982013-07-23 18:22:29 -0700752 // Return the index of the matching batch, or -1 if none found.
753 int attemptCoalesceLocked(long whenElapsed, long maxWhen) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700754 final int N = mAlarmBatches.size();
755 for (int i = 0; i < N; i++) {
756 Batch b = mAlarmBatches.get(i);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700757 if ((b.flags&AlarmManager.FLAG_STANDALONE) == 0 && b.canHold(whenElapsed, maxWhen)) {
Christopher Tate385e4982013-07-23 18:22:29 -0700758 return i;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700759 }
760 }
Christopher Tate385e4982013-07-23 18:22:29 -0700761 return -1;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700762 }
763
764 // The RTC clock has moved arbitrarily, so we need to recalculate all the batching
765 void rebatchAllAlarms() {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700766 synchronized (mLock) {
Christopher Tate4cb338d2013-07-26 13:11:31 -0700767 rebatchAllAlarmsLocked(true);
768 }
769 }
770
771 void rebatchAllAlarmsLocked(boolean doValidate) {
772 ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone();
773 mAlarmBatches.clear();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700774 Alarm oldPendingIdleUntil = mPendingIdleUntil;
Christopher Tate4cb338d2013-07-26 13:11:31 -0700775 final long nowElapsed = SystemClock.elapsedRealtime();
776 final int oldBatches = oldSet.size();
777 for (int batchNum = 0; batchNum < oldBatches; batchNum++) {
778 Batch batch = oldSet.get(batchNum);
779 final int N = batch.size();
780 for (int i = 0; i < N; i++) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700781 reAddAlarmLocked(batch.get(i), nowElapsed, doValidate);
Christopher Tatee0a22b32013-07-11 14:43:13 -0700782 }
783 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700784 if (oldPendingIdleUntil != null && oldPendingIdleUntil != mPendingIdleUntil) {
785 Slog.wtf(TAG, "Rebatching: idle until changed from " + oldPendingIdleUntil
786 + " to " + mPendingIdleUntil);
787 if (mPendingIdleUntil == null) {
788 // Somehow we lost this... we need to restore all of the pending alarms.
789 restorePendingWhileIdleAlarmsLocked();
790 }
791 }
792 rescheduleKernelAlarmsLocked();
793 updateNextAlarmClockLocked();
794 }
795
796 void reAddAlarmLocked(Alarm a, long nowElapsed, boolean doValidate) {
797 a.when = a.origWhen;
798 long whenElapsed = convertToElapsed(a.when, a.type);
799 final long maxElapsed;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700800 if (a.windowLength == AlarmManager.WINDOW_EXACT) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700801 // Exact
802 maxElapsed = whenElapsed;
803 } else {
804 // Not exact. Preserve any explicit window, otherwise recalculate
805 // the window based on the alarm's new futurity. Note that this
806 // reflects a policy of preferring timely to deferred delivery.
807 maxElapsed = (a.windowLength > 0)
808 ? (whenElapsed + a.windowLength)
809 : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
810 }
811 a.whenElapsed = whenElapsed;
812 a.maxWhenElapsed = maxElapsed;
813 setImplLocked(a, true, doValidate);
814 }
815
816 void restorePendingWhileIdleAlarmsLocked() {
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700817 if (RECORD_DEVICE_IDLE_ALARMS) {
818 IdleDispatchEntry ent = new IdleDispatchEntry();
819 ent.uid = 0;
820 ent.pkg = "FINISH IDLE";
821 ent.elapsedRealtime = SystemClock.elapsedRealtime();
822 mAllowWhileIdleDispatches.add(ent);
823 }
824
Dianne Hackborn35d54032015-04-23 10:30:43 -0700825 // Bring pending alarms back into the main list.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700826 if (mPendingWhileIdleAlarms.size() > 0) {
827 ArrayList<Alarm> alarms = mPendingWhileIdleAlarms;
828 mPendingWhileIdleAlarms = new ArrayList<>();
829 final long nowElapsed = SystemClock.elapsedRealtime();
830 for (int i=alarms.size() - 1; i >= 0; i--) {
831 Alarm a = alarms.get(i);
832 reAddAlarmLocked(a, nowElapsed, false);
833 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700834 }
Dianne Hackborn35d54032015-04-23 10:30:43 -0700835
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700836 // Make sure we are using the correct ALLOW_WHILE_IDLE min time.
Dianne Hackborna750a632015-06-16 17:18:23 -0700837 mConstants.updateAllowWhileIdleMinTimeLocked();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700838
Dianne Hackborn35d54032015-04-23 10:30:43 -0700839 // Reschedule everything.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700840 rescheduleKernelAlarmsLocked();
841 updateNextAlarmClockLocked();
Dianne Hackborn35d54032015-04-23 10:30:43 -0700842
843 // And send a TIME_TICK right now, since it is important to get the UI updated.
844 try {
845 mTimeTickSender.send();
846 } catch (PendingIntent.CanceledException e) {
847 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700848 }
849
Christopher Tate14a7bb02015-10-01 10:24:31 -0700850 static final class InFlight {
Dianne Hackborn81038902012-11-26 17:04:09 -0800851 final PendingIntent mPendingIntent;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700852 final IBinder mListener;
David Christieebe51fc2013-07-26 13:23:29 -0700853 final WorkSource mWorkSource;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700854 final int mUid;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700855 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -0800856 final BroadcastStats mBroadcastStats;
857 final FilterStats mFilterStats;
Dianne Hackborne5167ca2014-03-08 14:39:10 -0800858 final int mAlarmType;
Dianne Hackborn81038902012-11-26 17:04:09 -0800859
Christopher Tate14a7bb02015-10-01 10:24:31 -0700860 InFlight(AlarmManagerService service, PendingIntent pendingIntent, IAlarmListener listener,
861 WorkSource workSource, int uid, String alarmPkg, int alarmType, String tag,
862 long nowELAPSED) {
Dianne Hackborn81038902012-11-26 17:04:09 -0800863 mPendingIntent = pendingIntent;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700864 mListener = listener != null ? listener.asBinder() : null;
David Christieebe51fc2013-07-26 13:23:29 -0700865 mWorkSource = workSource;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700866 mUid = uid;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700867 mTag = tag;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700868 mBroadcastStats = (pendingIntent != null)
869 ? service.getStatsLocked(pendingIntent)
870 : service.getStatsLocked(uid, alarmPkg);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700871 FilterStats fs = mBroadcastStats.filterStats.get(mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -0800872 if (fs == null) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700873 fs = new FilterStats(mBroadcastStats, mTag);
874 mBroadcastStats.filterStats.put(mTag, fs);
Dianne Hackborn81038902012-11-26 17:04:09 -0800875 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -0700876 fs.lastTime = nowELAPSED;
Dianne Hackborn81038902012-11-26 17:04:09 -0800877 mFilterStats = fs;
Dianne Hackborne5167ca2014-03-08 14:39:10 -0800878 mAlarmType = alarmType;
Dianne Hackborn81038902012-11-26 17:04:09 -0800879 }
Makoto Onuki33955e12017-03-01 18:11:00 -0800880
881 @Override
882 public String toString() {
883 return "InFlight{"
884 + "pendingIntent=" + mPendingIntent
885 + ", workSource=" + mWorkSource
886 + ", uid=" + mUid
887 + ", tag=" + mTag
888 + ", broadcastStats=" + mBroadcastStats
889 + ", filterStats=" + mFilterStats
890 + ", alarmType=" + mAlarmType
891 + "}";
892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 }
Dianne Hackborn81038902012-11-26 17:04:09 -0800894
Adam Lesinski182f73f2013-12-05 16:48:06 -0800895 static final class FilterStats {
Dianne Hackborn81038902012-11-26 17:04:09 -0800896 final BroadcastStats mBroadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700897 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -0800898
Dianne Hackbornf70faed2015-04-21 14:11:38 -0700899 long lastTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 long aggregateTime;
Dianne Hackborn81038902012-11-26 17:04:09 -0800901 int count;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 int numWakeup;
903 long startTime;
904 int nesting;
Dianne Hackborn81038902012-11-26 17:04:09 -0800905
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700906 FilterStats(BroadcastStats broadcastStats, String tag) {
Dianne Hackborn81038902012-11-26 17:04:09 -0800907 mBroadcastStats = broadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700908 mTag = tag;
Dianne Hackborn81038902012-11-26 17:04:09 -0800909 }
Makoto Onuki33955e12017-03-01 18:11:00 -0800910
911 @Override
912 public String toString() {
913 return "FilterStats{"
914 + "tag=" + mTag
915 + ", lastTime=" + lastTime
916 + ", aggregateTime=" + aggregateTime
917 + ", count=" + count
918 + ", numWakeup=" + numWakeup
919 + ", startTime=" + startTime
920 + ", nesting=" + nesting
921 + "}";
922 }
Dianne Hackborn81038902012-11-26 17:04:09 -0800923 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700924
Adam Lesinski182f73f2013-12-05 16:48:06 -0800925 static final class BroadcastStats {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800926 final int mUid;
Dianne Hackborn81038902012-11-26 17:04:09 -0800927 final String mPackageName;
928
929 long aggregateTime;
930 int count;
931 int numWakeup;
932 long startTime;
933 int nesting;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700934 final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
Dianne Hackborn81038902012-11-26 17:04:09 -0800935
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800936 BroadcastStats(int uid, String packageName) {
937 mUid = uid;
Dianne Hackborn81038902012-11-26 17:04:09 -0800938 mPackageName = packageName;
939 }
Makoto Onuki33955e12017-03-01 18:11:00 -0800940
941 @Override
942 public String toString() {
943 return "BroadcastStats{"
944 + "uid=" + mUid
945 + ", packageName=" + mPackageName
946 + ", aggregateTime=" + aggregateTime
947 + ", count=" + count
948 + ", numWakeup=" + numWakeup
949 + ", startTime=" + startTime
950 + ", nesting=" + nesting
951 + "}";
952 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700954
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800955 final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
956 = new SparseArray<ArrayMap<String, BroadcastStats>>();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700957
958 int mNumDelayedAlarms = 0;
959 long mTotalDelayTime = 0;
960 long mMaxDelayTime = 0;
961
Adam Lesinski182f73f2013-12-05 16:48:06 -0800962 @Override
963 public void onStart() {
Greg Hackmanna1d6f922013-12-09 16:56:53 -0800964 mNativeData = init();
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800965 mNextWakeup = mNextNonWakeup = 0;
Robert CH Chou64ba8e42009-11-04 21:38:49 +0800966
967 // We have to set current TimeZone info to kernel
968 // because kernel doesn't keep this after reboot
Adam Lesinski182f73f2013-12-05 16:48:06 -0800969 setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
Robert CH Chou64ba8e42009-11-04 21:38:49 +0800970
Christopher Tate247571462017-04-10 11:45:05 -0700971 // Also sure that we're booting with a halfway sensible current time
972 if (mNativeData != 0) {
973 final long systemBuildTime = Environment.getRootDirectory().lastModified();
974 if (System.currentTimeMillis() < systemBuildTime) {
975 Slog.i(TAG, "Current time only " + System.currentTimeMillis()
976 + ", advancing to build time " + systemBuildTime);
977 setKernelTime(mNativeData, systemBuildTime);
978 }
979 }
980
Christopher Tatebb9cce52017-04-18 14:19:43 -0700981 // Determine SysUI's uid
982 final PackageManager packMan = getContext().getPackageManager();
983 try {
984 PermissionInfo sysUiPerm = packMan.getPermissionInfo(SYSTEM_UI_SELF_PERMISSION, 0);
985 ApplicationInfo sysUi = packMan.getApplicationInfo(sysUiPerm.packageName, 0);
986 if ((sysUi.privateFlags&ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
987 mSystemUiUid = sysUi.uid;
988 } else {
989 Slog.e(TAG, "SysUI permission " + SYSTEM_UI_SELF_PERMISSION
990 + " defined by non-privileged app " + sysUi.packageName
991 + " - ignoring");
992 }
993 } catch (NameNotFoundException e) {
994 }
995
996 if (mSystemUiUid <= 0) {
997 Slog.wtf(TAG, "SysUI package not found!");
998 }
999
Adam Lesinski182f73f2013-12-05 16:48:06 -08001000 PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001001 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
Dianne Hackborna1f1a3c2014-02-24 18:12:28 -08001002
Adam Lesinski182f73f2013-12-05 16:48:06 -08001003 mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 new Intent(Intent.ACTION_TIME_TICK).addFlags(
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07001005 Intent.FLAG_RECEIVER_REGISTERED_ONLY
Chad Brubaker291df4f2017-03-14 10:23:02 -07001006 | Intent.FLAG_RECEIVER_FOREGROUND
1007 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS), 0,
Dianne Hackborndb5aca92012-10-26 13:39:41 -07001008 UserHandle.ALL);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001009 Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
Chad Brubaker291df4f2017-03-14 10:23:02 -07001010 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
1011 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001012 mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
Dianne Hackborndb5aca92012-10-26 13:39:41 -07001013 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014
1015 // now that we have initied the driver schedule the alarm
Adam Lesinski182f73f2013-12-05 16:48:06 -08001016 mClockReceiver = new ClockReceiver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 mClockReceiver.scheduleTimeTickEvent();
1018 mClockReceiver.scheduleDateChangedEvent();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001019 mInteractiveStateReceiver = new InteractiveStateReceiver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 mUninstallReceiver = new UninstallReceiver();
1021
Greg Hackmanna1d6f922013-12-09 16:56:53 -08001022 if (mNativeData != 0) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001023 AlarmThread waitThread = new AlarmThread();
1024 waitThread.start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001026 Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001028
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001029 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001030 ActivityManager.getService().registerUidObserver(new UidObserver(),
Dianne Hackborn5614bf52016-11-07 17:26:41 -08001031 ActivityManager.UID_OBSERVER_IDLE, ActivityManager.PROCESS_STATE_UNKNOWN, null);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001032 } catch (RemoteException e) {
1033 // ignored; both services live in system_server
1034 }
1035
Adam Lesinski182f73f2013-12-05 16:48:06 -08001036 publishBinderService(Context.ALARM_SERVICE, mService);
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001037 publishLocalService(LocalService.class, new LocalService());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001039
1040 @Override
Dianne Hackborna750a632015-06-16 17:18:23 -07001041 public void onBootPhase(int phase) {
1042 if (phase == PHASE_SYSTEM_SERVICES_READY) {
1043 mConstants.start(getContext().getContentResolver());
Christopher Tate14a7bb02015-10-01 10:24:31 -07001044 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001045 mLocalDeviceIdleController
1046 = LocalServices.getService(DeviceIdleController.LocalService.class);
Dianne Hackborna750a632015-06-16 17:18:23 -07001047 }
1048 }
1049
1050 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 protected void finalize() throws Throwable {
1052 try {
Greg Hackmanna1d6f922013-12-09 16:56:53 -08001053 close(mNativeData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 } finally {
1055 super.finalize();
1056 }
1057 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001058
Adam Lesinski182f73f2013-12-05 16:48:06 -08001059 void setTimeZoneImpl(String tz) {
1060 if (TextUtils.isEmpty(tz)) {
1061 return;
David Christieebe51fc2013-07-26 13:23:29 -07001062 }
1063
Adam Lesinski182f73f2013-12-05 16:48:06 -08001064 TimeZone zone = TimeZone.getTimeZone(tz);
1065 // Prevent reentrant calls from stepping on each other when writing
1066 // the time zone property
1067 boolean timeZoneWasChanged = false;
1068 synchronized (this) {
1069 String current = SystemProperties.get(TIMEZONE_PROPERTY);
1070 if (current == null || !current.equals(zone.getID())) {
1071 if (localLOGV) {
1072 Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
1073 }
1074 timeZoneWasChanged = true;
1075 SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
1076 }
1077
1078 // Update the kernel timezone information
1079 // Kernel tracks time offsets as 'minutes west of GMT'
1080 int gmtOffset = zone.getOffset(System.currentTimeMillis());
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -08001081 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
Adam Lesinski182f73f2013-12-05 16:48:06 -08001082 }
1083
1084 TimeZone.setDefault(null);
1085
1086 if (timeZoneWasChanged) {
1087 Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
Chad Brubaker291df4f2017-03-14 10:23:02 -07001088 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
1089 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001090 intent.putExtra("time-zone", zone.getID());
1091 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
1092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001094
Adam Lesinski182f73f2013-12-05 16:48:06 -08001095 void removeImpl(PendingIntent operation) {
1096 if (operation == null) {
1097 return;
1098 }
1099 synchronized (mLock) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07001100 removeLocked(operation, null);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001101 }
1102 }
1103
1104 void setImpl(int type, long triggerAtTime, long windowLength, long interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001105 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1106 int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
1107 int callingUid, String callingPackage) {
1108 // must be *either* PendingIntent or AlarmReceiver, but not both
1109 if ((operation == null && directReceiver == null)
1110 || (operation != null && directReceiver != null)) {
1111 Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver");
1112 // NB: previous releases failed silently here, so we are continuing to do the same
1113 // rather than throw an IllegalArgumentException.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 return;
1115 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001116
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001117 // Sanity check the window length. This will catch people mistakenly
1118 // trying to pass an end-of-window timestamp rather than a duration.
1119 if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
1120 Slog.w(TAG, "Window length " + windowLength
1121 + "ms suspiciously long; limiting to 1 hour");
1122 windowLength = AlarmManager.INTERVAL_HOUR;
1123 }
1124
Christopher Tate498c6cb2014-11-17 16:09:27 -08001125 // Sanity check the recurrence interval. This will catch people who supply
1126 // seconds when the API expects milliseconds.
Dianne Hackborna750a632015-06-16 17:18:23 -07001127 final long minInterval = mConstants.MIN_INTERVAL;
1128 if (interval > 0 && interval < minInterval) {
Christopher Tate498c6cb2014-11-17 16:09:27 -08001129 Slog.w(TAG, "Suspiciously short interval " + interval
Dianne Hackborna750a632015-06-16 17:18:23 -07001130 + " millis; expanding to " + (minInterval/1000)
Christopher Tate498c6cb2014-11-17 16:09:27 -08001131 + " seconds");
Dianne Hackborna750a632015-06-16 17:18:23 -07001132 interval = minInterval;
Christopher Tate498c6cb2014-11-17 16:09:27 -08001133 }
1134
Christopher Tatee0a22b32013-07-11 14:43:13 -07001135 if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
1136 throw new IllegalArgumentException("Invalid alarm type " + type);
1137 }
1138
Christopher Tate5f221e82013-07-30 17:13:15 -07001139 if (triggerAtTime < 0) {
Christopher Tate5f221e82013-07-30 17:13:15 -07001140 final long what = Binder.getCallingPid();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001141 Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
Christopher Tate5f221e82013-07-30 17:13:15 -07001142 + " pid=" + what);
1143 triggerAtTime = 0;
1144 }
1145
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001146 final long nowElapsed = SystemClock.elapsedRealtime();
Christopher Tate498c6cb2014-11-17 16:09:27 -08001147 final long nominalTrigger = convertToElapsed(triggerAtTime, type);
1148 // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
Dianne Hackborna750a632015-06-16 17:18:23 -07001149 final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
Christopher Tate498c6cb2014-11-17 16:09:27 -08001150 final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
1151
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001152 final long maxElapsed;
1153 if (windowLength == AlarmManager.WINDOW_EXACT) {
1154 maxElapsed = triggerElapsed;
1155 } else if (windowLength < 0) {
1156 maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001157 // Fix this window in place, so that as time approaches we don't collapse it.
1158 windowLength = maxElapsed - triggerElapsed;
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001159 } else {
1160 maxElapsed = triggerElapsed + windowLength;
1161 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 synchronized (mLock) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07001164 if (DEBUG_BATCH) {
1165 Slog.v(TAG, "set(" + operation + ") : type=" + type
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001166 + " triggerAtTime=" + triggerAtTime + " win=" + windowLength
Christopher Tatee0a22b32013-07-11 14:43:13 -07001167 + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001168 + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 }
Christopher Tate3e04b472013-10-21 17:51:31 -07001170 setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001171 interval, operation, directReceiver, listenerTag, flags, true, workSource,
1172 alarmClock, callingUid, callingPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 }
1174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175
Christopher Tate3e04b472013-10-21 17:51:31 -07001176 private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001177 long maxWhen, long interval, PendingIntent operation, IAlarmListener directReceiver,
1178 String listenerTag, int flags, boolean doValidate, WorkSource workSource,
1179 AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) {
Christopher Tate3e04b472013-10-21 17:51:31 -07001180 Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001181 operation, directReceiver, listenerTag, workSource, flags, alarmClock,
1182 callingUid, callingPackage);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001183 try {
Dianne Hackbornc3af19a2017-01-20 17:00:44 -08001184 if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001185 Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
1186 + " -- package not allowed to start");
1187 return;
1188 }
1189 } catch (RemoteException e) {
1190 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07001191 removeLocked(operation, directReceiver);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001192 setImplLocked(a, false, doValidate);
1193 }
Christopher Tateb8849c12011-02-08 13:39:01 -08001194
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001195 private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
1196 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001197 // This is a special alarm that will put the system into idle until it goes off.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001198 // The caller has given the time they want this to happen at, however we need
1199 // to pull that earlier if there are existing alarms that have requested to
Dianne Hackbornf3831292015-10-15 14:51:06 -07001200 // bring us out of idle at an earlier time.
1201 if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001202 a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001203 }
1204 // Add fuzz to make the alarm go off some time before the actual desired time.
1205 final long nowElapsed = SystemClock.elapsedRealtime();
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001206 final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001207 if (fuzz > 0) {
1208 if (mRandom == null) {
1209 mRandom = new Random();
1210 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001211 final int delta = mRandom.nextInt(fuzz);
1212 a.whenElapsed -= delta;
1213 if (false) {
1214 Slog.d(TAG, "Alarm when: " + a.whenElapsed);
1215 Slog.d(TAG, "Delta until alarm: " + (a.whenElapsed-nowElapsed));
1216 Slog.d(TAG, "Applied fuzz: " + fuzz);
1217 Slog.d(TAG, "Final delta: " + delta);
1218 Slog.d(TAG, "Final when: " + a.whenElapsed);
1219 }
1220 a.when = a.maxWhenElapsed = a.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001221 }
1222
1223 } else if (mPendingIdleUntil != null) {
1224 // We currently have an idle until alarm scheduled; if the new alarm has
1225 // not explicitly stated it wants to run while idle, then put it on hold.
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001226 if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
1227 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
1228 | AlarmManager.FLAG_WAKE_FROM_IDLE))
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001229 == 0) {
1230 mPendingWhileIdleAlarms.add(a);
1231 return;
1232 }
1233 }
1234
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001235 if (RECORD_DEVICE_IDLE_ALARMS) {
1236 if ((a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
1237 IdleDispatchEntry ent = new IdleDispatchEntry();
1238 ent.uid = a.uid;
1239 ent.pkg = a.operation.getCreatorPackage();
1240 ent.tag = a.operation.getTag("");
1241 ent.op = "SET";
1242 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1243 ent.argRealtime = a.whenElapsed;
1244 mAllowWhileIdleDispatches.add(ent);
1245 }
1246 }
1247
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001248 int whichBatch = ((a.flags&AlarmManager.FLAG_STANDALONE) != 0)
1249 ? -1 : attemptCoalesceLocked(a.whenElapsed, a.maxWhenElapsed);
Christopher Tate385e4982013-07-23 18:22:29 -07001250 if (whichBatch < 0) {
1251 Batch batch = new Batch(a);
Christopher Tate7d57ed82013-10-25 20:18:03 -07001252 addBatchLocked(mAlarmBatches, batch);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 } else {
Christopher Tate385e4982013-07-23 18:22:29 -07001254 Batch batch = mAlarmBatches.get(whichBatch);
Christopher Tate7d57ed82013-10-25 20:18:03 -07001255 if (batch.add(a)) {
Christopher Tate385e4982013-07-23 18:22:29 -07001256 // The start time of this batch advanced, so batch ordering may
1257 // have just been broken. Move it to where it now belongs.
1258 mAlarmBatches.remove(whichBatch);
1259 addBatchLocked(mAlarmBatches, batch);
1260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261 }
1262
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001263 if (a.alarmClock != null) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001264 mNextAlarmClockMayChange = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +02001265 }
1266
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001267 boolean needRebatch = false;
1268
1269 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001270 if (RECORD_DEVICE_IDLE_ALARMS) {
1271 if (mPendingIdleUntil == null) {
1272 IdleDispatchEntry ent = new IdleDispatchEntry();
1273 ent.uid = 0;
1274 ent.pkg = "START IDLE";
1275 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1276 mAllowWhileIdleDispatches.add(ent);
1277 }
1278 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001279 mPendingIdleUntil = a;
Dianne Hackborna750a632015-06-16 17:18:23 -07001280 mConstants.updateAllowWhileIdleMinTimeLocked();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001281 needRebatch = true;
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001282 } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
1283 if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
1284 mNextWakeFromIdle = a;
1285 // If this wake from idle is earlier than whatever was previously scheduled,
1286 // and we are currently idling, then we need to rebatch alarms in case the idle
1287 // until time needs to be updated.
1288 if (mPendingIdleUntil != null) {
1289 needRebatch = true;
1290 }
1291 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001292 }
1293
1294 if (!rebatching) {
1295 if (DEBUG_VALIDATE) {
1296 if (doValidate && !validateConsistencyLocked()) {
1297 Slog.v(TAG, "Tipping-point operation: type=" + a.type + " when=" + a.when
1298 + " when(hex)=" + Long.toHexString(a.when)
1299 + " whenElapsed=" + a.whenElapsed
1300 + " maxWhenElapsed=" + a.maxWhenElapsed
1301 + " interval=" + a.repeatInterval + " op=" + a.operation
1302 + " flags=0x" + Integer.toHexString(a.flags));
1303 rebatchAllAlarmsLocked(false);
1304 needRebatch = false;
1305 }
1306 }
1307
1308 if (needRebatch) {
Christopher Tate4cb338d2013-07-26 13:11:31 -07001309 rebatchAllAlarmsLocked(false);
Christopher Tate4cb338d2013-07-26 13:11:31 -07001310 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001311
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001312 rescheduleKernelAlarmsLocked();
1313 updateNextAlarmClockLocked();
1314 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001315 }
1316
Adam Lesinski182f73f2013-12-05 16:48:06 -08001317 private final IBinder mService = new IAlarmManager.Stub() {
1318 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07001319 public void set(String callingPackage,
1320 int type, long triggerAtTime, long windowLength, long interval, int flags,
1321 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1322 WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001323 final int callingUid = Binder.getCallingUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07001324
1325 // make sure the caller is not lying about which package should be blamed for
1326 // wakelock time spent in alarm delivery
1327 mAppOps.checkPackage(callingUid, callingPackage);
1328
1329 // Repeating alarms must use PendingIntent, not direct listener
1330 if (interval != 0) {
1331 if (directReceiver != null) {
1332 throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers");
1333 }
1334 }
1335
Adam Lesinski182f73f2013-12-05 16:48:06 -08001336 if (workSource != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001337 getContext().enforcePermission(
Adam Lesinski182f73f2013-12-05 16:48:06 -08001338 android.Manifest.permission.UPDATE_DEVICE_STATS,
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001339 Binder.getCallingPid(), callingUid, "AlarmManager.set");
Christopher Tate89779822012-08-31 14:40:03 -07001340 }
1341
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001342 // No incoming callers can request either WAKE_FROM_IDLE or
1343 // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
1344 flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
1345 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
1346
1347 // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
1348 // manager when to come out of idle mode, which is only for DeviceIdleController.
1349 if (callingUid != Process.SYSTEM_UID) {
1350 flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
1351 }
1352
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001353 // If this is an exact time alarm, then it can't be batched with other alarms.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001354 if (windowLength == AlarmManager.WINDOW_EXACT) {
1355 flags |= AlarmManager.FLAG_STANDALONE;
1356 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001357
1358 // If this alarm is for an alarm clock, then it must be standalone and we will
1359 // use it to wake early from idle if needed.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001360 if (alarmClock != null) {
1361 flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001362
1363 // If the caller is a core system component or on the user's whitelist, and not calling
1364 // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
1365 // This means we will allow these alarms to go off as normal even while idle, with no
1366 // timing restrictions.
1367 } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
Christopher Tatebb9cce52017-04-18 14:19:43 -07001368 || callingUid == mSystemUiUid
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001369 || Arrays.binarySearch(mDeviceIdleUserWhitelist,
1370 UserHandle.getAppId(callingUid)) >= 0)) {
1371 flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
1372 flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001373 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001374
Christopher Tate14a7bb02015-10-01 10:24:31 -07001375 setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
1376 listenerTag, flags, workSource, alarmClock, callingUid, callingPackage);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001377 }
Christopher Tate89779822012-08-31 14:40:03 -07001378
Adam Lesinski182f73f2013-12-05 16:48:06 -08001379 @Override
Greg Hackmann0cab8962014-02-21 16:35:52 -08001380 public boolean setTime(long millis) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001381 getContext().enforceCallingOrSelfPermission(
1382 "android.permission.SET_TIME",
1383 "setTime");
1384
Greg Hackmann0cab8962014-02-21 16:35:52 -08001385 if (mNativeData == 0) {
1386 Slog.w(TAG, "Not setting time since no alarm driver is available.");
1387 return false;
Christopher Tate89779822012-08-31 14:40:03 -07001388 }
Greg Hackmann0cab8962014-02-21 16:35:52 -08001389
1390 synchronized (mLock) {
1391 return setKernelTime(mNativeData, millis) == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001394
1395 @Override
1396 public void setTimeZone(String tz) {
1397 getContext().enforceCallingOrSelfPermission(
1398 "android.permission.SET_TIME_ZONE",
1399 "setTimeZone");
1400
1401 final long oldId = Binder.clearCallingIdentity();
1402 try {
1403 setTimeZoneImpl(tz);
1404 } finally {
1405 Binder.restoreCallingIdentity(oldId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 }
1407 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001408
Adam Lesinski182f73f2013-12-05 16:48:06 -08001409 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07001410 public void remove(PendingIntent operation, IAlarmListener listener) {
1411 if (operation == null && listener == null) {
1412 Slog.w(TAG, "remove() with no intent or listener");
1413 return;
1414 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001415
Christopher Tate14a7bb02015-10-01 10:24:31 -07001416 synchronized (mLock) {
1417 removeLocked(operation, listener);
1418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001420
Adam Lesinski182f73f2013-12-05 16:48:06 -08001421 @Override
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001422 public long getNextWakeFromIdleTime() {
1423 return getNextWakeFromIdleTimeImpl();
1424 }
1425
1426 @Override
Jose Lima235510e2014-08-13 12:50:01 -07001427 public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001428 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1429 Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */,
1430 "getNextAlarmClock", null);
1431
1432 return getNextAlarmClockImpl(userId);
1433 }
1434
1435 @Override
Adam Lesinski182f73f2013-12-05 16:48:06 -08001436 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -06001437 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
Adam Lesinski182f73f2013-12-05 16:48:06 -08001438 dumpImpl(pw);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001439 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001440 };
Christopher Tate4cb338d2013-07-26 13:11:31 -07001441
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001442 public final class LocalService {
1443 public void setDeviceIdleUserWhitelist(int[] appids) {
1444 setDeviceIdleUserWhitelistImpl(appids);
1445 }
1446 }
1447
Adam Lesinski182f73f2013-12-05 16:48:06 -08001448 void dumpImpl(PrintWriter pw) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 synchronized (mLock) {
1450 pw.println("Current Alarm Manager state:");
Dianne Hackborna750a632015-06-16 17:18:23 -07001451 mConstants.dump(pw);
1452 pw.println();
1453
Christopher Tatee0a22b32013-07-11 14:43:13 -07001454 final long nowRTC = System.currentTimeMillis();
1455 final long nowELAPSED = SystemClock.elapsedRealtime();
1456 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1457
Dianne Hackborna750a632015-06-16 17:18:23 -07001458 pw.print(" nowRTC="); pw.print(nowRTC);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001459 pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
Christopher Tate7f2a0352015-12-08 10:24:33 -08001460 pw.print(" nowELAPSED="); pw.print(nowELAPSED);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001461 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001462 pw.print(" mLastTimeChangeClockTime="); pw.print(mLastTimeChangeClockTime);
Dianne Hackbornc3527222015-05-13 14:03:20 -07001463 pw.print("="); pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
Dianne Hackborna750a632015-06-16 17:18:23 -07001464 pw.print(" mLastTimeChangeRealtime=");
Dianne Hackbornc3527222015-05-13 14:03:20 -07001465 TimeUtils.formatDuration(mLastTimeChangeRealtime, pw);
1466 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001467 if (!mInteractive) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001468 pw.print(" Time since non-interactive: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001469 TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
1470 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001471 pw.print(" Max wakeup delay: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001472 TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
1473 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001474 pw.print(" Time since last dispatch: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001475 TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
1476 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001477 pw.print(" Next non-wakeup delivery time: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001478 TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
1479 pw.println();
1480 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001481
1482 long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
1483 long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
Dianne Hackborna750a632015-06-16 17:18:23 -07001484 pw.print(" Next non-wakeup alarm: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001485 TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001486 pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
Dianne Hackborna750a632015-06-16 17:18:23 -07001487 pw.print(" Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001488 pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07001489 pw.print(" Last wakeup: "); TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw);
1490 pw.print(" set at "); TimeUtils.formatDuration(mLastWakeupSet, nowELAPSED, pw);
1491 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001492 pw.print(" Num time change events: "); pw.println(mNumTimeChanged);
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001493 pw.println(" mDeviceIdleUserWhitelist=" + Arrays.toString(mDeviceIdleUserWhitelist));
Christopher Tatee0a22b32013-07-11 14:43:13 -07001494
John Spurlock604a5ee2015-06-01 12:27:22 -04001495 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001496 pw.println(" Next alarm clock information: ");
John Spurlock604a5ee2015-06-01 12:27:22 -04001497 final TreeSet<Integer> users = new TreeSet<>();
1498 for (int i = 0; i < mNextAlarmClockForUser.size(); i++) {
1499 users.add(mNextAlarmClockForUser.keyAt(i));
1500 }
1501 for (int i = 0; i < mPendingSendNextAlarmClockChangedForUser.size(); i++) {
1502 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
1503 }
1504 for (int user : users) {
1505 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
1506 final long time = next != null ? next.getTriggerTime() : 0;
1507 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
Dianne Hackborna750a632015-06-16 17:18:23 -07001508 pw.print(" user:"); pw.print(user);
John Spurlock604a5ee2015-06-01 12:27:22 -04001509 pw.print(" pendingSend:"); pw.print(pendingSend);
1510 pw.print(" time:"); pw.print(time);
1511 if (time > 0) {
1512 pw.print(" = "); pw.print(sdf.format(new Date(time)));
1513 pw.print(" = "); TimeUtils.formatDuration(time, nowRTC, pw);
1514 }
1515 pw.println();
1516 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001517 if (mAlarmBatches.size() > 0) {
1518 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001519 pw.print(" Pending alarm batches: ");
Christopher Tatee0a22b32013-07-11 14:43:13 -07001520 pw.println(mAlarmBatches.size());
1521 for (Batch b : mAlarmBatches) {
1522 pw.print(b); pw.println(':');
Dianne Hackborna750a632015-06-16 17:18:23 -07001523 dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001524 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001525 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001526 if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001527 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001528 pw.println(" Idle mode state:");
1529 pw.print(" Idling until: ");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001530 if (mPendingIdleUntil != null) {
1531 pw.println(mPendingIdleUntil);
Dianne Hackbornf3831292015-10-15 14:51:06 -07001532 mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001533 } else {
1534 pw.println("null");
1535 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001536 pw.println(" Pending alarms:");
1537 dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001538 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001539 if (mNextWakeFromIdle != null) {
1540 pw.println();
1541 pw.print(" Next wake from idle: "); pw.println(mNextWakeFromIdle);
1542 mNextWakeFromIdle.dump(pw, " ", nowRTC, nowELAPSED, sdf);
1543 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001544
1545 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001546 pw.print(" Past-due non-wakeup alarms: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001547 if (mPendingNonWakeupAlarms.size() > 0) {
1548 pw.println(mPendingNonWakeupAlarms.size());
Dianne Hackborna750a632015-06-16 17:18:23 -07001549 dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001550 } else {
1551 pw.println("(none)");
1552 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001553 pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001554 pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
1555 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001556 pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001557 pw.print(", max non-interactive time: ");
1558 TimeUtils.formatDuration(mNonInteractiveTime, pw);
1559 pw.println();
1560
1561 pw.println();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001562 pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
Dianne Hackborn81038902012-11-26 17:04:09 -08001563 pw.println();
1564
Christopher Tate7f2a0352015-12-08 10:24:33 -08001565 if (mInFlight.size() > 0) {
1566 pw.println("Outstanding deliveries:");
1567 for (int i = 0; i < mInFlight.size(); i++) {
1568 pw.print(" #"); pw.print(i); pw.print(": ");
1569 pw.println(mInFlight.get(i));
1570 }
1571 pw.println();
1572 }
1573
Dianne Hackborna750a632015-06-16 17:18:23 -07001574 pw.print(" mAllowWhileIdleMinTime=");
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001575 TimeUtils.formatDuration(mAllowWhileIdleMinTime, pw);
1576 pw.println();
1577 if (mLastAllowWhileIdleDispatch.size() > 0) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001578 pw.println(" Last allow while idle dispatch times:");
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001579 for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
1580 pw.print(" UID ");
1581 UserHandle.formatUid(pw, mLastAllowWhileIdleDispatch.keyAt(i));
1582 pw.print(": ");
1583 TimeUtils.formatDuration(mLastAllowWhileIdleDispatch.valueAt(i),
1584 nowELAPSED, pw);
1585 pw.println();
1586 }
1587 }
1588 pw.println();
1589
Dianne Hackborn81038902012-11-26 17:04:09 -08001590 if (mLog.dump(pw, " Recent problems", " ")) {
1591 pw.println();
1592 }
1593
1594 final FilterStats[] topFilters = new FilterStats[10];
1595 final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
1596 @Override
1597 public int compare(FilterStats lhs, FilterStats rhs) {
1598 if (lhs.aggregateTime < rhs.aggregateTime) {
1599 return 1;
1600 } else if (lhs.aggregateTime > rhs.aggregateTime) {
1601 return -1;
1602 }
1603 return 0;
1604 }
1605 };
1606 int len = 0;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001607 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
1608 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
1609 for (int ip=0; ip<uidStats.size(); ip++) {
1610 BroadcastStats bs = uidStats.valueAt(ip);
1611 for (int is=0; is<bs.filterStats.size(); is++) {
1612 FilterStats fs = bs.filterStats.valueAt(is);
1613 int pos = len > 0
1614 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
1615 if (pos < 0) {
1616 pos = -pos - 1;
Dianne Hackborn81038902012-11-26 17:04:09 -08001617 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001618 if (pos < topFilters.length) {
1619 int copylen = topFilters.length - pos - 1;
1620 if (copylen > 0) {
1621 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
1622 }
1623 topFilters[pos] = fs;
1624 if (len < topFilters.length) {
1625 len++;
1626 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001627 }
1628 }
1629 }
1630 }
1631 if (len > 0) {
1632 pw.println(" Top Alarms:");
1633 for (int i=0; i<len; i++) {
1634 FilterStats fs = topFilters[i];
1635 pw.print(" ");
1636 if (fs.nesting > 0) pw.print("*ACTIVE* ");
1637 TimeUtils.formatDuration(fs.aggregateTime, pw);
1638 pw.print(" running, "); pw.print(fs.numWakeup);
1639 pw.print(" wakeups, "); pw.print(fs.count);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001640 pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
1641 pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
Dianne Hackborn81038902012-11-26 17:04:09 -08001642 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001643 pw.print(" "); pw.print(fs.mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08001644 pw.println();
1645 }
1646 }
1647
1648 pw.println(" ");
1649 pw.println(" Alarm Stats:");
1650 final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001651 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
1652 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
1653 for (int ip=0; ip<uidStats.size(); ip++) {
1654 BroadcastStats bs = uidStats.valueAt(ip);
1655 pw.print(" ");
1656 if (bs.nesting > 0) pw.print("*ACTIVE* ");
1657 UserHandle.formatUid(pw, bs.mUid);
1658 pw.print(":");
1659 pw.print(bs.mPackageName);
1660 pw.print(" "); TimeUtils.formatDuration(bs.aggregateTime, pw);
1661 pw.print(" running, "); pw.print(bs.numWakeup);
1662 pw.println(" wakeups:");
1663 tmpFilters.clear();
1664 for (int is=0; is<bs.filterStats.size(); is++) {
1665 tmpFilters.add(bs.filterStats.valueAt(is));
1666 }
1667 Collections.sort(tmpFilters, comparator);
1668 for (int i=0; i<tmpFilters.size(); i++) {
1669 FilterStats fs = tmpFilters.get(i);
1670 pw.print(" ");
1671 if (fs.nesting > 0) pw.print("*ACTIVE* ");
1672 TimeUtils.formatDuration(fs.aggregateTime, pw);
1673 pw.print(" "); pw.print(fs.numWakeup);
1674 pw.print(" wakes " ); pw.print(fs.count);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001675 pw.print(" alarms, last ");
1676 TimeUtils.formatDuration(fs.lastTime, nowELAPSED, pw);
1677 pw.println(":");
1678 pw.print(" ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001679 pw.print(fs.mTag);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001680 pw.println();
1681 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 }
1683 }
Christopher Tate18a75f12013-07-01 18:18:59 -07001684
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001685 if (RECORD_DEVICE_IDLE_ALARMS) {
1686 pw.println();
1687 pw.println(" Allow while idle dispatches:");
1688 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
1689 IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
1690 pw.print(" ");
1691 TimeUtils.formatDuration(ent.elapsedRealtime, nowELAPSED, pw);
1692 pw.print(": ");
1693 UserHandle.formatUid(pw, ent.uid);
1694 pw.print(":");
1695 pw.println(ent.pkg);
1696 if (ent.op != null) {
1697 pw.print(" ");
1698 pw.print(ent.op);
1699 pw.print(" / ");
1700 pw.print(ent.tag);
1701 if (ent.argRealtime != 0) {
1702 pw.print(" (");
1703 TimeUtils.formatDuration(ent.argRealtime, nowELAPSED, pw);
1704 pw.print(")");
1705 }
1706 pw.println();
1707 }
1708 }
1709 }
1710
Christopher Tate18a75f12013-07-01 18:18:59 -07001711 if (WAKEUP_STATS) {
1712 pw.println();
1713 pw.println(" Recent Wakeup History:");
Christopher Tate18a75f12013-07-01 18:18:59 -07001714 long last = -1;
1715 for (WakeupEvent event : mRecentWakeups) {
1716 pw.print(" "); pw.print(sdf.format(new Date(event.when)));
1717 pw.print('|');
1718 if (last < 0) {
1719 pw.print('0');
1720 } else {
1721 pw.print(event.when - last);
1722 }
1723 last = event.when;
1724 pw.print('|'); pw.print(event.uid);
1725 pw.print('|'); pw.print(event.action);
1726 pw.println();
1727 }
1728 pw.println();
1729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730 }
1731 }
1732
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001733 private void logBatchesLocked(SimpleDateFormat sdf) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001734 ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
1735 PrintWriter pw = new PrintWriter(bs);
1736 final long nowRTC = System.currentTimeMillis();
1737 final long nowELAPSED = SystemClock.elapsedRealtime();
1738 final int NZ = mAlarmBatches.size();
1739 for (int iz = 0; iz < NZ; iz++) {
1740 Batch bz = mAlarmBatches.get(iz);
1741 pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001742 dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC, sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001743 pw.flush();
1744 Slog.v(TAG, bs.toString());
1745 bs.reset();
1746 }
1747 }
1748
1749 private boolean validateConsistencyLocked() {
1750 if (DEBUG_VALIDATE) {
1751 long lastTime = Long.MIN_VALUE;
1752 final int N = mAlarmBatches.size();
1753 for (int i = 0; i < N; i++) {
1754 Batch b = mAlarmBatches.get(i);
1755 if (b.start >= lastTime) {
1756 // duplicate start times are okay because of standalone batches
1757 lastTime = b.start;
1758 } else {
1759 Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001760 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1761 logBatchesLocked(sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001762 return false;
1763 }
1764 }
1765 }
1766 return true;
1767 }
1768
Christopher Tate0dab4dc2014-12-16 12:14:06 -08001769 private Batch findFirstWakeupBatchLocked() {
1770 final int N = mAlarmBatches.size();
1771 for (int i = 0; i < N; i++) {
1772 Batch b = mAlarmBatches.get(i);
1773 if (b.hasWakeups()) {
1774 return b;
1775 }
1776 }
1777 return null;
1778 }
1779
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001780 long getNextWakeFromIdleTimeImpl() {
1781 synchronized (mLock) {
1782 return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE;
1783 }
1784 }
1785
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001786 void setDeviceIdleUserWhitelistImpl(int[] appids) {
1787 synchronized (mLock) {
1788 mDeviceIdleUserWhitelist = appids;
1789 }
1790 }
1791
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001792 AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001793 synchronized (mLock) {
1794 return mNextAlarmClockForUser.get(userId);
1795 }
1796 }
1797
1798 /**
1799 * Recomputes the next alarm clock for all users.
1800 */
1801 private void updateNextAlarmClockLocked() {
1802 if (!mNextAlarmClockMayChange) {
1803 return;
1804 }
1805 mNextAlarmClockMayChange = false;
1806
Jose Lima235510e2014-08-13 12:50:01 -07001807 SparseArray<AlarmManager.AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02001808 nextForUser.clear();
1809
1810 final int N = mAlarmBatches.size();
1811 for (int i = 0; i < N; i++) {
1812 ArrayList<Alarm> alarms = mAlarmBatches.get(i).alarms;
1813 final int M = alarms.size();
1814
1815 for (int j = 0; j < M; j++) {
1816 Alarm a = alarms.get(j);
1817 if (a.alarmClock != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001818 final int userId = UserHandle.getUserId(a.uid);
Christopher Tate76389c02016-08-03 14:57:47 -07001819 AlarmManager.AlarmClockInfo current = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02001820
1821 if (DEBUG_ALARM_CLOCK) {
Christopher Tate76389c02016-08-03 14:57:47 -07001822 Log.v(TAG, "Found AlarmClockInfo " + a.alarmClock + " at " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01001823 formatNextAlarm(getContext(), a.alarmClock, userId) +
Adrian Roosc42a1e12014-07-07 23:35:53 +02001824 " for user " + userId);
1825 }
1826
1827 // Alarms and batches are sorted by time, no need to compare times here.
1828 if (nextForUser.get(userId) == null) {
1829 nextForUser.put(userId, a.alarmClock);
Christopher Tate76389c02016-08-03 14:57:47 -07001830 } else if (a.alarmClock.equals(current)
1831 && current.getTriggerTime() <= nextForUser.get(userId).getTriggerTime()) {
1832 // same/earlier time and it's the one we cited before, so stick with it
1833 nextForUser.put(userId, current);
Adrian Roosc42a1e12014-07-07 23:35:53 +02001834 }
1835 }
1836 }
1837 }
1838
1839 // Update mNextAlarmForUser with new values.
1840 final int NN = nextForUser.size();
1841 for (int i = 0; i < NN; i++) {
Jose Lima235510e2014-08-13 12:50:01 -07001842 AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02001843 int userId = nextForUser.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07001844 AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02001845 if (!newAlarm.equals(currentAlarm)) {
1846 updateNextAlarmInfoForUserLocked(userId, newAlarm);
1847 }
1848 }
1849
1850 // Remove users without any alarm clocks scheduled.
1851 final int NNN = mNextAlarmClockForUser.size();
1852 for (int i = NNN - 1; i >= 0; i--) {
1853 int userId = mNextAlarmClockForUser.keyAt(i);
1854 if (nextForUser.get(userId) == null) {
1855 updateNextAlarmInfoForUserLocked(userId, null);
1856 }
1857 }
1858 }
1859
Jose Lima235510e2014-08-13 12:50:01 -07001860 private void updateNextAlarmInfoForUserLocked(int userId,
1861 AlarmManager.AlarmClockInfo alarmClock) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001862 if (alarmClock != null) {
1863 if (DEBUG_ALARM_CLOCK) {
1864 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01001865 formatNextAlarm(getContext(), alarmClock, userId));
Adrian Roosc42a1e12014-07-07 23:35:53 +02001866 }
1867 mNextAlarmClockForUser.put(userId, alarmClock);
1868 } else {
1869 if (DEBUG_ALARM_CLOCK) {
1870 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None");
1871 }
1872 mNextAlarmClockForUser.remove(userId);
1873 }
1874
1875 mPendingSendNextAlarmClockChangedForUser.put(userId, true);
1876 mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
1877 mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
1878 }
1879
1880 /**
1881 * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
1882 * for which alarm clocks have changed since the last call to this.
1883 *
1884 * Do not call with a lock held. Only call from mHandler's thread.
1885 *
1886 * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
1887 */
1888 private void sendNextAlarmClockChanged() {
Jose Lima235510e2014-08-13 12:50:01 -07001889 SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02001890 pendingUsers.clear();
1891
1892 synchronized (mLock) {
1893 final int N = mPendingSendNextAlarmClockChangedForUser.size();
1894 for (int i = 0; i < N; i++) {
1895 int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i);
1896 pendingUsers.append(userId, mNextAlarmClockForUser.get(userId));
1897 }
1898 mPendingSendNextAlarmClockChangedForUser.clear();
1899 }
1900
1901 final int N = pendingUsers.size();
1902 for (int i = 0; i < N; i++) {
1903 int userId = pendingUsers.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07001904 AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02001905 Settings.System.putStringForUser(getContext().getContentResolver(),
1906 Settings.System.NEXT_ALARM_FORMATTED,
Selim Cinek9c4a7072014-11-21 17:44:34 +01001907 formatNextAlarm(getContext(), alarmClock, userId),
Adrian Roosc42a1e12014-07-07 23:35:53 +02001908 userId);
1909
1910 getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT,
1911 new UserHandle(userId));
1912 }
1913 }
1914
1915 /**
1916 * Formats an alarm like platform/packages/apps/DeskClock used to.
1917 */
Selim Cinek9c4a7072014-11-21 17:44:34 +01001918 private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info,
1919 int userId) {
1920 String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma";
Adrian Roosc42a1e12014-07-07 23:35:53 +02001921 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
1922 return (info == null) ? "" :
1923 DateFormat.format(pattern, info.getTriggerTime()).toString();
1924 }
1925
Adam Lesinski182f73f2013-12-05 16:48:06 -08001926 void rescheduleKernelAlarmsLocked() {
1927 // Schedule the next upcoming wakeup alarm. If there is a deliverable batch
1928 // prior to that which contains no wakeups, we schedule that as well.
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001929 long nextNonWakeup = 0;
Adam Lesinski182f73f2013-12-05 16:48:06 -08001930 if (mAlarmBatches.size() > 0) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08001931 final Batch firstWakeup = findFirstWakeupBatchLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08001932 final Batch firstBatch = mAlarmBatches.get(0);
Prashant Malani753e9e02015-06-10 17:43:49 -07001933 if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08001934 mNextWakeup = firstWakeup.start;
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07001935 mLastWakeupSet = SystemClock.elapsedRealtime();
Christopher Tate0dab4dc2014-12-16 12:14:06 -08001936 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001937 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001938 if (firstBatch != firstWakeup) {
1939 nextNonWakeup = firstBatch.start;
Adam Lesinski182f73f2013-12-05 16:48:06 -08001940 }
1941 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001942 if (mPendingNonWakeupAlarms.size() > 0) {
1943 if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
1944 nextNonWakeup = mNextNonWakeupDeliveryTime;
1945 }
1946 }
Prashant Malani753e9e02015-06-10 17:43:49 -07001947 if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001948 mNextNonWakeup = nextNonWakeup;
1949 setLocked(ELAPSED_REALTIME, nextNonWakeup);
1950 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001951 }
1952
Christopher Tate14a7bb02015-10-01 10:24:31 -07001953 private void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001954 boolean didRemove = false;
1955 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1956 Batch b = mAlarmBatches.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -07001957 didRemove |= b.remove(operation, directReceiver);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001958 if (b.size() == 0) {
1959 mAlarmBatches.remove(i);
1960 }
1961 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001962 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07001963 if (mPendingWhileIdleAlarms.get(i).matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001964 // Don't set didRemove, since this doesn't impact the scheduled alarms.
1965 mPendingWhileIdleAlarms.remove(i);
1966 }
1967 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001968
1969 if (didRemove) {
1970 if (DEBUG_BATCH) {
1971 Slog.v(TAG, "remove(operation) changed bounds; rebatching");
1972 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001973 boolean restorePending = false;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001974 if (mPendingIdleUntil != null && mPendingIdleUntil.matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001975 mPendingIdleUntil = null;
1976 restorePending = true;
1977 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07001978 if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001979 mNextWakeFromIdle = null;
1980 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001981 rebatchAllAlarmsLocked(true);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001982 if (restorePending) {
1983 restorePendingWhileIdleAlarmsLocked();
1984 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02001985 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08001986 }
1987 }
1988
1989 void removeLocked(String packageName) {
1990 boolean didRemove = false;
1991 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
1992 Batch b = mAlarmBatches.get(i);
1993 didRemove |= b.remove(packageName);
1994 if (b.size() == 0) {
1995 mAlarmBatches.remove(i);
1996 }
1997 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001998 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07001999 final Alarm a = mPendingWhileIdleAlarms.get(i);
2000 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002001 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2002 mPendingWhileIdleAlarms.remove(i);
2003 }
2004 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002005
2006 if (didRemove) {
2007 if (DEBUG_BATCH) {
2008 Slog.v(TAG, "remove(package) changed bounds; rebatching");
2009 }
2010 rebatchAllAlarmsLocked(true);
2011 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02002012 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002013 }
2014 }
2015
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002016 void removeForStoppedLocked(int uid) {
2017 boolean didRemove = false;
2018 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2019 Batch b = mAlarmBatches.get(i);
2020 didRemove |= b.removeForStopped(uid);
2021 if (b.size() == 0) {
2022 mAlarmBatches.remove(i);
2023 }
2024 }
2025 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
2026 final Alarm a = mPendingWhileIdleAlarms.get(i);
Dianne Hackborne07641d2016-11-09 15:07:23 -08002027 if (a.uid == uid) {
2028 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2029 mPendingWhileIdleAlarms.remove(i);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002030 }
2031 }
2032
2033 if (didRemove) {
2034 if (DEBUG_BATCH) {
2035 Slog.v(TAG, "remove(package) changed bounds; rebatching");
2036 }
2037 rebatchAllAlarmsLocked(true);
2038 rescheduleKernelAlarmsLocked();
2039 updateNextAlarmClockLocked();
2040 }
2041 }
2042
Adam Lesinski182f73f2013-12-05 16:48:06 -08002043 void removeUserLocked(int userHandle) {
2044 boolean didRemove = false;
2045 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2046 Batch b = mAlarmBatches.get(i);
2047 didRemove |= b.remove(userHandle);
2048 if (b.size() == 0) {
2049 mAlarmBatches.remove(i);
2050 }
2051 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002052 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002053 if (UserHandle.getUserId(mPendingWhileIdleAlarms.get(i).creatorUid)
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002054 == userHandle) {
2055 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2056 mPendingWhileIdleAlarms.remove(i);
2057 }
2058 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002059 for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
2060 if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
2061 mLastAllowWhileIdleDispatch.removeAt(i);
2062 }
2063 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002064
2065 if (didRemove) {
2066 if (DEBUG_BATCH) {
2067 Slog.v(TAG, "remove(user) changed bounds; rebatching");
2068 }
2069 rebatchAllAlarmsLocked(true);
2070 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02002071 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002072 }
2073 }
2074
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002075 void interactiveStateChangedLocked(boolean interactive) {
2076 if (mInteractive != interactive) {
2077 mInteractive = interactive;
2078 final long nowELAPSED = SystemClock.elapsedRealtime();
2079 if (interactive) {
2080 if (mPendingNonWakeupAlarms.size() > 0) {
2081 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
2082 mTotalDelayTime += thisDelayTime;
2083 if (mMaxDelayTime < thisDelayTime) {
2084 mMaxDelayTime = thisDelayTime;
2085 }
2086 deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
2087 mPendingNonWakeupAlarms.clear();
2088 }
2089 if (mNonInteractiveStartTime > 0) {
2090 long dur = nowELAPSED - mNonInteractiveStartTime;
2091 if (dur > mNonInteractiveTime) {
2092 mNonInteractiveTime = dur;
2093 }
2094 }
2095 } else {
2096 mNonInteractiveStartTime = nowELAPSED;
2097 }
2098 }
2099 }
2100
Adam Lesinski182f73f2013-12-05 16:48:06 -08002101 boolean lookForPackageLocked(String packageName) {
2102 for (int i = 0; i < mAlarmBatches.size(); i++) {
2103 Batch b = mAlarmBatches.get(i);
2104 if (b.hasPackage(packageName)) {
2105 return true;
2106 }
2107 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002108 for (int i = 0; i < mPendingWhileIdleAlarms.size(); i++) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002109 final Alarm a = mPendingWhileIdleAlarms.get(i);
2110 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002111 return true;
2112 }
2113 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002114 return false;
2115 }
2116
2117 private void setLocked(int type, long when) {
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -08002118 if (mNativeData != 0) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08002119 // The kernel never triggers alarms with negative wakeup times
2120 // so we ensure they are positive.
2121 long alarmSeconds, alarmNanoseconds;
2122 if (when < 0) {
2123 alarmSeconds = 0;
2124 alarmNanoseconds = 0;
2125 } else {
2126 alarmSeconds = when / 1000;
2127 alarmNanoseconds = (when % 1000) * 1000 * 1000;
2128 }
2129
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -08002130 set(mNativeData, type, alarmSeconds, alarmNanoseconds);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002131 } else {
2132 Message msg = Message.obtain();
2133 msg.what = ALARM_EVENT;
2134
2135 mHandler.removeMessages(ALARM_EVENT);
2136 mHandler.sendMessageAtTime(msg, when);
2137 }
2138 }
2139
Dianne Hackborn043fcd92010-10-06 14:27:34 -07002140 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002141 String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 for (int i=list.size()-1; i>=0; i--) {
2143 Alarm a = list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002144 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
2145 pw.print(": "); pw.println(a);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002146 a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 }
2148 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002149
2150 private static final String labelForType(int type) {
2151 switch (type) {
2152 case RTC: return "RTC";
2153 case RTC_WAKEUP : return "RTC_WAKEUP";
2154 case ELAPSED_REALTIME : return "ELAPSED";
2155 case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP";
2156 default:
2157 break;
2158 }
2159 return "--unknown--";
2160 }
2161
2162 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002163 String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07002164 for (int i=list.size()-1; i>=0; i--) {
2165 Alarm a = list.get(i);
2166 final String label = labelForType(a.type);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002167 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
2168 pw.print(": "); pw.println(a);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002169 a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002170 }
2171 }
2172
Greg Hackmanna1d6f922013-12-09 16:56:53 -08002173 private native long init();
2174 private native void close(long nativeData);
2175 private native void set(long nativeData, int type, long seconds, long nanoseconds);
2176 private native int waitForAlarm(long nativeData);
Greg Hackmann38bf5142014-02-19 16:39:36 -08002177 private native int setKernelTime(long nativeData, long millis);
Greg Hackmanna1d6f922013-12-09 16:56:53 -08002178 private native int setKernelTimezone(long nativeData, int minuteswest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002180 boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002181 final long nowRTC) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002182 boolean hasWakeup = false;
Christopher Tatee0a22b32013-07-11 14:43:13 -07002183 // batches are temporally sorted, so we need only pull from the
2184 // start of the list until we either empty it or hit a batch
2185 // that is not yet deliverable
Christopher Tate6578ad12013-09-24 17:12:46 -07002186 while (mAlarmBatches.size() > 0) {
2187 Batch batch = mAlarmBatches.get(0);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002188 if (batch.start > nowELAPSED) {
2189 // Everything else is scheduled for the future
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002190 break;
2191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192
Christopher Tatee0a22b32013-07-11 14:43:13 -07002193 // We will (re)schedule some alarms now; don't let that interfere
2194 // with delivery of this current batch
2195 mAlarmBatches.remove(0);
Dianne Hackborn390517b2013-05-30 15:03:32 -07002196
Christopher Tatee0a22b32013-07-11 14:43:13 -07002197 final int N = batch.size();
2198 for (int i = 0; i < N; i++) {
2199 Alarm alarm = batch.get(i);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002200
2201 if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
2202 // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
2203 // schedule such alarms.
2204 long lastTime = mLastAllowWhileIdleDispatch.get(alarm.uid, 0);
2205 long minTime = lastTime + mAllowWhileIdleMinTime;
2206 if (nowELAPSED < minTime) {
2207 // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
2208 // alarm went off for this app. Reschedule the alarm to be in the
2209 // correct time period.
2210 alarm.whenElapsed = minTime;
2211 if (alarm.maxWhenElapsed < minTime) {
2212 alarm.maxWhenElapsed = minTime;
2213 }
Dianne Hackbornae78bf82015-10-26 13:33:20 -07002214 if (RECORD_DEVICE_IDLE_ALARMS) {
2215 IdleDispatchEntry ent = new IdleDispatchEntry();
2216 ent.uid = alarm.uid;
2217 ent.pkg = alarm.operation.getCreatorPackage();
2218 ent.tag = alarm.operation.getTag("");
2219 ent.op = "RESCHEDULE";
2220 ent.elapsedRealtime = nowELAPSED;
2221 ent.argRealtime = lastTime;
2222 mAllowWhileIdleDispatches.add(ent);
2223 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002224 setImplLocked(alarm, true, false);
2225 continue;
2226 }
2227 }
2228
Christopher Tatee0a22b32013-07-11 14:43:13 -07002229 alarm.count = 1;
2230 triggerList.add(alarm);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002231 if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
2232 EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
Christopher Tate14a7bb02015-10-01 10:24:31 -07002233 alarm.statsTag);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002234 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002235 if (mPendingIdleUntil == alarm) {
2236 mPendingIdleUntil = null;
2237 rebatchAllAlarmsLocked(false);
2238 restorePendingWhileIdleAlarmsLocked();
2239 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002240 if (mNextWakeFromIdle == alarm) {
2241 mNextWakeFromIdle = null;
2242 rebatchAllAlarmsLocked(false);
2243 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002244
2245 // Recurring alarms may have passed several alarm intervals while the
2246 // phone was asleep or off, so pass a trigger count when sending them.
2247 if (alarm.repeatInterval > 0) {
2248 // this adjustment will be zero if we're late by
2249 // less than one full repeat interval
2250 alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval;
2251
2252 // Also schedule its next recurrence
2253 final long delta = alarm.count * alarm.repeatInterval;
2254 final long nextElapsed = alarm.whenElapsed + delta;
Christopher Tate3e04b472013-10-21 17:51:31 -07002255 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
Christopher Tatee0a22b32013-07-11 14:43:13 -07002256 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
Christopher Tate14a7bb02015-10-01 10:24:31 -07002257 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
2258 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
Christopher Tate864d42e2014-12-02 11:48:53 -08002259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002260
Christopher Tate864d42e2014-12-02 11:48:53 -08002261 if (alarm.wakeup) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002262 hasWakeup = true;
2263 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02002264
2265 // We removed an alarm clock. Let the caller recompute the next alarm clock.
2266 if (alarm.alarmClock != null) {
2267 mNextAlarmClockMayChange = true;
2268 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002271
Christopher Tate1590f1e2014-10-02 17:27:57 -07002272 // This is a new alarm delivery set; bump the sequence number to indicate that
2273 // all apps' alarm delivery classes should be recalculated.
2274 mCurrentSeq++;
2275 calculateDeliveryPriorities(triggerList);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002276 Collections.sort(triggerList, mAlarmDispatchComparator);
2277
2278 if (localLOGV) {
2279 for (int i=0; i<triggerList.size(); i++) {
2280 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
2281 }
2282 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002283
2284 return hasWakeup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002287 /**
2288 * This Comparator sorts Alarms into increasing time order.
2289 */
2290 public static class IncreasingTimeOrder implements Comparator<Alarm> {
2291 public int compare(Alarm a1, Alarm a2) {
jinho.park1acd32a2015-05-27 14:44:18 +09002292 long when1 = a1.whenElapsed;
2293 long when2 = a2.whenElapsed;
Charles Tsaicdaaeee2015-05-20 18:16:48 +08002294 if (when1 > when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 return 1;
2296 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +08002297 if (when1 < when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002298 return -1;
2299 }
2300 return 0;
2301 }
2302 }
2303
2304 private static class Alarm {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002305 public final int type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002306 public final long origWhen;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002307 public final boolean wakeup;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002308 public final PendingIntent operation;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002309 public final IAlarmListener listener;
2310 public final String listenerTag;
2311 public final String statsTag;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002312 public final WorkSource workSource;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002313 public final int flags;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002314 public final AlarmManager.AlarmClockInfo alarmClock;
2315 public final int uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002316 public final int creatorUid;
2317 public final String packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 public int count;
2319 public long when;
Christopher Tate3e04b472013-10-21 17:51:31 -07002320 public long windowLength;
Christopher Tatee0a22b32013-07-11 14:43:13 -07002321 public long whenElapsed; // 'when' in the elapsed time base
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002322 public long maxWhenElapsed; // also in the elapsed time base
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 public long repeatInterval;
Christopher Tate1590f1e2014-10-02 17:27:57 -07002324 public PriorityClass priorityClass;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002325
Christopher Tate3e04b472013-10-21 17:51:31 -07002326 public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
Christopher Tate14a7bb02015-10-01 10:24:31 -07002327 long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag,
2328 WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info,
2329 int _uid, String _pkgName) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07002330 type = _type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002331 origWhen = _when;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002332 wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
2333 || _type == AlarmManager.RTC_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -07002334 when = _when;
2335 whenElapsed = _whenElapsed;
Christopher Tate3e04b472013-10-21 17:51:31 -07002336 windowLength = _windowLength;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002337 maxWhenElapsed = _maxWhen;
Christopher Tatee0a22b32013-07-11 14:43:13 -07002338 repeatInterval = _interval;
2339 operation = _op;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002340 listener = _rec;
2341 listenerTag = _listenerTag;
2342 statsTag = makeTag(_op, _listenerTag, _type);
David Christieebe51fc2013-07-26 13:23:29 -07002343 workSource = _ws;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002344 flags = _flags;
Adrian Roosc42a1e12014-07-07 23:35:53 +02002345 alarmClock = _info;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002346 uid = _uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002347 packageName = _pkgName;
2348
2349 creatorUid = (operation != null) ? operation.getCreatorUid() : uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002351
Christopher Tate14a7bb02015-10-01 10:24:31 -07002352 public static String makeTag(PendingIntent pi, String tag, int type) {
2353 final String alarmString = type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
2354 ? "*walarm*:" : "*alarm*:";
2355 return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag);
2356 }
2357
2358 public WakeupEvent makeWakeupEvent(long nowRTC) {
2359 return new WakeupEvent(nowRTC, creatorUid,
2360 (operation != null)
2361 ? operation.getIntent().getAction()
2362 : ("<listener>:" + listenerTag));
2363 }
2364
2365 // Returns true if either matches
2366 public boolean matches(PendingIntent pi, IAlarmListener rec) {
2367 return (operation != null)
2368 ? operation.equals(pi)
Lorenzo Colitti9b43ce02015-11-22 22:00:08 +09002369 : rec != null && listener.asBinder().equals(rec.asBinder());
Christopher Tate14a7bb02015-10-01 10:24:31 -07002370 }
2371
2372 public boolean matches(String packageName) {
2373 return (operation != null)
2374 ? packageName.equals(operation.getTargetPackage())
2375 : packageName.equals(this.packageName);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002376 }
2377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002378 @Override
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002379 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002380 StringBuilder sb = new StringBuilder(128);
2381 sb.append("Alarm{");
2382 sb.append(Integer.toHexString(System.identityHashCode(this)));
2383 sb.append(" type ");
2384 sb.append(type);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002385 sb.append(" when ");
2386 sb.append(when);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002387 sb.append(" ");
Christopher Tate14a7bb02015-10-01 10:24:31 -07002388 if (operation != null) {
2389 sb.append(operation.getTargetPackage());
2390 } else {
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07002391 sb.append(packageName);
Christopher Tate14a7bb02015-10-01 10:24:31 -07002392 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002393 sb.append('}');
2394 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002395 }
2396
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002397 public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED,
2398 SimpleDateFormat sdf) {
2399 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
Christopher Tate14a7bb02015-10-01 10:24:31 -07002400 pw.print(prefix); pw.print("tag="); pw.println(statsTag);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002401 pw.print(prefix); pw.print("type="); pw.print(type);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002402 pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
2403 nowELAPSED, pw);
Christopher Tate14a7bb02015-10-01 10:24:31 -07002404 pw.print(" when=");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002405 if (isRtc) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002406 pw.print(sdf.format(new Date(when)));
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002407 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002408 TimeUtils.formatDuration(when, nowELAPSED, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002409 }
2410 pw.println();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002411 pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002412 pw.print(" repeatInterval="); pw.print(repeatInterval);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002413 pw.print(" count="); pw.print(count);
2414 pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002415 if (alarmClock != null) {
2416 pw.print(prefix); pw.println("Alarm clock:");
2417 pw.print(prefix); pw.print(" triggerTime=");
2418 pw.println(sdf.format(new Date(alarmClock.getTriggerTime())));
2419 pw.print(prefix); pw.print(" showIntent="); pw.println(alarmClock.getShowIntent());
2420 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002421 pw.print(prefix); pw.print("operation="); pw.println(operation);
Christopher Tate14a7bb02015-10-01 10:24:31 -07002422 if (listener != null) {
2423 pw.print(prefix); pw.print("listener="); pw.println(listener.asBinder());
2424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002425 }
2426 }
Christopher Tate18a75f12013-07-01 18:18:59 -07002427
Christopher Tatee0a22b32013-07-11 14:43:13 -07002428 void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) {
2429 final int numBatches = batches.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07002430 for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) {
2431 Batch b = batches.get(nextBatch);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002432 if (b.start > nowELAPSED) {
Christopher Tate18a75f12013-07-01 18:18:59 -07002433 break;
2434 }
2435
Christopher Tatee0a22b32013-07-11 14:43:13 -07002436 final int numAlarms = b.alarms.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07002437 for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) {
2438 Alarm a = b.alarms.get(nextAlarm);
Christopher Tate14a7bb02015-10-01 10:24:31 -07002439 mRecentWakeups.add(a.makeWakeupEvent(nowRTC));
Christopher Tatee0a22b32013-07-11 14:43:13 -07002440 }
Christopher Tate18a75f12013-07-01 18:18:59 -07002441 }
2442 }
2443
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002444 long currentNonWakeupFuzzLocked(long nowELAPSED) {
2445 long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
2446 if (timeSinceOn < 5*60*1000) {
2447 // If the screen has been off for 5 minutes, only delay by at most two minutes.
2448 return 2*60*1000;
2449 } else if (timeSinceOn < 30*60*1000) {
2450 // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
2451 return 15*60*1000;
2452 } else {
2453 // Otherwise, we will delay by at most an hour.
2454 return 60*60*1000;
2455 }
2456 }
2457
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002458 static int fuzzForDuration(long duration) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002459 if (duration < 15*60*1000) {
2460 // If the duration until the time is less than 15 minutes, the maximum fuzz
2461 // is the duration.
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002462 return (int)duration;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002463 } else if (duration < 90*60*1000) {
2464 // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes,
2465 return 15*60*1000;
2466 } else {
2467 // Otherwise, we will fuzz by at most half an hour.
2468 return 30*60*1000;
2469 }
2470 }
2471
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002472 boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
2473 if (mInteractive) {
2474 return false;
2475 }
2476 if (mLastAlarmDeliveryTime <= 0) {
2477 return false;
2478 }
minho.choo649acab2014-12-12 16:13:55 +09002479 if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002480 // This is just a little paranoia, if somehow we have pending non-wakeup alarms
2481 // and the next delivery time is in the past, then just deliver them all. This
2482 // avoids bugs where we get stuck in a loop trying to poll for alarms.
2483 return false;
2484 }
2485 long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
2486 return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
2487 }
2488
2489 void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
2490 mLastAlarmDeliveryTime = nowELAPSED;
2491 for (int i=0; i<triggerList.size(); i++) {
2492 Alarm alarm = triggerList.get(i);
Dianne Hackborna750a632015-06-16 17:18:23 -07002493 final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002494 try {
Christopher Tate2ff5a732014-09-18 13:47:57 -07002495 if (localLOGV) {
2496 Slog.v(TAG, "sending alarm " + alarm);
2497 }
Dianne Hackborn1e383822015-04-10 14:02:33 -07002498 if (RECORD_ALARMS_IN_HISTORY) {
2499 if (alarm.workSource != null && alarm.workSource.size() > 0) {
2500 for (int wi=0; wi<alarm.workSource.size(); wi++) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002501 ActivityManager.noteAlarmStart(
Christopher Tate14a7bb02015-10-01 10:24:31 -07002502 alarm.operation, alarm.workSource.get(wi), alarm.statsTag);
Dianne Hackborn1e383822015-04-10 14:02:33 -07002503 }
2504 } else {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002505 ActivityManager.noteAlarmStart(
Christopher Tate14a7bb02015-10-01 10:24:31 -07002506 alarm.operation, alarm.uid, alarm.statsTag);
Dianne Hackborn1e383822015-04-10 14:02:33 -07002507 }
2508 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002509 mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002510 } catch (RuntimeException e) {
2511 Slog.w(TAG, "Failure sending alarm.", e);
2512 }
2513 }
2514 }
2515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 private class AlarmThread extends Thread
2517 {
2518 public AlarmThread()
2519 {
2520 super("AlarmManager");
2521 }
2522
2523 public void run()
2524 {
Dianne Hackborn390517b2013-05-30 15:03:32 -07002525 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
2526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 while (true)
2528 {
Greg Hackmanna1d6f922013-12-09 16:56:53 -08002529 int result = waitForAlarm(mNativeData);
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07002530 mLastWakeup = SystemClock.elapsedRealtime();
Dianne Hackborn390517b2013-05-30 15:03:32 -07002531
2532 triggerList.clear();
2533
Dianne Hackbornc3527222015-05-13 14:03:20 -07002534 final long nowRTC = System.currentTimeMillis();
2535 final long nowELAPSED = SystemClock.elapsedRealtime();
2536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 if ((result & TIME_CHANGED_MASK) != 0) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07002538 // The kernel can give us spurious time change notifications due to
2539 // small adjustments it makes internally; we want to filter those out.
2540 final long lastTimeChangeClockTime;
2541 final long expectedClockTime;
Dianne Hackborn998e6082014-09-11 19:13:23 -07002542 synchronized (mLock) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07002543 lastTimeChangeClockTime = mLastTimeChangeClockTime;
2544 expectedClockTime = lastTimeChangeClockTime
2545 + (nowELAPSED - mLastTimeChangeRealtime);
Dianne Hackborn998e6082014-09-11 19:13:23 -07002546 }
Christopher Tate2b6e459e2017-02-17 14:33:52 -08002547 if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-1000)
2548 || nowRTC > (expectedClockTime+1000)) {
2549 // The change is by at least +/- 1000 ms (or this is the first change),
Dianne Hackbornc3527222015-05-13 14:03:20 -07002550 // let's do it!
2551 if (DEBUG_BATCH) {
2552 Slog.v(TAG, "Time changed notification from kernel; rebatching");
2553 }
2554 removeImpl(mTimeTickSender);
Christopher Tatecf024712016-08-05 13:21:45 -07002555 removeImpl(mDateChangeSender);
Dianne Hackbornc3527222015-05-13 14:03:20 -07002556 rebatchAllAlarms();
2557 mClockReceiver.scheduleTimeTickEvent();
Christopher Tatecf024712016-08-05 13:21:45 -07002558 mClockReceiver.scheduleDateChangedEvent();
Dianne Hackbornc3527222015-05-13 14:03:20 -07002559 synchronized (mLock) {
2560 mNumTimeChanged++;
2561 mLastTimeChangeClockTime = nowRTC;
2562 mLastTimeChangeRealtime = nowELAPSED;
2563 }
2564 Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
2565 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
Christopher Tate2b6e459e2017-02-17 14:33:52 -08002566 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
Chad Brubaker291df4f2017-03-14 10:23:02 -07002567 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
2568 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Dianne Hackbornc3527222015-05-13 14:03:20 -07002569 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
2570
2571 // The world has changed on us, so we need to re-evaluate alarms
2572 // regardless of whether the kernel has told us one went off.
2573 result |= IS_WAKEUP_MASK;
2574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576
Dianne Hackbornc3527222015-05-13 14:03:20 -07002577 if (result != TIME_CHANGED_MASK) {
2578 // If this was anything besides just a time change, then figure what if
2579 // anything to do about alarms.
2580 synchronized (mLock) {
2581 if (localLOGV) Slog.v(
2582 TAG, "Checking for alarms... rtc=" + nowRTC
2583 + ", elapsed=" + nowELAPSED);
Christopher Tate18a75f12013-07-01 18:18:59 -07002584
Dianne Hackbornc3527222015-05-13 14:03:20 -07002585 if (WAKEUP_STATS) {
2586 if ((result & IS_WAKEUP_MASK) != 0) {
2587 long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
2588 int n = 0;
2589 for (WakeupEvent event : mRecentWakeups) {
2590 if (event.when > newEarliest) break;
2591 n++; // number of now-stale entries at the list head
2592 }
2593 for (int i = 0; i < n; i++) {
2594 mRecentWakeups.remove();
2595 }
Christopher Tate18a75f12013-07-01 18:18:59 -07002596
Dianne Hackbornc3527222015-05-13 14:03:20 -07002597 recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002598 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002599 }
Dianne Hackbornc3527222015-05-13 14:03:20 -07002600
2601 boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2602 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
2603 // if there are no wakeup alarms and the screen is off, we can
2604 // delay what we have so far until the future.
2605 if (mPendingNonWakeupAlarms.size() == 0) {
2606 mStartCurrentDelayTime = nowELAPSED;
2607 mNextNonWakeupDeliveryTime = nowELAPSED
2608 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
2609 }
2610 mPendingNonWakeupAlarms.addAll(triggerList);
2611 mNumDelayedAlarms += triggerList.size();
2612 rescheduleKernelAlarmsLocked();
2613 updateNextAlarmClockLocked();
2614 } else {
2615 // now deliver the alarm intents; if there are pending non-wakeup
2616 // alarms, we need to merge them in to the list. note we don't
2617 // just deliver them first because we generally want non-wakeup
2618 // alarms delivered after wakeup alarms.
2619 rescheduleKernelAlarmsLocked();
2620 updateNextAlarmClockLocked();
2621 if (mPendingNonWakeupAlarms.size() > 0) {
2622 calculateDeliveryPriorities(mPendingNonWakeupAlarms);
2623 triggerList.addAll(mPendingNonWakeupAlarms);
2624 Collections.sort(triggerList, mAlarmDispatchComparator);
2625 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
2626 mTotalDelayTime += thisDelayTime;
2627 if (mMaxDelayTime < thisDelayTime) {
2628 mMaxDelayTime = thisDelayTime;
2629 }
2630 mPendingNonWakeupAlarms.clear();
2631 }
2632 deliverAlarmsLocked(triggerList, nowELAPSED);
2633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 }
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07002635
2636 } else {
2637 // Just in case -- even though no wakeup flag was set, make sure
2638 // we have updated the kernel to the next alarm time.
Christopher Tate7b5b7cb2016-07-07 14:41:36 -07002639 synchronized (mLock) {
2640 rescheduleKernelAlarmsLocked();
2641 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002642 }
2643 }
2644 }
2645 }
Christopher Tatec4a07d12012-04-06 14:19:13 -07002646
David Christieebe51fc2013-07-26 13:23:29 -07002647 /**
2648 * Attribute blame for a WakeLock.
2649 * @param pi PendingIntent to attribute blame to if ws is null.
2650 * @param ws WorkSource to attribute blame.
Christopher Tate14a7bb02015-10-01 10:24:31 -07002651 * @param knownUid attribution uid; < 0 if we need to derive it from the PendingIntent sender
David Christieebe51fc2013-07-26 13:23:29 -07002652 */
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002653 void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
Christopher Tate14a7bb02015-10-01 10:24:31 -07002654 int knownUid, boolean first) {
Christopher Tatec4a07d12012-04-06 14:19:13 -07002655 try {
Dianne Hackborna1bd7922014-03-21 11:07:11 -07002656 final boolean unimportant = pi == mTimeTickSender;
2657 mWakeLock.setUnimportantForLogging(unimportant);
Dianne Hackborn4590e522014-03-24 13:36:46 -07002658 if (first || mLastWakeLockUnimportantForLogging) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002659 mWakeLock.setHistoryTag(tag);
Dianne Hackborn4590e522014-03-24 13:36:46 -07002660 } else {
2661 mWakeLock.setHistoryTag(null);
2662 }
2663 mLastWakeLockUnimportantForLogging = unimportant;
David Christieebe51fc2013-07-26 13:23:29 -07002664 if (ws != null) {
2665 mWakeLock.setWorkSource(ws);
2666 return;
2667 }
2668
Christopher Tate14a7bb02015-10-01 10:24:31 -07002669 final int uid = (knownUid >= 0)
2670 ? knownUid
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002671 : ActivityManager.getService().getUidForIntentSender(pi.getTarget());
Christopher Tatec4a07d12012-04-06 14:19:13 -07002672 if (uid >= 0) {
2673 mWakeLock.setWorkSource(new WorkSource(uid));
2674 return;
2675 }
2676 } catch (Exception e) {
2677 }
2678
2679 // Something went wrong; fall back to attributing the lock to the OS
2680 mWakeLock.setWorkSource(null);
2681 }
2682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 private class AlarmHandler extends Handler {
2684 public static final int ALARM_EVENT = 1;
Dianne Hackborn627dfa12015-11-11 18:10:30 -08002685 public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2;
2686 public static final int LISTENER_TIMEOUT = 3;
2687 public static final int REPORT_ALARMS_ACTIVE = 4;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002688
2689 public AlarmHandler() {
2690 }
2691
2692 public void handleMessage(Message msg) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002693 switch (msg.what) {
2694 case ALARM_EVENT: {
2695 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
2696 synchronized (mLock) {
2697 final long nowRTC = System.currentTimeMillis();
2698 final long nowELAPSED = SystemClock.elapsedRealtime();
2699 triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2700 updateNextAlarmClockLocked();
2701 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02002702
Christopher Tate14a7bb02015-10-01 10:24:31 -07002703 // now trigger the alarms without the lock held
2704 for (int i=0; i<triggerList.size(); i++) {
2705 Alarm alarm = triggerList.get(i);
2706 try {
2707 alarm.operation.send();
2708 } catch (PendingIntent.CanceledException e) {
2709 if (alarm.repeatInterval > 0) {
2710 // This IntentSender is no longer valid, but this
2711 // is a repeating alarm, so toss the hoser.
2712 removeImpl(alarm.operation);
2713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 }
2715 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002716 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002718
2719 case SEND_NEXT_ALARM_CLOCK_CHANGED:
2720 sendNextAlarmClockChanged();
2721 break;
2722
2723 case LISTENER_TIMEOUT:
2724 mDeliveryTracker.alarmTimedOut((IBinder) msg.obj);
2725 break;
2726
Dianne Hackborn627dfa12015-11-11 18:10:30 -08002727 case REPORT_ALARMS_ACTIVE:
2728 if (mLocalDeviceIdleController != null) {
2729 mLocalDeviceIdleController.setAlarmsActive(msg.arg1 != 0);
2730 }
2731 break;
2732
Christopher Tate14a7bb02015-10-01 10:24:31 -07002733 default:
2734 // nope, just ignore it
2735 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002736 }
2737 }
2738 }
2739
2740 class ClockReceiver extends BroadcastReceiver {
2741 public ClockReceiver() {
2742 IntentFilter filter = new IntentFilter();
2743 filter.addAction(Intent.ACTION_TIME_TICK);
2744 filter.addAction(Intent.ACTION_DATE_CHANGED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002745 getContext().registerReceiver(this, filter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002746 }
2747
2748 @Override
2749 public void onReceive(Context context, Intent intent) {
2750 if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
Christopher Tate385e4982013-07-23 18:22:29 -07002751 if (DEBUG_BATCH) {
2752 Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
2753 }
2754 scheduleTimeTickEvent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
2756 // Since the kernel does not keep track of DST, we need to
2757 // reset the TZ information at the beginning of each day
2758 // based off of the current Zone gmt offset + userspace tracked
2759 // daylight savings information.
2760 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
Lavettacn Xiaoc84cc4f2010-08-30 12:47:23 +02002761 int gmtOffset = zone.getOffset(System.currentTimeMillis());
Greg Hackmanna1d6f922013-12-09 16:56:53 -08002762 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
Christopher Tate385e4982013-07-23 18:22:29 -07002763 scheduleDateChangedEvent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002764 }
2765 }
2766
2767 public void scheduleTimeTickEvent() {
Paul Westbrook51608a52011-08-25 13:18:54 -07002768 final long currentTime = System.currentTimeMillis();
Sungmin Choi563914a2013-01-10 17:28:40 +09002769 final long nextTime = 60000 * ((currentTime / 60000) + 1);
Paul Westbrook51608a52011-08-25 13:18:54 -07002770
2771 // Schedule this event for the amount of time that it would take to get to
2772 // the top of the next minute.
Sungmin Choi563914a2013-01-10 17:28:40 +09002773 final long tickEventDelay = nextTime - currentTime;
Paul Westbrook51608a52011-08-25 13:18:54 -07002774
David Christieebe51fc2013-07-26 13:23:29 -07002775 final WorkSource workSource = null; // Let system take blame for time tick events.
Adam Lesinski182f73f2013-12-05 16:48:06 -08002776 setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
Christopher Tate14a7bb02015-10-01 10:24:31 -07002777 0, mTimeTickSender, null, null, AlarmManager.FLAG_STANDALONE, workSource,
2778 null, Process.myUid(), "android");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 }
Christopher Tate385e4982013-07-23 18:22:29 -07002780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781 public void scheduleDateChangedEvent() {
2782 Calendar calendar = Calendar.getInstance();
2783 calendar.setTimeInMillis(System.currentTimeMillis());
Christopher Tateafa8b982016-08-10 16:15:48 -07002784 calendar.set(Calendar.HOUR_OF_DAY, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002785 calendar.set(Calendar.MINUTE, 0);
2786 calendar.set(Calendar.SECOND, 0);
2787 calendar.set(Calendar.MILLISECOND, 0);
2788 calendar.add(Calendar.DAY_OF_MONTH, 1);
David Christieebe51fc2013-07-26 13:23:29 -07002789
2790 final WorkSource workSource = null; // Let system take blame for date change events.
Christopher Tate14a7bb02015-10-01 10:24:31 -07002791 setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
2792 AlarmManager.FLAG_STANDALONE, workSource, null,
2793 Process.myUid(), "android");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002794 }
2795 }
2796
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002797 class InteractiveStateReceiver extends BroadcastReceiver {
2798 public InteractiveStateReceiver() {
2799 IntentFilter filter = new IntentFilter();
2800 filter.addAction(Intent.ACTION_SCREEN_OFF);
2801 filter.addAction(Intent.ACTION_SCREEN_ON);
2802 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
2803 getContext().registerReceiver(this, filter);
2804 }
2805
2806 @Override
2807 public void onReceive(Context context, Intent intent) {
2808 synchronized (mLock) {
2809 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
2810 }
2811 }
2812 }
2813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002814 class UninstallReceiver extends BroadcastReceiver {
2815 public UninstallReceiver() {
2816 IntentFilter filter = new IntentFilter();
2817 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
2818 filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08002819 filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 filter.addDataScheme("package");
Adam Lesinski182f73f2013-12-05 16:48:06 -08002821 getContext().registerReceiver(this, filter);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002822 // Register for events related to sdcard installation.
2823 IntentFilter sdFilter = new IntentFilter();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08002824 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07002825 sdFilter.addAction(Intent.ACTION_USER_STOPPED);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002826 sdFilter.addAction(Intent.ACTION_UID_REMOVED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002827 getContext().registerReceiver(this, sdFilter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828 }
2829
2830 @Override
2831 public void onReceive(Context context, Intent intent) {
2832 synchronized (mLock) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002833 String action = intent.getAction();
2834 String pkgList[] = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08002835 if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
2836 pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
2837 for (String packageName : pkgList) {
2838 if (lookForPackageLocked(packageName)) {
2839 setResultCode(Activity.RESULT_OK);
2840 return;
2841 }
2842 }
2843 return;
2844 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002845 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07002846 } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
2847 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
2848 if (userHandle >= 0) {
2849 removeUserLocked(userHandle);
2850 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002851 } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
2852 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
2853 if (uid >= 0) {
2854 mLastAllowWhileIdleDispatch.delete(uid);
2855 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002856 } else {
Dianne Hackborn409578f2010-03-10 17:23:43 -08002857 if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
2858 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
2859 // This package is being updated; don't kill its alarms.
2860 return;
2861 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002862 Uri data = intent.getData();
2863 if (data != null) {
2864 String pkg = data.getSchemeSpecificPart();
2865 if (pkg != null) {
2866 pkgList = new String[]{pkg};
2867 }
2868 }
2869 }
2870 if (pkgList != null && (pkgList.length > 0)) {
2871 for (String pkg : pkgList) {
2872 removeLocked(pkg);
Christopher Tate1590f1e2014-10-02 17:27:57 -07002873 mPriorities.remove(pkg);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002874 for (int i=mBroadcastStats.size()-1; i>=0; i--) {
2875 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
2876 if (uidStats.remove(pkg) != null) {
2877 if (uidStats.size() <= 0) {
2878 mBroadcastStats.removeAt(i);
2879 }
2880 }
2881 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 }
2884 }
2885 }
2886 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002887
2888 final class UidObserver extends IUidObserver.Stub {
Sudheer Shanka80255802017-03-04 14:48:53 -08002889 @Override public void onUidStateChanged(int uid, int procState,
2890 long procStateSeq) throws RemoteException {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002891 }
2892
Dianne Hackborne07641d2016-11-09 15:07:23 -08002893 @Override public void onUidGone(int uid, boolean disabled) throws RemoteException {
2894 if (disabled) {
2895 synchronized (mLock) {
2896 removeForStoppedLocked(uid);
2897 }
2898 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002899 }
2900
2901 @Override public void onUidActive(int uid) throws RemoteException {
2902 }
2903
Dianne Hackborne07641d2016-11-09 15:07:23 -08002904 @Override public void onUidIdle(int uid, boolean disabled) throws RemoteException {
2905 if (disabled) {
2906 synchronized (mLock) {
2907 removeForStoppedLocked(uid);
2908 }
Dianne Hackbornde9c48b2015-11-20 14:49:59 -08002909 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002910 }
2911 };
2912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002913 private final BroadcastStats getStatsLocked(PendingIntent pi) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002914 String pkg = pi.getCreatorPackage();
2915 int uid = pi.getCreatorUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07002916 return getStatsLocked(uid, pkg);
2917 }
2918
2919 private final BroadcastStats getStatsLocked(int uid, String pkgName) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002920 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
2921 if (uidStats == null) {
2922 uidStats = new ArrayMap<String, BroadcastStats>();
2923 mBroadcastStats.put(uid, uidStats);
2924 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002925 BroadcastStats bs = uidStats.get(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002926 if (bs == null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002927 bs = new BroadcastStats(uid, pkgName);
2928 uidStats.put(pkgName, bs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 }
2930 return bs;
2931 }
Dianne Hackborn81038902012-11-26 17:04:09 -08002932
Christopher Tate14a7bb02015-10-01 10:24:31 -07002933 class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished {
2934 private InFlight removeLocked(PendingIntent pi, Intent intent) {
2935 for (int i = 0; i < mInFlight.size(); i++) {
2936 if (mInFlight.get(i).mPendingIntent == pi) {
2937 return mInFlight.remove(i);
2938 }
2939 }
2940 mLog.w("No in-flight alarm for " + pi + " " + intent);
2941 return null;
2942 }
2943
2944 private InFlight removeLocked(IBinder listener) {
2945 for (int i = 0; i < mInFlight.size(); i++) {
2946 if (mInFlight.get(i).mListener == listener) {
2947 return mInFlight.remove(i);
2948 }
2949 }
2950 mLog.w("No in-flight alarm for listener " + listener);
2951 return null;
2952 }
2953
2954 private void updateStatsLocked(InFlight inflight) {
2955 final long nowELAPSED = SystemClock.elapsedRealtime();
2956 BroadcastStats bs = inflight.mBroadcastStats;
2957 bs.nesting--;
2958 if (bs.nesting <= 0) {
2959 bs.nesting = 0;
2960 bs.aggregateTime += nowELAPSED - bs.startTime;
2961 }
2962 FilterStats fs = inflight.mFilterStats;
2963 fs.nesting--;
2964 if (fs.nesting <= 0) {
2965 fs.nesting = 0;
2966 fs.aggregateTime += nowELAPSED - fs.startTime;
2967 }
2968 if (RECORD_ALARMS_IN_HISTORY) {
2969 if (inflight.mWorkSource != null && inflight.mWorkSource.size() > 0) {
2970 for (int wi=0; wi<inflight.mWorkSource.size(); wi++) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002971 ActivityManager.noteAlarmFinish(
Christopher Tate14a7bb02015-10-01 10:24:31 -07002972 inflight.mPendingIntent, inflight.mWorkSource.get(wi), inflight.mTag);
2973 }
2974 } else {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002975 ActivityManager.noteAlarmFinish(
Christopher Tate14a7bb02015-10-01 10:24:31 -07002976 inflight.mPendingIntent, inflight.mUid, inflight.mTag);
2977 }
2978 }
2979 }
2980
2981 private void updateTrackingLocked(InFlight inflight) {
2982 if (inflight != null) {
2983 updateStatsLocked(inflight);
2984 }
2985 mBroadcastRefCount--;
Makoto Onuki3e7d8452017-03-02 15:33:17 -08002986 if (DEBUG_WAKELOCK) {
2987 Slog.d(TAG, "mBroadcastRefCount -> " + mBroadcastRefCount);
2988 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002989 if (mBroadcastRefCount == 0) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08002990 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07002991 mWakeLock.release();
2992 if (mInFlight.size() > 0) {
2993 mLog.w("Finished all dispatches with " + mInFlight.size()
2994 + " remaining inflights");
2995 for (int i=0; i<mInFlight.size(); i++) {
2996 mLog.w(" Remaining #" + i + ": " + mInFlight.get(i));
2997 }
2998 mInFlight.clear();
2999 }
3000 } else {
3001 // the next of our alarms is now in flight. reattribute the wakelock.
3002 if (mInFlight.size() > 0) {
3003 InFlight inFlight = mInFlight.get(0);
3004 setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
3005 inFlight.mAlarmType, inFlight.mTag, -1, false);
3006 } else {
3007 // should never happen
3008 mLog.w("Alarm wakelock still held but sent queue empty");
3009 mWakeLock.setWorkSource(null);
3010 }
3011 }
3012 }
3013
3014 /**
3015 * Callback that arrives when a direct-call alarm reports that delivery has finished
3016 */
3017 @Override
3018 public void alarmComplete(IBinder who) {
3019 if (who == null) {
3020 Slog.w(TAG, "Invalid alarmComplete: uid=" + Binder.getCallingUid()
3021 + " pid=" + Binder.getCallingPid());
3022 return;
3023 }
3024
3025 final long ident = Binder.clearCallingIdentity();
3026 try {
3027 synchronized (mLock) {
3028 mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who);
3029 InFlight inflight = removeLocked(who);
3030 if (inflight != null) {
3031 if (DEBUG_LISTENER_CALLBACK) {
3032 Slog.i(TAG, "alarmComplete() from " + who);
3033 }
3034 updateTrackingLocked(inflight);
3035 } else {
3036 // Delivery timed out, and the timeout handling already took care of
3037 // updating our tracking here, so we needn't do anything further.
3038 if (DEBUG_LISTENER_CALLBACK) {
3039 Slog.i(TAG, "Late alarmComplete() from " + who);
3040 }
3041 }
3042 }
3043 } finally {
3044 Binder.restoreCallingIdentity(ident);
3045 }
3046 }
3047
3048 /**
3049 * Callback that arrives when a PendingIntent alarm has finished delivery
3050 */
3051 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
3053 String resultData, Bundle resultExtras) {
3054 synchronized (mLock) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003055 updateTrackingLocked(removeLocked(pi, intent));
3056 }
3057 }
3058
3059 /**
3060 * Timeout of a direct-call alarm delivery
3061 */
3062 public void alarmTimedOut(IBinder who) {
3063 synchronized (mLock) {
3064 InFlight inflight = removeLocked(who);
Dianne Hackborn81038902012-11-26 17:04:09 -08003065 if (inflight != null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003066 // TODO: implement ANR policy for the target
3067 if (DEBUG_LISTENER_CALLBACK) {
3068 Slog.i(TAG, "Alarm listener " + who + " timed out in delivery");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003070 updateTrackingLocked(inflight);
Dianne Hackborn81038902012-11-26 17:04:09 -08003071 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003072 if (DEBUG_LISTENER_CALLBACK) {
3073 Slog.i(TAG, "Spurious timeout of listener " + who);
3074 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003076 }
3077 }
3078
3079 /**
3080 * Deliver an alarm and set up the post-delivery handling appropriately
3081 */
3082 public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
3083 if (alarm.operation != null) {
3084 // PendingIntent alarm
3085 try {
3086 alarm.operation.send(getContext(), 0,
3087 mBackgroundIntent.putExtra(
3088 Intent.EXTRA_ALARM_COUNT, alarm.count),
3089 mDeliveryTracker, mHandler, null,
3090 allowWhileIdle ? mIdleOptions : null);
3091 } catch (PendingIntent.CanceledException e) {
3092 if (alarm.repeatInterval > 0) {
3093 // This IntentSender is no longer valid, but this
3094 // is a repeating alarm, so toss it
3095 removeImpl(alarm.operation);
3096 }
Christopher Tate7f2a0352015-12-08 10:24:33 -08003097 // No actual delivery was possible, so the delivery tracker's
3098 // 'finished' callback won't be invoked. We also don't need
3099 // to do any wakelock or stats tracking, so we have nothing
3100 // left to do here but go on to the next thing.
3101 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003102 }
3103 } else {
3104 // Direct listener callback alarm
3105 try {
3106 if (DEBUG_LISTENER_CALLBACK) {
3107 Slog.v(TAG, "Alarm to uid=" + alarm.uid
3108 + " listener=" + alarm.listener.asBinder());
3109 }
3110 alarm.listener.doAlarm(this);
3111 mHandler.sendMessageDelayed(
3112 mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
3113 alarm.listener.asBinder()),
3114 mConstants.LISTENER_TIMEOUT);
3115 } catch (Exception e) {
3116 if (DEBUG_LISTENER_CALLBACK) {
3117 Slog.i(TAG, "Alarm undeliverable to listener "
3118 + alarm.listener.asBinder(), e);
3119 }
Christopher Tate7f2a0352015-12-08 10:24:33 -08003120 // As in the PendingIntent.CanceledException case, delivery of the
3121 // alarm was not possible, so we have no wakelock or timeout or
3122 // stats management to do. It threw before we posted the delayed
3123 // timeout message, so we're done here.
3124 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003125 }
3126 }
3127
3128 // The alarm is now in flight; now arrange wakelock and stats tracking
Makoto Onuki3e7d8452017-03-02 15:33:17 -08003129 if (DEBUG_WAKELOCK) {
3130 Slog.d(TAG, "mBroadcastRefCount -> " + (mBroadcastRefCount + 1));
3131 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003132 if (mBroadcastRefCount == 0) {
3133 setWakelockWorkSource(alarm.operation, alarm.workSource,
3134 alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1,
3135 true);
3136 mWakeLock.acquire();
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003137 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07003138 }
3139 final InFlight inflight = new InFlight(AlarmManagerService.this,
3140 alarm.operation, alarm.listener, alarm.workSource, alarm.uid,
3141 alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
3142 mInFlight.add(inflight);
3143 mBroadcastRefCount++;
3144
3145 if (allowWhileIdle) {
3146 // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
3147 mLastAllowWhileIdleDispatch.put(alarm.uid, nowELAPSED);
3148 if (RECORD_DEVICE_IDLE_ALARMS) {
3149 IdleDispatchEntry ent = new IdleDispatchEntry();
3150 ent.uid = alarm.uid;
3151 ent.pkg = alarm.packageName;
3152 ent.tag = alarm.statsTag;
3153 ent.op = "DELIVER";
3154 ent.elapsedRealtime = nowELAPSED;
3155 mAllowWhileIdleDispatches.add(ent);
3156 }
3157 }
3158
3159 final BroadcastStats bs = inflight.mBroadcastStats;
3160 bs.count++;
3161 if (bs.nesting == 0) {
3162 bs.nesting = 1;
3163 bs.startTime = nowELAPSED;
3164 } else {
3165 bs.nesting++;
3166 }
3167 final FilterStats fs = inflight.mFilterStats;
3168 fs.count++;
3169 if (fs.nesting == 0) {
3170 fs.nesting = 1;
3171 fs.startTime = nowELAPSED;
3172 } else {
3173 fs.nesting++;
3174 }
3175 if (alarm.type == ELAPSED_REALTIME_WAKEUP
3176 || alarm.type == RTC_WAKEUP) {
3177 bs.numWakeup++;
3178 fs.numWakeup++;
3179 if (alarm.workSource != null && alarm.workSource.size() > 0) {
3180 for (int wi=0; wi<alarm.workSource.size(); wi++) {
Christopher Tate0029f572016-06-14 10:16:28 -07003181 final String wsName = alarm.workSource.getName(wi);
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003182 ActivityManager.noteWakeupAlarm(
Christopher Tate14a7bb02015-10-01 10:24:31 -07003183 alarm.operation, alarm.workSource.get(wi),
Christopher Tate0029f572016-06-14 10:16:28 -07003184 (wsName != null) ? wsName : alarm.packageName,
3185 alarm.statsTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08003186 }
Christopher Tatec4a07d12012-04-06 14:19:13 -07003187 } else {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003188 ActivityManager.noteWakeupAlarm(
Joe Onorato78bcdf92016-05-09 10:10:29 -07003189 alarm.operation, alarm.uid, alarm.packageName, alarm.statsTag);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003190 }
3191 }
3192 }
3193 }
3194}