blob: cab6ecf3931e355b2bebe895f75c8e89f702a58d [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.content.pm.PackageManager;
Christopher Tatebb9cce52017-04-18 14:19:43 -070036import android.content.pm.PackageManager.NameNotFoundException;
37import android.content.pm.PermissionInfo;
Dianne Hackborna750a632015-06-16 17:18:23 -070038import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.net.Uri;
40import android.os.Binder;
41import android.os.Bundle;
Christopher Tate247571462017-04-10 11:45:05 -070042import android.os.Environment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.os.Handler;
Adam Lesinski182f73f2013-12-05 16:48:06 -080044import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.os.Message;
46import android.os.PowerManager;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -070047import android.os.Process;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070048import android.os.RemoteException;
Suprabh Shukladb6bf662017-08-30 15:41:53 -070049import android.os.ServiceManager;
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;
Suprabh Shukladb6bf662017-08-30 15:41:53 -070058import android.util.ArraySet;
Dianne Hackborna750a632015-06-16 17:18:23 -070059import android.util.KeyValueListParser;
Adrian Roosc42a1e12014-07-07 23:35:53 +020060import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080061import android.util.Slog;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080062import android.util.SparseArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +020063import android.util.SparseBooleanArray;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -070064import android.util.SparseLongArray;
Dianne Hackborn043fcd92010-10-06 14:27:34 -070065import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066
Christopher Tate4cb338d2013-07-26 13:11:31 -070067import java.io.ByteArrayOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import java.io.FileDescriptor;
69import java.io.PrintWriter;
Dianne Hackborn043fcd92010-10-06 14:27:34 -070070import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import java.util.ArrayList;
Dianne Hackborn81038902012-11-26 17:04:09 -080072import java.util.Arrays;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import java.util.Calendar;
74import java.util.Collections;
75import java.util.Comparator;
Mike Lockwood1f7b4132009-11-20 15:12:51 -050076import java.util.Date;
Christopher Tate1590f1e2014-10-02 17:27:57 -070077import java.util.HashMap;
Christopher Tate18a75f12013-07-01 18:18:59 -070078import java.util.LinkedList;
Adrian Roosc42a1e12014-07-07 23:35:53 +020079import java.util.Locale;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -070080import java.util.Random;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import java.util.TimeZone;
John Spurlock604a5ee2015-06-01 12:27:22 -040082import java.util.TreeSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083
Christopher Tatee0a22b32013-07-11 14:43:13 -070084import static android.app.AlarmManager.RTC_WAKEUP;
85import static android.app.AlarmManager.RTC;
86import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
87import static android.app.AlarmManager.ELAPSED_REALTIME;
88
Christopher Tate21e9f192017-08-08 13:49:11 -070089import com.android.internal.annotations.GuardedBy;
Suprabh Shukladb6bf662017-08-30 15:41:53 -070090import com.android.internal.app.IAppOpsCallback;
91import com.android.internal.app.IAppOpsService;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060092import com.android.internal.util.DumpUtils;
Dianne Hackborn81038902012-11-26 17:04:09 -080093import com.android.internal.util.LocalLog;
94
Adam Lesinski182f73f2013-12-05 16:48:06 -080095class AlarmManagerService extends SystemService {
Christopher Tatee0a22b32013-07-11 14:43:13 -070096 private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
97 private static final int RTC_MASK = 1 << RTC;
Adam Lesinski182f73f2013-12-05 16:48:06 -080098 private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -070099 private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800100 static final int TIME_CHANGED_MASK = 1 << 16;
101 static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
Christopher Tateb8849c12011-02-08 13:39:01 -0800102
Christopher Tatee0a22b32013-07-11 14:43:13 -0700103 // Mask for testing whether a given alarm type is wakeup vs non-wakeup
Adam Lesinski182f73f2013-12-05 16:48:06 -0800104 static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
Christopher Tateb8849c12011-02-08 13:39:01 -0800105
Adam Lesinski182f73f2013-12-05 16:48:06 -0800106 static final String TAG = "AlarmManager";
Adam Lesinski182f73f2013-12-05 16:48:06 -0800107 static final boolean localLOGV = false;
108 static final boolean DEBUG_BATCH = localLOGV || false;
109 static final boolean DEBUG_VALIDATE = localLOGV || false;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200110 static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700111 static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
Makoto Onuki3e7d8452017-03-02 15:33:17 -0800112 static final boolean DEBUG_WAKELOCK = localLOGV || false;
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700113 static final boolean DEBUG_BG_LIMIT = localLOGV || false;
Dianne Hackborn1e383822015-04-10 14:02:33 -0700114 static final boolean RECORD_ALARMS_IN_HISTORY = true;
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700115 static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800116 static final int ALARM_EVENT = 1;
117 static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
Adrian Roosc42a1e12014-07-07 23:35:53 +0200118
Christopher Tate14a7bb02015-10-01 10:24:31 -0700119 private final Intent mBackgroundIntent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800121 static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700122
Adam Lesinski182f73f2013-12-05 16:48:06 -0800123 static final boolean WAKEUP_STATS = false;
Christopher Tate18a75f12013-07-01 18:18:59 -0700124
Christopher Tate24cd46f2016-02-02 14:28:01 -0800125 private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT =
126 new Intent(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)
Christopher Tate50191db2017-05-09 16:02:25 -0700127 .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
128 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Adrian Roosc42a1e12014-07-07 23:35:53 +0200129
Adam Lesinski182f73f2013-12-05 16:48:06 -0800130 final LocalLog mLog = new LocalLog(TAG);
Dianne Hackborn81038902012-11-26 17:04:09 -0800131
Christopher Tate14a7bb02015-10-01 10:24:31 -0700132 AppOpsManager mAppOps;
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700133 IAppOpsService mAppOpsService;
Dianne Hackborn627dfa12015-11-11 18:10:30 -0800134 DeviceIdleController.LocalService mLocalDeviceIdleController;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700135
Adam Lesinski182f73f2013-12-05 16:48:06 -0800136 final Object mLock = new Object();
Dianne Hackborn81038902012-11-26 17:04:09 -0800137
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700138 ArraySet<String> mForcedAppStandbyPackages = new ArraySet<>();
139 SparseBooleanArray mForegroundUids = new SparseBooleanArray();
140 // List of alarms per uid deferred due to user applied background restrictions on the source app
141 SparseArray<ArrayList<Alarm>> mPendingBackgroundAlarms = new SparseArray<>();
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -0800142 long mNativeData;
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800143 private long mNextWakeup;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700144 private long mNextNonWakeup;
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -0700145 private long mLastWakeupSet;
146 private long mLastWakeup;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800147 int mBroadcastRefCount = 0;
148 PowerManager.WakeLock mWakeLock;
Dianne Hackborna1bd7922014-03-21 11:07:11 -0700149 boolean mLastWakeLockUnimportantForLogging;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700150 ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
151 ArrayList<InFlight> mInFlight = new ArrayList<>();
Adam Lesinski182f73f2013-12-05 16:48:06 -0800152 final AlarmHandler mHandler = new AlarmHandler();
153 ClockReceiver mClockReceiver;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700154 InteractiveStateReceiver mInteractiveStateReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 private UninstallReceiver mUninstallReceiver;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700156 final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
Adam Lesinski182f73f2013-12-05 16:48:06 -0800157 PendingIntent mTimeTickSender;
158 PendingIntent mDateChangeSender;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700159 Random mRandom;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700160 boolean mInteractive = true;
161 long mNonInteractiveStartTime;
162 long mNonInteractiveTime;
163 long mLastAlarmDeliveryTime;
164 long mStartCurrentDelayTime;
165 long mNextNonWakeupDeliveryTime;
Dianne Hackbornc3527222015-05-13 14:03:20 -0700166 long mLastTimeChangeClockTime;
167 long mLastTimeChangeRealtime;
Dianne Hackborna750a632015-06-16 17:18:23 -0700168 long mAllowWhileIdleMinTime;
Dianne Hackborn998e6082014-09-11 19:13:23 -0700169 int mNumTimeChanged;
Dianne Hackborn81038902012-11-26 17:04:09 -0800170
Christopher Tatebb9cce52017-04-18 14:19:43 -0700171 // Bookkeeping about the identity of the "System UI" package, determined at runtime.
172
173 /**
174 * This permission must be defined by the canonical System UI package,
175 * with protection level "signature".
176 */
177 private static final String SYSTEM_UI_SELF_PERMISSION =
178 "android.permission.systemui.IDENTITY";
179
180 /**
181 * At boot we use SYSTEM_UI_SELF_PERMISSION to look up the definer's uid.
182 */
183 int mSystemUiUid;
184
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700185 /**
Dianne Hackborn262ae5c2016-02-10 16:28:29 -0800186 * The current set of user whitelisted apps for device idle mode, meaning these are allowed
187 * to freely schedule alarms.
188 */
189 int[] mDeviceIdleUserWhitelist = new int[0];
190
191 /**
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700192 * For each uid, this is the last time we dispatched an "allow while idle" alarm,
193 * used to determine the earliest we can dispatch the next such alarm.
194 */
195 final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
196
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700197 final static class IdleDispatchEntry {
198 int uid;
199 String pkg;
200 String tag;
201 String op;
202 long elapsedRealtime;
203 long argRealtime;
204 }
205 final ArrayList<IdleDispatchEntry> mAllowWhileIdleDispatches = new ArrayList();
206
Dianne Hackborna750a632015-06-16 17:18:23 -0700207 /**
208 * Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
209 */
210 Bundle mIdleOptions;
211
Jose Lima235510e2014-08-13 12:50:01 -0700212 private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
213 new SparseArray<>();
214 private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
215 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200216 private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
217 new SparseBooleanArray();
218 private boolean mNextAlarmClockMayChange;
219
220 // May only use on mHandler's thread, locking not required.
Jose Lima235510e2014-08-13 12:50:01 -0700221 private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
222 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200223
Dianne Hackborna750a632015-06-16 17:18:23 -0700224 /**
225 * All times are in milliseconds. These constants are kept synchronized with the system
226 * global Settings. Any access to this class or its fields should be done while
227 * holding the AlarmManagerService.mLock lock.
228 */
229 private final class Constants extends ContentObserver {
230 // Key names stored in the settings value.
231 private static final String KEY_MIN_FUTURITY = "min_futurity";
232 private static final String KEY_MIN_INTERVAL = "min_interval";
233 private static final String KEY_ALLOW_WHILE_IDLE_SHORT_TIME = "allow_while_idle_short_time";
234 private static final String KEY_ALLOW_WHILE_IDLE_LONG_TIME = "allow_while_idle_long_time";
235 private static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
236 = "allow_while_idle_whitelist_duration";
Christopher Tate14a7bb02015-10-01 10:24:31 -0700237 private static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700238 private static final String KEY_BG_RESTRICTIONS_ENABLED = "limit_bg_alarms_enabled";
Dianne Hackborna750a632015-06-16 17:18:23 -0700239
240 private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
241 private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
Christopher Tateaa244da2015-08-27 15:57:57 -0700242 private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
Dianne Hackborn7682b262015-10-26 17:51:57 -0700243 private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000;
Dianne Hackborna750a632015-06-16 17:18:23 -0700244 private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
245
Christopher Tate14a7bb02015-10-01 10:24:31 -0700246 private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
247
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700248 private static final boolean DEFAULT_BACKGROUND_RESTRICTIONS_ENABLED = false;
249
Dianne Hackborna750a632015-06-16 17:18:23 -0700250 // Minimum futurity of a new alarm
251 public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
252
253 // Minimum alarm recurrence interval
254 public long MIN_INTERVAL = DEFAULT_MIN_INTERVAL;
255
256 // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
257 public long ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME;
258
259 // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
260 public long ALLOW_WHILE_IDLE_LONG_TIME = DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME;
261
262 // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
263 public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
264 = DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
265
Christopher Tate14a7bb02015-10-01 10:24:31 -0700266 // Direct alarm listener callback timeout
267 public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
268
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700269 public boolean BACKGROUND_ALARMS_BLOCKED = DEFAULT_BACKGROUND_RESTRICTIONS_ENABLED;
270
Dianne Hackborna750a632015-06-16 17:18:23 -0700271 private ContentResolver mResolver;
272 private final KeyValueListParser mParser = new KeyValueListParser(',');
273 private long mLastAllowWhileIdleWhitelistDuration = -1;
274
275 public Constants(Handler handler) {
276 super(handler);
277 updateAllowWhileIdleMinTimeLocked();
278 updateAllowWhileIdleWhitelistDurationLocked();
279 }
280
281 public void start(ContentResolver resolver) {
282 mResolver = resolver;
283 mResolver.registerContentObserver(Settings.Global.getUriFor(
284 Settings.Global.ALARM_MANAGER_CONSTANTS), false, this);
285 updateConstants();
286 }
287
288 public void updateAllowWhileIdleMinTimeLocked() {
289 mAllowWhileIdleMinTime = mPendingIdleUntil != null
290 ? ALLOW_WHILE_IDLE_LONG_TIME : ALLOW_WHILE_IDLE_SHORT_TIME;
291 }
292
293 public void updateAllowWhileIdleWhitelistDurationLocked() {
294 if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
295 mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
296 BroadcastOptions opts = BroadcastOptions.makeBasic();
297 opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
298 mIdleOptions = opts.toBundle();
299 }
300 }
301
302 @Override
303 public void onChange(boolean selfChange, Uri uri) {
304 updateConstants();
305 }
306
307 private void updateConstants() {
308 synchronized (mLock) {
309 try {
310 mParser.setString(Settings.Global.getString(mResolver,
311 Settings.Global.ALARM_MANAGER_CONSTANTS));
312 } catch (IllegalArgumentException e) {
313 // Failed to parse the settings string, log this and move on
314 // with defaults.
Dianne Hackborn0ef403e2017-01-24 18:22:15 -0800315 Slog.e(TAG, "Bad alarm manager settings", e);
Dianne Hackborna750a632015-06-16 17:18:23 -0700316 }
317
318 MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
319 MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
320 ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
321 DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
322 ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME,
323 DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
324 ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong(
325 KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
326 DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700327 LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
328 DEFAULT_LISTENER_TIMEOUT);
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700329 BACKGROUND_ALARMS_BLOCKED = mParser.getBoolean(KEY_BG_RESTRICTIONS_ENABLED,
330 DEFAULT_BACKGROUND_RESTRICTIONS_ENABLED);
331 if (!BACKGROUND_ALARMS_BLOCKED) {
332 // TODO: remove this code and constant when feature is turned on
333 // deliver all blocked alarms
334 final ArrayList<Alarm> allBlockedAlarms = new ArrayList<>();
335 for (int i = mPendingBackgroundAlarms.size() - 1; i >=0; i--) {
336 allBlockedAlarms.addAll(mPendingBackgroundAlarms.valueAt(i));
337 }
338 mPendingBackgroundAlarms = new SparseArray<>();
339 deliverPendingBackgroundAlarmsLocked(allBlockedAlarms,
340 SystemClock.elapsedRealtime());
341 } else if (DEBUG_BG_LIMIT) {
342 Slog.d(TAG, "Background limiting enabled");
343 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700344
345 updateAllowWhileIdleMinTimeLocked();
346 updateAllowWhileIdleWhitelistDurationLocked();
347 }
348 }
349
350 void dump(PrintWriter pw) {
351 pw.println(" Settings:");
352
353 pw.print(" "); pw.print(KEY_MIN_FUTURITY); pw.print("=");
354 TimeUtils.formatDuration(MIN_FUTURITY, pw);
355 pw.println();
356
357 pw.print(" "); pw.print(KEY_MIN_INTERVAL); pw.print("=");
358 TimeUtils.formatDuration(MIN_INTERVAL, pw);
359 pw.println();
360
Christopher Tate14a7bb02015-10-01 10:24:31 -0700361 pw.print(" "); pw.print(KEY_LISTENER_TIMEOUT); pw.print("=");
362 TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
363 pw.println();
364
Dianne Hackborna750a632015-06-16 17:18:23 -0700365 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME); pw.print("=");
366 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw);
367 pw.println();
368
369 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME); pw.print("=");
370 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw);
371 pw.println();
372
373 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); pw.print("=");
374 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
375 pw.println();
376 }
377 }
378
379 final Constants mConstants;
380
Christopher Tate1590f1e2014-10-02 17:27:57 -0700381 // Alarm delivery ordering bookkeeping
382 static final int PRIO_TICK = 0;
383 static final int PRIO_WAKEUP = 1;
384 static final int PRIO_NORMAL = 2;
385
Dianne Hackborna750a632015-06-16 17:18:23 -0700386 final class PriorityClass {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700387 int seq;
388 int priority;
389
390 PriorityClass() {
391 seq = mCurrentSeq - 1;
392 priority = PRIO_NORMAL;
393 }
394 }
395
Dianne Hackborna750a632015-06-16 17:18:23 -0700396 final HashMap<String, PriorityClass> mPriorities = new HashMap<>();
Christopher Tate1590f1e2014-10-02 17:27:57 -0700397 int mCurrentSeq = 0;
398
Dianne Hackborna750a632015-06-16 17:18:23 -0700399 static final class WakeupEvent {
Christopher Tate18a75f12013-07-01 18:18:59 -0700400 public long when;
401 public int uid;
402 public String action;
403
404 public WakeupEvent(long theTime, int theUid, String theAction) {
405 when = theTime;
406 uid = theUid;
407 action = theAction;
408 }
409 }
410
Adam Lesinski182f73f2013-12-05 16:48:06 -0800411 final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
412 final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
Christopher Tate18a75f12013-07-01 18:18:59 -0700413
Adrian Roosc42a1e12014-07-07 23:35:53 +0200414 final class Batch {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700415 long start; // These endpoints are always in ELAPSED
416 long end;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700417 int flags; // Flags for alarms, such as FLAG_STANDALONE.
Christopher Tatee0a22b32013-07-11 14:43:13 -0700418
419 final ArrayList<Alarm> alarms = new ArrayList<Alarm>();
420
421 Batch() {
422 start = 0;
423 end = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700424 flags = 0;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700425 }
426
427 Batch(Alarm seed) {
428 start = seed.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700429 end = seed.maxWhenElapsed;
430 flags = seed.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700431 alarms.add(seed);
432 }
433
434 int size() {
435 return alarms.size();
436 }
437
438 Alarm get(int index) {
439 return alarms.get(index);
440 }
441
442 boolean canHold(long whenElapsed, long maxWhen) {
443 return (end >= whenElapsed) && (start <= maxWhen);
444 }
445
446 boolean add(Alarm alarm) {
447 boolean newStart = false;
448 // narrows the batch if necessary; presumes that canHold(alarm) is true
449 int index = Collections.binarySearch(alarms, alarm, sIncreasingTimeOrder);
450 if (index < 0) {
451 index = 0 - index - 1;
452 }
453 alarms.add(index, alarm);
454 if (DEBUG_BATCH) {
455 Slog.v(TAG, "Adding " + alarm + " to " + this);
456 }
457 if (alarm.whenElapsed > start) {
458 start = alarm.whenElapsed;
459 newStart = true;
460 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700461 if (alarm.maxWhenElapsed < end) {
462 end = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700463 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700464 flags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700465
466 if (DEBUG_BATCH) {
467 Slog.v(TAG, " => now " + this);
468 }
469 return newStart;
470 }
471
Christopher Tate14a7bb02015-10-01 10:24:31 -0700472 boolean remove(final PendingIntent operation, final IAlarmListener listener) {
473 if (operation == null && listener == null) {
474 if (localLOGV) {
475 Slog.w(TAG, "requested remove() of null operation",
476 new RuntimeException("here"));
477 }
478 return false;
479 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700480 boolean didRemove = false;
481 long newStart = 0; // recalculate endpoints as we go
482 long newEnd = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700483 int newFlags = 0;
Christopher Tateae269d52013-09-26 13:11:55 -0700484 for (int i = 0; i < alarms.size(); ) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700485 Alarm alarm = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700486 if (alarm.matches(operation, listener)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700487 alarms.remove(i);
488 didRemove = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200489 if (alarm.alarmClock != null) {
490 mNextAlarmClockMayChange = true;
491 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700492 } else {
493 if (alarm.whenElapsed > newStart) {
494 newStart = alarm.whenElapsed;
495 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700496 if (alarm.maxWhenElapsed < newEnd) {
497 newEnd = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700498 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700499 newFlags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700500 i++;
501 }
502 }
503 if (didRemove) {
504 // commit the new batch bounds
505 start = newStart;
506 end = newEnd;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700507 flags = newFlags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700508 }
509 return didRemove;
510 }
511
512 boolean remove(final String packageName) {
Christopher Tate14a7bb02015-10-01 10:24:31 -0700513 if (packageName == null) {
514 if (localLOGV) {
515 Slog.w(TAG, "requested remove() of null packageName",
516 new RuntimeException("here"));
517 }
518 return false;
519 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700520 boolean didRemove = false;
521 long newStart = 0; // recalculate endpoints as we go
522 long newEnd = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700523 int newFlags = 0;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700524 for (int i = alarms.size()-1; i >= 0; i--) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700525 Alarm alarm = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700526 if (alarm.matches(packageName)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700527 alarms.remove(i);
528 didRemove = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200529 if (alarm.alarmClock != null) {
530 mNextAlarmClockMayChange = true;
531 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700532 } else {
533 if (alarm.whenElapsed > newStart) {
534 newStart = alarm.whenElapsed;
535 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700536 if (alarm.maxWhenElapsed < newEnd) {
537 newEnd = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700538 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700539 newFlags |= alarm.flags;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700540 }
541 }
542 if (didRemove) {
543 // commit the new batch bounds
544 start = newStart;
545 end = newEnd;
546 flags = newFlags;
547 }
548 return didRemove;
549 }
550
551 boolean removeForStopped(final int uid) {
552 boolean didRemove = false;
553 long newStart = 0; // recalculate endpoints as we go
554 long newEnd = Long.MAX_VALUE;
555 int newFlags = 0;
556 for (int i = alarms.size()-1; i >= 0; i--) {
557 Alarm alarm = alarms.get(i);
558 try {
Dianne Hackbornc3af19a2017-01-20 17:00:44 -0800559 if (alarm.uid == uid && ActivityManager.getService().isAppStartModeDisabled(
560 uid, alarm.packageName)) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700561 alarms.remove(i);
562 didRemove = true;
563 if (alarm.alarmClock != null) {
564 mNextAlarmClockMayChange = true;
565 }
566 } else {
567 if (alarm.whenElapsed > newStart) {
568 newStart = alarm.whenElapsed;
569 }
570 if (alarm.maxWhenElapsed < newEnd) {
571 newEnd = alarm.maxWhenElapsed;
572 }
573 newFlags |= alarm.flags;
574 }
575 } catch (RemoteException e) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700576 }
577 }
578 if (didRemove) {
579 // commit the new batch bounds
580 start = newStart;
581 end = newEnd;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700582 flags = newFlags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700583 }
584 return didRemove;
585 }
586
587 boolean remove(final int userHandle) {
588 boolean didRemove = false;
589 long newStart = 0; // recalculate endpoints as we go
590 long newEnd = Long.MAX_VALUE;
Christopher Tateae269d52013-09-26 13:11:55 -0700591 for (int i = 0; i < alarms.size(); ) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700592 Alarm alarm = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700593 if (UserHandle.getUserId(alarm.creatorUid) == userHandle) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700594 alarms.remove(i);
595 didRemove = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200596 if (alarm.alarmClock != null) {
597 mNextAlarmClockMayChange = true;
598 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700599 } else {
600 if (alarm.whenElapsed > newStart) {
601 newStart = alarm.whenElapsed;
602 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700603 if (alarm.maxWhenElapsed < newEnd) {
604 newEnd = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700605 }
606 i++;
607 }
608 }
609 if (didRemove) {
610 // commit the new batch bounds
611 start = newStart;
612 end = newEnd;
613 }
614 return didRemove;
615 }
616
617 boolean hasPackage(final String packageName) {
618 final int N = alarms.size();
619 for (int i = 0; i < N; i++) {
620 Alarm a = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700621 if (a.matches(packageName)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700622 return true;
623 }
624 }
625 return false;
626 }
627
628 boolean hasWakeups() {
629 final int N = alarms.size();
630 for (int i = 0; i < N; i++) {
631 Alarm a = alarms.get(i);
632 // non-wakeup alarms are types 1 and 3, i.e. have the low bit set
633 if ((a.type & TYPE_NONWAKEUP_MASK) == 0) {
634 return true;
635 }
636 }
637 return false;
638 }
639
640 @Override
641 public String toString() {
642 StringBuilder b = new StringBuilder(40);
643 b.append("Batch{"); b.append(Integer.toHexString(this.hashCode()));
644 b.append(" num="); b.append(size());
645 b.append(" start="); b.append(start);
646 b.append(" end="); b.append(end);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700647 if (flags != 0) {
648 b.append(" flgs=0x");
649 b.append(Integer.toHexString(flags));
Christopher Tatee0a22b32013-07-11 14:43:13 -0700650 }
651 b.append('}');
652 return b.toString();
653 }
654 }
655
656 static class BatchTimeOrder implements Comparator<Batch> {
657 public int compare(Batch b1, Batch b2) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800658 long when1 = b1.start;
659 long when2 = b2.start;
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800660 if (when1 > when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700661 return 1;
662 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800663 if (when1 < when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700664 return -1;
665 }
666 return 0;
667 }
668 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800669
670 final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
671 @Override
672 public int compare(Alarm lhs, Alarm rhs) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700673 // priority class trumps everything. TICK < WAKEUP < NORMAL
674 if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
675 return -1;
676 } else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
677 return 1;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800678 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700679
680 // within each class, sort by nominal delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800681 if (lhs.whenElapsed < rhs.whenElapsed) {
682 return -1;
683 } else if (lhs.whenElapsed > rhs.whenElapsed) {
684 return 1;
685 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700686
687 // same priority class + same target delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800688 return 0;
689 }
690 };
691
Christopher Tate1590f1e2014-10-02 17:27:57 -0700692 void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
693 final int N = alarms.size();
694 for (int i = 0; i < N; i++) {
695 Alarm a = alarms.get(i);
696
697 final int alarmPrio;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700698 if (a.operation != null
699 && Intent.ACTION_TIME_TICK.equals(a.operation.getIntent().getAction())) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700700 alarmPrio = PRIO_TICK;
701 } else if (a.wakeup) {
702 alarmPrio = PRIO_WAKEUP;
703 } else {
704 alarmPrio = PRIO_NORMAL;
705 }
706
707 PriorityClass packagePrio = a.priorityClass;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700708 String alarmPackage = (a.operation != null)
709 ? a.operation.getCreatorPackage()
710 : a.packageName;
711 if (packagePrio == null) packagePrio = mPriorities.get(alarmPackage);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700712 if (packagePrio == null) {
713 packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
Christopher Tate14a7bb02015-10-01 10:24:31 -0700714 mPriorities.put(alarmPackage, packagePrio);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700715 }
716 a.priorityClass = packagePrio;
717
718 if (packagePrio.seq != mCurrentSeq) {
719 // first alarm we've seen in the current delivery generation from this package
720 packagePrio.priority = alarmPrio;
721 packagePrio.seq = mCurrentSeq;
722 } else {
723 // Multiple alarms from this package being delivered in this generation;
724 // bump the package's delivery class if it's warranted.
725 // TICK < WAKEUP < NORMAL
726 if (alarmPrio < packagePrio.priority) {
727 packagePrio.priority = alarmPrio;
728 }
729 }
730 }
731 }
732
Christopher Tatee0a22b32013-07-11 14:43:13 -0700733 // minimum recurrence period or alarm futurity for us to be able to fuzz it
Adam Lesinski182f73f2013-12-05 16:48:06 -0800734 static final long MIN_FUZZABLE_INTERVAL = 10000;
735 static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700736 final ArrayList<Batch> mAlarmBatches = new ArrayList<>();
737
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700738 // set to non-null if in idle mode; while in this mode, any alarms we don't want
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700739 // to run during this time are placed in mPendingWhileIdleAlarms
740 Alarm mPendingIdleUntil = null;
Dianne Hackbornf70faed2015-04-21 14:11:38 -0700741 Alarm mNextWakeFromIdle = null;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700742 ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
Christopher Tatee0a22b32013-07-11 14:43:13 -0700743
Jeff Brownb880d882014-02-10 19:47:07 -0800744 public AlarmManagerService(Context context) {
745 super(context);
Dianne Hackborna750a632015-06-16 17:18:23 -0700746 mConstants = new Constants(mHandler);
Jeff Brownb880d882014-02-10 19:47:07 -0800747 }
748
Christopher Tatee0a22b32013-07-11 14:43:13 -0700749 static long convertToElapsed(long when, int type) {
750 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
751 if (isRtc) {
752 when -= System.currentTimeMillis() - SystemClock.elapsedRealtime();
753 }
754 return when;
755 }
756
757 // Apply a heuristic to { recurrence interval, futurity of the trigger time } to
758 // calculate the end of our nominal delivery window for the alarm.
759 static long maxTriggerTime(long now, long triggerAtTime, long interval) {
760 // Current heuristic: batchable window is 75% of either the recurrence interval
761 // [for a periodic alarm] or of the time from now to the desired delivery time,
762 // with a minimum delay/interval of 10 seconds, under which we will simply not
763 // defer the alarm.
764 long futurity = (interval == 0)
765 ? (triggerAtTime - now)
766 : interval;
Christopher Tate57ceaaa2013-07-19 16:30:43 -0700767 if (futurity < MIN_FUZZABLE_INTERVAL) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700768 futurity = 0;
769 }
770 return triggerAtTime + (long)(.75 * futurity);
771 }
772
773 // returns true if the batch was added at the head
774 static boolean addBatchLocked(ArrayList<Batch> list, Batch newBatch) {
775 int index = Collections.binarySearch(list, newBatch, sBatchOrder);
776 if (index < 0) {
777 index = 0 - index - 1;
778 }
779 list.add(index, newBatch);
780 return (index == 0);
781 }
782
Christopher Tate385e4982013-07-23 18:22:29 -0700783 // Return the index of the matching batch, or -1 if none found.
784 int attemptCoalesceLocked(long whenElapsed, long maxWhen) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700785 final int N = mAlarmBatches.size();
786 for (int i = 0; i < N; i++) {
787 Batch b = mAlarmBatches.get(i);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700788 if ((b.flags&AlarmManager.FLAG_STANDALONE) == 0 && b.canHold(whenElapsed, maxWhen)) {
Christopher Tate385e4982013-07-23 18:22:29 -0700789 return i;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700790 }
791 }
Christopher Tate385e4982013-07-23 18:22:29 -0700792 return -1;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700793 }
794
795 // The RTC clock has moved arbitrarily, so we need to recalculate all the batching
796 void rebatchAllAlarms() {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700797 synchronized (mLock) {
Christopher Tate4cb338d2013-07-26 13:11:31 -0700798 rebatchAllAlarmsLocked(true);
799 }
800 }
801
802 void rebatchAllAlarmsLocked(boolean doValidate) {
803 ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone();
804 mAlarmBatches.clear();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700805 Alarm oldPendingIdleUntil = mPendingIdleUntil;
Christopher Tate4cb338d2013-07-26 13:11:31 -0700806 final long nowElapsed = SystemClock.elapsedRealtime();
807 final int oldBatches = oldSet.size();
808 for (int batchNum = 0; batchNum < oldBatches; batchNum++) {
809 Batch batch = oldSet.get(batchNum);
810 final int N = batch.size();
811 for (int i = 0; i < N; i++) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700812 reAddAlarmLocked(batch.get(i), nowElapsed, doValidate);
Christopher Tatee0a22b32013-07-11 14:43:13 -0700813 }
814 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700815 if (oldPendingIdleUntil != null && oldPendingIdleUntil != mPendingIdleUntil) {
816 Slog.wtf(TAG, "Rebatching: idle until changed from " + oldPendingIdleUntil
817 + " to " + mPendingIdleUntil);
818 if (mPendingIdleUntil == null) {
819 // Somehow we lost this... we need to restore all of the pending alarms.
820 restorePendingWhileIdleAlarmsLocked();
821 }
822 }
823 rescheduleKernelAlarmsLocked();
824 updateNextAlarmClockLocked();
825 }
826
827 void reAddAlarmLocked(Alarm a, long nowElapsed, boolean doValidate) {
828 a.when = a.origWhen;
829 long whenElapsed = convertToElapsed(a.when, a.type);
830 final long maxElapsed;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700831 if (a.windowLength == AlarmManager.WINDOW_EXACT) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700832 // Exact
833 maxElapsed = whenElapsed;
834 } else {
835 // Not exact. Preserve any explicit window, otherwise recalculate
836 // the window based on the alarm's new futurity. Note that this
837 // reflects a policy of preferring timely to deferred delivery.
838 maxElapsed = (a.windowLength > 0)
839 ? (whenElapsed + a.windowLength)
840 : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
841 }
842 a.whenElapsed = whenElapsed;
843 a.maxWhenElapsed = maxElapsed;
844 setImplLocked(a, true, doValidate);
845 }
846
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700847 /**
848 * Sends alarms that were blocked due to user applied background restrictions - either because
849 * the user lifted those or the uid came to foreground.
850 *
851 * @param uid uid to filter on
852 * @param packageName package to filter on, or null for all packages in uid
853 */
854 void sendPendingBackgroundAlarmsLocked(int uid, String packageName) {
855 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(uid);
856 if (alarmsForUid == null || alarmsForUid.size() == 0) {
857 return;
858 }
859 final ArrayList<Alarm> alarmsToDeliver;
860 if (packageName != null) {
861 if (DEBUG_BG_LIMIT) {
862 Slog.d(TAG, "Sending blocked alarms for uid " + uid + ", package " + packageName);
863 }
864 alarmsToDeliver = new ArrayList<>();
865 for (int i = alarmsForUid.size() - 1; i >= 0; i--) {
866 final Alarm a = alarmsForUid.get(i);
867 if (a.matches(packageName)) {
868 alarmsToDeliver.add(alarmsForUid.remove(i));
869 }
870 }
871 if (alarmsForUid.size() == 0) {
872 mPendingBackgroundAlarms.remove(uid);
873 }
874 } else {
875 if (DEBUG_BG_LIMIT) {
876 Slog.d(TAG, "Sending blocked alarms for uid " + uid);
877 }
878 alarmsToDeliver = alarmsForUid;
879 mPendingBackgroundAlarms.remove(uid);
880 }
881 deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, SystemClock.elapsedRealtime());
882 }
883
884 void sendPendingBackgroundAlarmsForAppIdLocked(int appId) {
885 final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
886 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
887 final int uid = mPendingBackgroundAlarms.keyAt(i);
888 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
889 if (UserHandle.getAppId(uid) == appId) {
890 alarmsToDeliver.addAll(alarmsForUid);
891 mPendingBackgroundAlarms.removeAt(i);
892 }
893 }
894 deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, SystemClock.elapsedRealtime());
895 }
896
897 private void deliverPendingBackgroundAlarmsLocked(ArrayList<Alarm> alarms, long nowELAPSED) {
898 final int N = alarms.size();
899 boolean hasWakeup = false;
900 for (int i = 0; i < N; i++) {
901 final Alarm alarm = alarms.get(i);
902 if (alarm.wakeup) {
903 hasWakeup = true;
904 }
905 alarm.count = 1;
906 // Recurring alarms may have passed several alarm intervals while the
907 // alarm was kept pending. Send the appropriate trigger count.
908 if (alarm.repeatInterval > 0) {
909 alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval;
910 // Also schedule its next recurrence
911 final long delta = alarm.count * alarm.repeatInterval;
912 final long nextElapsed = alarm.whenElapsed + delta;
913 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
914 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
915 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
916 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
917 // Kernel alarms will be rescheduled as needed in setImplLocked
918 }
919 }
920 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
921 // No need to wakeup for non wakeup alarms
922 if (mPendingNonWakeupAlarms.size() == 0) {
923 mStartCurrentDelayTime = nowELAPSED;
924 mNextNonWakeupDeliveryTime = nowELAPSED
925 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
926 }
927 mPendingNonWakeupAlarms.addAll(alarms);
928 mNumDelayedAlarms += alarms.size();
929 } else {
930 if (DEBUG_BG_LIMIT) {
931 Slog.d(TAG, "Waking up to deliver pending blocked alarms");
932 }
933 // Since we are waking up, also deliver any pending non wakeup alarms we have.
934 if (mPendingNonWakeupAlarms.size() > 0) {
935 alarms.addAll(mPendingNonWakeupAlarms);
936 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
937 mTotalDelayTime += thisDelayTime;
938 if (mMaxDelayTime < thisDelayTime) {
939 mMaxDelayTime = thisDelayTime;
940 }
941 mPendingNonWakeupAlarms.clear();
942 }
943 calculateDeliveryPriorities(alarms);
944 Collections.sort(alarms, mAlarmDispatchComparator);
945 deliverAlarmsLocked(alarms, nowELAPSED);
946 }
947 }
948
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700949 void restorePendingWhileIdleAlarmsLocked() {
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700950 if (RECORD_DEVICE_IDLE_ALARMS) {
951 IdleDispatchEntry ent = new IdleDispatchEntry();
952 ent.uid = 0;
953 ent.pkg = "FINISH IDLE";
954 ent.elapsedRealtime = SystemClock.elapsedRealtime();
955 mAllowWhileIdleDispatches.add(ent);
956 }
957
Dianne Hackborn35d54032015-04-23 10:30:43 -0700958 // Bring pending alarms back into the main list.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700959 if (mPendingWhileIdleAlarms.size() > 0) {
960 ArrayList<Alarm> alarms = mPendingWhileIdleAlarms;
961 mPendingWhileIdleAlarms = new ArrayList<>();
962 final long nowElapsed = SystemClock.elapsedRealtime();
963 for (int i=alarms.size() - 1; i >= 0; i--) {
964 Alarm a = alarms.get(i);
965 reAddAlarmLocked(a, nowElapsed, false);
966 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700967 }
Dianne Hackborn35d54032015-04-23 10:30:43 -0700968
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700969 // Make sure we are using the correct ALLOW_WHILE_IDLE min time.
Dianne Hackborna750a632015-06-16 17:18:23 -0700970 mConstants.updateAllowWhileIdleMinTimeLocked();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700971
Dianne Hackborn35d54032015-04-23 10:30:43 -0700972 // Reschedule everything.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700973 rescheduleKernelAlarmsLocked();
974 updateNextAlarmClockLocked();
Dianne Hackborn35d54032015-04-23 10:30:43 -0700975
976 // And send a TIME_TICK right now, since it is important to get the UI updated.
977 try {
978 mTimeTickSender.send();
979 } catch (PendingIntent.CanceledException e) {
980 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700981 }
982
Christopher Tate14a7bb02015-10-01 10:24:31 -0700983 static final class InFlight {
Dianne Hackborn81038902012-11-26 17:04:09 -0800984 final PendingIntent mPendingIntent;
Christopher Tateeabba732017-08-17 17:12:52 -0700985 final long mWhenElapsed;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700986 final IBinder mListener;
David Christieebe51fc2013-07-26 13:23:29 -0700987 final WorkSource mWorkSource;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700988 final int mUid;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700989 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -0800990 final BroadcastStats mBroadcastStats;
991 final FilterStats mFilterStats;
Dianne Hackborne5167ca2014-03-08 14:39:10 -0800992 final int mAlarmType;
Dianne Hackborn81038902012-11-26 17:04:09 -0800993
Christopher Tate14a7bb02015-10-01 10:24:31 -0700994 InFlight(AlarmManagerService service, PendingIntent pendingIntent, IAlarmListener listener,
995 WorkSource workSource, int uid, String alarmPkg, int alarmType, String tag,
996 long nowELAPSED) {
Dianne Hackborn81038902012-11-26 17:04:09 -0800997 mPendingIntent = pendingIntent;
Christopher Tateeabba732017-08-17 17:12:52 -0700998 mWhenElapsed = nowELAPSED;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700999 mListener = listener != null ? listener.asBinder() : null;
David Christieebe51fc2013-07-26 13:23:29 -07001000 mWorkSource = workSource;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001001 mUid = uid;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001002 mTag = tag;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001003 mBroadcastStats = (pendingIntent != null)
1004 ? service.getStatsLocked(pendingIntent)
1005 : service.getStatsLocked(uid, alarmPkg);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001006 FilterStats fs = mBroadcastStats.filterStats.get(mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08001007 if (fs == null) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001008 fs = new FilterStats(mBroadcastStats, mTag);
1009 mBroadcastStats.filterStats.put(mTag, fs);
Dianne Hackborn81038902012-11-26 17:04:09 -08001010 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001011 fs.lastTime = nowELAPSED;
Dianne Hackborn81038902012-11-26 17:04:09 -08001012 mFilterStats = fs;
Dianne Hackborne5167ca2014-03-08 14:39:10 -08001013 mAlarmType = alarmType;
Dianne Hackborn81038902012-11-26 17:04:09 -08001014 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001015
1016 @Override
1017 public String toString() {
1018 return "InFlight{"
1019 + "pendingIntent=" + mPendingIntent
Christopher Tateeabba732017-08-17 17:12:52 -07001020 + ", when=" + mWhenElapsed
Makoto Onuki33955e12017-03-01 18:11:00 -08001021 + ", workSource=" + mWorkSource
1022 + ", uid=" + mUid
1023 + ", tag=" + mTag
1024 + ", broadcastStats=" + mBroadcastStats
1025 + ", filterStats=" + mFilterStats
1026 + ", alarmType=" + mAlarmType
1027 + "}";
1028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001030
Adam Lesinski182f73f2013-12-05 16:48:06 -08001031 static final class FilterStats {
Dianne Hackborn81038902012-11-26 17:04:09 -08001032 final BroadcastStats mBroadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001033 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001034
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001035 long lastTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001036 long aggregateTime;
Dianne Hackborn81038902012-11-26 17:04:09 -08001037 int count;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 int numWakeup;
1039 long startTime;
1040 int nesting;
Dianne Hackborn81038902012-11-26 17:04:09 -08001041
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001042 FilterStats(BroadcastStats broadcastStats, String tag) {
Dianne Hackborn81038902012-11-26 17:04:09 -08001043 mBroadcastStats = broadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001044 mTag = tag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001045 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001046
1047 @Override
1048 public String toString() {
1049 return "FilterStats{"
1050 + "tag=" + mTag
1051 + ", lastTime=" + lastTime
1052 + ", aggregateTime=" + aggregateTime
1053 + ", count=" + count
1054 + ", numWakeup=" + numWakeup
1055 + ", startTime=" + startTime
1056 + ", nesting=" + nesting
1057 + "}";
1058 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001059 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001060
Adam Lesinski182f73f2013-12-05 16:48:06 -08001061 static final class BroadcastStats {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001062 final int mUid;
Dianne Hackborn81038902012-11-26 17:04:09 -08001063 final String mPackageName;
1064
1065 long aggregateTime;
1066 int count;
1067 int numWakeup;
1068 long startTime;
1069 int nesting;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001070 final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
Dianne Hackborn81038902012-11-26 17:04:09 -08001071
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001072 BroadcastStats(int uid, String packageName) {
1073 mUid = uid;
Dianne Hackborn81038902012-11-26 17:04:09 -08001074 mPackageName = packageName;
1075 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001076
1077 @Override
1078 public String toString() {
1079 return "BroadcastStats{"
1080 + "uid=" + mUid
1081 + ", packageName=" + mPackageName
1082 + ", aggregateTime=" + aggregateTime
1083 + ", count=" + count
1084 + ", numWakeup=" + numWakeup
1085 + ", startTime=" + startTime
1086 + ", nesting=" + nesting
1087 + "}";
1088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001090
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001091 final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
1092 = new SparseArray<ArrayMap<String, BroadcastStats>>();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001093
1094 int mNumDelayedAlarms = 0;
1095 long mTotalDelayTime = 0;
1096 long mMaxDelayTime = 0;
1097
Adam Lesinski182f73f2013-12-05 16:48:06 -08001098 @Override
1099 public void onStart() {
Greg Hackmanna1d6f922013-12-09 16:56:53 -08001100 mNativeData = init();
Christopher Tate0dab4dc2014-12-16 12:14:06 -08001101 mNextWakeup = mNextNonWakeup = 0;
Robert CH Chou64ba8e42009-11-04 21:38:49 +08001102
1103 // We have to set current TimeZone info to kernel
1104 // because kernel doesn't keep this after reboot
Adam Lesinski182f73f2013-12-05 16:48:06 -08001105 setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
Robert CH Chou64ba8e42009-11-04 21:38:49 +08001106
Christopher Tate247571462017-04-10 11:45:05 -07001107 // Also sure that we're booting with a halfway sensible current time
1108 if (mNativeData != 0) {
1109 final long systemBuildTime = Environment.getRootDirectory().lastModified();
1110 if (System.currentTimeMillis() < systemBuildTime) {
1111 Slog.i(TAG, "Current time only " + System.currentTimeMillis()
1112 + ", advancing to build time " + systemBuildTime);
1113 setKernelTime(mNativeData, systemBuildTime);
1114 }
1115 }
1116
Christopher Tatebb9cce52017-04-18 14:19:43 -07001117 // Determine SysUI's uid
1118 final PackageManager packMan = getContext().getPackageManager();
1119 try {
1120 PermissionInfo sysUiPerm = packMan.getPermissionInfo(SYSTEM_UI_SELF_PERMISSION, 0);
1121 ApplicationInfo sysUi = packMan.getApplicationInfo(sysUiPerm.packageName, 0);
1122 if ((sysUi.privateFlags&ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
1123 mSystemUiUid = sysUi.uid;
1124 } else {
1125 Slog.e(TAG, "SysUI permission " + SYSTEM_UI_SELF_PERMISSION
1126 + " defined by non-privileged app " + sysUi.packageName
1127 + " - ignoring");
1128 }
1129 } catch (NameNotFoundException e) {
1130 }
1131
1132 if (mSystemUiUid <= 0) {
1133 Slog.wtf(TAG, "SysUI package not found!");
1134 }
1135
Adam Lesinski182f73f2013-12-05 16:48:06 -08001136 PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001137 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
Dianne Hackborna1f1a3c2014-02-24 18:12:28 -08001138
Adam Lesinski182f73f2013-12-05 16:48:06 -08001139 mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 new Intent(Intent.ACTION_TIME_TICK).addFlags(
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07001141 Intent.FLAG_RECEIVER_REGISTERED_ONLY
Chad Brubaker291df4f2017-03-14 10:23:02 -07001142 | Intent.FLAG_RECEIVER_FOREGROUND
1143 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS), 0,
Dianne Hackborndb5aca92012-10-26 13:39:41 -07001144 UserHandle.ALL);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001145 Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
Chad Brubaker291df4f2017-03-14 10:23:02 -07001146 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
1147 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001148 mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
Dianne Hackborndb5aca92012-10-26 13:39:41 -07001149 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150
1151 // now that we have initied the driver schedule the alarm
Adam Lesinski182f73f2013-12-05 16:48:06 -08001152 mClockReceiver = new ClockReceiver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 mClockReceiver.scheduleTimeTickEvent();
1154 mClockReceiver.scheduleDateChangedEvent();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001155 mInteractiveStateReceiver = new InteractiveStateReceiver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 mUninstallReceiver = new UninstallReceiver();
1157
Greg Hackmanna1d6f922013-12-09 16:56:53 -08001158 if (mNativeData != 0) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001159 AlarmThread waitThread = new AlarmThread();
1160 waitThread.start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001162 Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001164
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001165 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001166 ActivityManager.getService().registerUidObserver(new UidObserver(),
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001167 ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
1168 | ActivityManager.UID_OBSERVER_ACTIVE,
1169 ActivityManager.PROCESS_STATE_UNKNOWN, null);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001170 } catch (RemoteException e) {
1171 // ignored; both services live in system_server
1172 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001173 mAppOpsService = IAppOpsService.Stub.asInterface(
1174 ServiceManager.getService(Context.APP_OPS_SERVICE));
Adam Lesinski182f73f2013-12-05 16:48:06 -08001175 publishBinderService(Context.ALARM_SERVICE, mService);
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001176 publishLocalService(LocalService.class, new LocalService());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001178
1179 @Override
Dianne Hackborna750a632015-06-16 17:18:23 -07001180 public void onBootPhase(int phase) {
1181 if (phase == PHASE_SYSTEM_SERVICES_READY) {
1182 mConstants.start(getContext().getContentResolver());
Christopher Tate14a7bb02015-10-01 10:24:31 -07001183 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001184 mLocalDeviceIdleController
1185 = LocalServices.getService(DeviceIdleController.LocalService.class);
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001186 try {
1187 mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, null,
1188 new AppOpsWatcher());
1189 } catch (RemoteException rexc) {
1190 // Shouldn't happen as they are in the same process.
1191 Slog.e(TAG, "AppOps service not reachable", rexc);
1192 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001193 }
1194 }
1195
1196 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 protected void finalize() throws Throwable {
1198 try {
Greg Hackmanna1d6f922013-12-09 16:56:53 -08001199 close(mNativeData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 } finally {
1201 super.finalize();
1202 }
1203 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001204
Adam Lesinski182f73f2013-12-05 16:48:06 -08001205 void setTimeZoneImpl(String tz) {
1206 if (TextUtils.isEmpty(tz)) {
1207 return;
David Christieebe51fc2013-07-26 13:23:29 -07001208 }
1209
Adam Lesinski182f73f2013-12-05 16:48:06 -08001210 TimeZone zone = TimeZone.getTimeZone(tz);
1211 // Prevent reentrant calls from stepping on each other when writing
1212 // the time zone property
1213 boolean timeZoneWasChanged = false;
1214 synchronized (this) {
1215 String current = SystemProperties.get(TIMEZONE_PROPERTY);
1216 if (current == null || !current.equals(zone.getID())) {
1217 if (localLOGV) {
1218 Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
1219 }
1220 timeZoneWasChanged = true;
1221 SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
1222 }
1223
1224 // Update the kernel timezone information
1225 // Kernel tracks time offsets as 'minutes west of GMT'
1226 int gmtOffset = zone.getOffset(System.currentTimeMillis());
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -08001227 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
Adam Lesinski182f73f2013-12-05 16:48:06 -08001228 }
1229
1230 TimeZone.setDefault(null);
1231
1232 if (timeZoneWasChanged) {
1233 Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
Chad Brubaker291df4f2017-03-14 10:23:02 -07001234 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
Christopher Tate5cdf9f82017-05-03 18:10:39 -07001235 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
Chad Brubaker291df4f2017-03-14 10:23:02 -07001236 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001237 intent.putExtra("time-zone", zone.getID());
1238 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
1239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001241
Adam Lesinski182f73f2013-12-05 16:48:06 -08001242 void removeImpl(PendingIntent operation) {
1243 if (operation == null) {
1244 return;
1245 }
1246 synchronized (mLock) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07001247 removeLocked(operation, null);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001248 }
1249 }
1250
1251 void setImpl(int type, long triggerAtTime, long windowLength, long interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001252 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1253 int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
1254 int callingUid, String callingPackage) {
1255 // must be *either* PendingIntent or AlarmReceiver, but not both
1256 if ((operation == null && directReceiver == null)
1257 || (operation != null && directReceiver != null)) {
1258 Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver");
1259 // NB: previous releases failed silently here, so we are continuing to do the same
1260 // rather than throw an IllegalArgumentException.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261 return;
1262 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001263
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001264 // Sanity check the window length. This will catch people mistakenly
1265 // trying to pass an end-of-window timestamp rather than a duration.
1266 if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
1267 Slog.w(TAG, "Window length " + windowLength
1268 + "ms suspiciously long; limiting to 1 hour");
1269 windowLength = AlarmManager.INTERVAL_HOUR;
1270 }
1271
Christopher Tate498c6cb2014-11-17 16:09:27 -08001272 // Sanity check the recurrence interval. This will catch people who supply
1273 // seconds when the API expects milliseconds.
Dianne Hackborna750a632015-06-16 17:18:23 -07001274 final long minInterval = mConstants.MIN_INTERVAL;
1275 if (interval > 0 && interval < minInterval) {
Christopher Tate498c6cb2014-11-17 16:09:27 -08001276 Slog.w(TAG, "Suspiciously short interval " + interval
Dianne Hackborna750a632015-06-16 17:18:23 -07001277 + " millis; expanding to " + (minInterval/1000)
Christopher Tate498c6cb2014-11-17 16:09:27 -08001278 + " seconds");
Dianne Hackborna750a632015-06-16 17:18:23 -07001279 interval = minInterval;
Christopher Tate498c6cb2014-11-17 16:09:27 -08001280 }
1281
Christopher Tatee0a22b32013-07-11 14:43:13 -07001282 if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
1283 throw new IllegalArgumentException("Invalid alarm type " + type);
1284 }
1285
Christopher Tate5f221e82013-07-30 17:13:15 -07001286 if (triggerAtTime < 0) {
Christopher Tate5f221e82013-07-30 17:13:15 -07001287 final long what = Binder.getCallingPid();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001288 Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
Christopher Tate5f221e82013-07-30 17:13:15 -07001289 + " pid=" + what);
1290 triggerAtTime = 0;
1291 }
1292
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001293 final long nowElapsed = SystemClock.elapsedRealtime();
Christopher Tate498c6cb2014-11-17 16:09:27 -08001294 final long nominalTrigger = convertToElapsed(triggerAtTime, type);
1295 // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
Dianne Hackborna750a632015-06-16 17:18:23 -07001296 final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
Christopher Tate498c6cb2014-11-17 16:09:27 -08001297 final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
1298
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001299 final long maxElapsed;
1300 if (windowLength == AlarmManager.WINDOW_EXACT) {
1301 maxElapsed = triggerElapsed;
1302 } else if (windowLength < 0) {
1303 maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001304 // Fix this window in place, so that as time approaches we don't collapse it.
1305 windowLength = maxElapsed - triggerElapsed;
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001306 } else {
1307 maxElapsed = triggerElapsed + windowLength;
1308 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001310 synchronized (mLock) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07001311 if (DEBUG_BATCH) {
1312 Slog.v(TAG, "set(" + operation + ") : type=" + type
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001313 + " triggerAtTime=" + triggerAtTime + " win=" + windowLength
Christopher Tatee0a22b32013-07-11 14:43:13 -07001314 + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001315 + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316 }
Christopher Tate3e04b472013-10-21 17:51:31 -07001317 setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001318 interval, operation, directReceiver, listenerTag, flags, true, workSource,
1319 alarmClock, callingUid, callingPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320 }
1321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001322
Christopher Tate3e04b472013-10-21 17:51:31 -07001323 private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001324 long maxWhen, long interval, PendingIntent operation, IAlarmListener directReceiver,
1325 String listenerTag, int flags, boolean doValidate, WorkSource workSource,
1326 AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) {
Christopher Tate3e04b472013-10-21 17:51:31 -07001327 Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001328 operation, directReceiver, listenerTag, workSource, flags, alarmClock,
1329 callingUid, callingPackage);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001330 try {
Dianne Hackbornc3af19a2017-01-20 17:00:44 -08001331 if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001332 Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
1333 + " -- package not allowed to start");
1334 return;
1335 }
1336 } catch (RemoteException e) {
1337 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07001338 removeLocked(operation, directReceiver);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001339 setImplLocked(a, false, doValidate);
1340 }
Christopher Tateb8849c12011-02-08 13:39:01 -08001341
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001342 private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
1343 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001344 // This is a special alarm that will put the system into idle until it goes off.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001345 // The caller has given the time they want this to happen at, however we need
1346 // to pull that earlier if there are existing alarms that have requested to
Dianne Hackbornf3831292015-10-15 14:51:06 -07001347 // bring us out of idle at an earlier time.
1348 if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001349 a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001350 }
1351 // Add fuzz to make the alarm go off some time before the actual desired time.
1352 final long nowElapsed = SystemClock.elapsedRealtime();
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001353 final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001354 if (fuzz > 0) {
1355 if (mRandom == null) {
1356 mRandom = new Random();
1357 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001358 final int delta = mRandom.nextInt(fuzz);
1359 a.whenElapsed -= delta;
1360 if (false) {
1361 Slog.d(TAG, "Alarm when: " + a.whenElapsed);
1362 Slog.d(TAG, "Delta until alarm: " + (a.whenElapsed-nowElapsed));
1363 Slog.d(TAG, "Applied fuzz: " + fuzz);
1364 Slog.d(TAG, "Final delta: " + delta);
1365 Slog.d(TAG, "Final when: " + a.whenElapsed);
1366 }
1367 a.when = a.maxWhenElapsed = a.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001368 }
1369
1370 } else if (mPendingIdleUntil != null) {
1371 // We currently have an idle until alarm scheduled; if the new alarm has
1372 // not explicitly stated it wants to run while idle, then put it on hold.
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001373 if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
1374 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
1375 | AlarmManager.FLAG_WAKE_FROM_IDLE))
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001376 == 0) {
1377 mPendingWhileIdleAlarms.add(a);
1378 return;
1379 }
1380 }
1381
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001382 if (RECORD_DEVICE_IDLE_ALARMS) {
1383 if ((a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
1384 IdleDispatchEntry ent = new IdleDispatchEntry();
1385 ent.uid = a.uid;
1386 ent.pkg = a.operation.getCreatorPackage();
1387 ent.tag = a.operation.getTag("");
1388 ent.op = "SET";
1389 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1390 ent.argRealtime = a.whenElapsed;
1391 mAllowWhileIdleDispatches.add(ent);
1392 }
1393 }
1394
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001395 int whichBatch = ((a.flags&AlarmManager.FLAG_STANDALONE) != 0)
1396 ? -1 : attemptCoalesceLocked(a.whenElapsed, a.maxWhenElapsed);
Christopher Tate385e4982013-07-23 18:22:29 -07001397 if (whichBatch < 0) {
1398 Batch batch = new Batch(a);
Christopher Tate7d57ed82013-10-25 20:18:03 -07001399 addBatchLocked(mAlarmBatches, batch);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 } else {
Christopher Tate385e4982013-07-23 18:22:29 -07001401 Batch batch = mAlarmBatches.get(whichBatch);
Christopher Tate7d57ed82013-10-25 20:18:03 -07001402 if (batch.add(a)) {
Christopher Tate385e4982013-07-23 18:22:29 -07001403 // The start time of this batch advanced, so batch ordering may
1404 // have just been broken. Move it to where it now belongs.
1405 mAlarmBatches.remove(whichBatch);
1406 addBatchLocked(mAlarmBatches, batch);
1407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 }
1409
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001410 if (a.alarmClock != null) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001411 mNextAlarmClockMayChange = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +02001412 }
1413
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001414 boolean needRebatch = false;
1415
1416 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001417 if (RECORD_DEVICE_IDLE_ALARMS) {
1418 if (mPendingIdleUntil == null) {
1419 IdleDispatchEntry ent = new IdleDispatchEntry();
1420 ent.uid = 0;
1421 ent.pkg = "START IDLE";
1422 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1423 mAllowWhileIdleDispatches.add(ent);
1424 }
1425 }
Makoto Onuki4274a6d2017-04-21 12:21:25 -07001426 if ((mPendingIdleUntil != a) && (mPendingIdleUntil != null)) {
1427 Slog.wtfStack(TAG, "setImplLocked: idle until changed from " + mPendingIdleUntil
1428 + " to " + a);
1429 }
1430
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001431 mPendingIdleUntil = a;
Dianne Hackborna750a632015-06-16 17:18:23 -07001432 mConstants.updateAllowWhileIdleMinTimeLocked();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001433 needRebatch = true;
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001434 } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
1435 if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
1436 mNextWakeFromIdle = a;
1437 // If this wake from idle is earlier than whatever was previously scheduled,
1438 // and we are currently idling, then we need to rebatch alarms in case the idle
1439 // until time needs to be updated.
1440 if (mPendingIdleUntil != null) {
1441 needRebatch = true;
1442 }
1443 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001444 }
1445
1446 if (!rebatching) {
1447 if (DEBUG_VALIDATE) {
1448 if (doValidate && !validateConsistencyLocked()) {
1449 Slog.v(TAG, "Tipping-point operation: type=" + a.type + " when=" + a.when
1450 + " when(hex)=" + Long.toHexString(a.when)
1451 + " whenElapsed=" + a.whenElapsed
1452 + " maxWhenElapsed=" + a.maxWhenElapsed
1453 + " interval=" + a.repeatInterval + " op=" + a.operation
1454 + " flags=0x" + Integer.toHexString(a.flags));
1455 rebatchAllAlarmsLocked(false);
1456 needRebatch = false;
1457 }
1458 }
1459
1460 if (needRebatch) {
Christopher Tate4cb338d2013-07-26 13:11:31 -07001461 rebatchAllAlarmsLocked(false);
Christopher Tate4cb338d2013-07-26 13:11:31 -07001462 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001463
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001464 rescheduleKernelAlarmsLocked();
1465 updateNextAlarmClockLocked();
1466 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001467 }
1468
Adam Lesinski182f73f2013-12-05 16:48:06 -08001469 private final IBinder mService = new IAlarmManager.Stub() {
1470 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07001471 public void set(String callingPackage,
1472 int type, long triggerAtTime, long windowLength, long interval, int flags,
1473 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1474 WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001475 final int callingUid = Binder.getCallingUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07001476
1477 // make sure the caller is not lying about which package should be blamed for
1478 // wakelock time spent in alarm delivery
1479 mAppOps.checkPackage(callingUid, callingPackage);
1480
1481 // Repeating alarms must use PendingIntent, not direct listener
1482 if (interval != 0) {
1483 if (directReceiver != null) {
1484 throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers");
1485 }
1486 }
1487
Adam Lesinski182f73f2013-12-05 16:48:06 -08001488 if (workSource != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001489 getContext().enforcePermission(
Adam Lesinski182f73f2013-12-05 16:48:06 -08001490 android.Manifest.permission.UPDATE_DEVICE_STATS,
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001491 Binder.getCallingPid(), callingUid, "AlarmManager.set");
Christopher Tate89779822012-08-31 14:40:03 -07001492 }
1493
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001494 // No incoming callers can request either WAKE_FROM_IDLE or
1495 // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
1496 flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
1497 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
1498
1499 // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
1500 // manager when to come out of idle mode, which is only for DeviceIdleController.
1501 if (callingUid != Process.SYSTEM_UID) {
1502 flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
1503 }
1504
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001505 // If this is an exact time alarm, then it can't be batched with other alarms.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001506 if (windowLength == AlarmManager.WINDOW_EXACT) {
1507 flags |= AlarmManager.FLAG_STANDALONE;
1508 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001509
1510 // If this alarm is for an alarm clock, then it must be standalone and we will
1511 // use it to wake early from idle if needed.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001512 if (alarmClock != null) {
1513 flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001514
1515 // If the caller is a core system component or on the user's whitelist, and not calling
1516 // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
1517 // This means we will allow these alarms to go off as normal even while idle, with no
1518 // timing restrictions.
1519 } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
Christopher Tatebb9cce52017-04-18 14:19:43 -07001520 || callingUid == mSystemUiUid
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001521 || Arrays.binarySearch(mDeviceIdleUserWhitelist,
1522 UserHandle.getAppId(callingUid)) >= 0)) {
1523 flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
1524 flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001525 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001526
Christopher Tate14a7bb02015-10-01 10:24:31 -07001527 setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
1528 listenerTag, flags, workSource, alarmClock, callingUid, callingPackage);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001529 }
Christopher Tate89779822012-08-31 14:40:03 -07001530
Adam Lesinski182f73f2013-12-05 16:48:06 -08001531 @Override
Greg Hackmann0cab8962014-02-21 16:35:52 -08001532 public boolean setTime(long millis) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001533 getContext().enforceCallingOrSelfPermission(
1534 "android.permission.SET_TIME",
1535 "setTime");
1536
Greg Hackmann0cab8962014-02-21 16:35:52 -08001537 if (mNativeData == 0) {
1538 Slog.w(TAG, "Not setting time since no alarm driver is available.");
1539 return false;
Christopher Tate89779822012-08-31 14:40:03 -07001540 }
Greg Hackmann0cab8962014-02-21 16:35:52 -08001541
1542 synchronized (mLock) {
1543 return setKernelTime(mNativeData, millis) == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001546
1547 @Override
1548 public void setTimeZone(String tz) {
1549 getContext().enforceCallingOrSelfPermission(
1550 "android.permission.SET_TIME_ZONE",
1551 "setTimeZone");
1552
1553 final long oldId = Binder.clearCallingIdentity();
1554 try {
1555 setTimeZoneImpl(tz);
1556 } finally {
1557 Binder.restoreCallingIdentity(oldId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 }
1559 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001560
Adam Lesinski182f73f2013-12-05 16:48:06 -08001561 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07001562 public void remove(PendingIntent operation, IAlarmListener listener) {
1563 if (operation == null && listener == null) {
1564 Slog.w(TAG, "remove() with no intent or listener");
1565 return;
1566 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001567
Christopher Tate14a7bb02015-10-01 10:24:31 -07001568 synchronized (mLock) {
1569 removeLocked(operation, listener);
1570 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001572
Adam Lesinski182f73f2013-12-05 16:48:06 -08001573 @Override
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001574 public long getNextWakeFromIdleTime() {
1575 return getNextWakeFromIdleTimeImpl();
1576 }
1577
1578 @Override
Jose Lima235510e2014-08-13 12:50:01 -07001579 public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001580 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1581 Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */,
1582 "getNextAlarmClock", null);
1583
1584 return getNextAlarmClockImpl(userId);
1585 }
1586
1587 @Override
Adam Lesinski182f73f2013-12-05 16:48:06 -08001588 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -06001589 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
Adam Lesinski182f73f2013-12-05 16:48:06 -08001590 dumpImpl(pw);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001591 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001592 };
Christopher Tate4cb338d2013-07-26 13:11:31 -07001593
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001594 public final class LocalService {
1595 public void setDeviceIdleUserWhitelist(int[] appids) {
1596 setDeviceIdleUserWhitelistImpl(appids);
1597 }
1598 }
1599
Adam Lesinski182f73f2013-12-05 16:48:06 -08001600 void dumpImpl(PrintWriter pw) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 synchronized (mLock) {
1602 pw.println("Current Alarm Manager state:");
Dianne Hackborna750a632015-06-16 17:18:23 -07001603 mConstants.dump(pw);
1604 pw.println();
1605
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001606 pw.print(" Foreground uids: [");
1607 for (int i = 0; i < mForegroundUids.size(); i++) {
1608 if (mForegroundUids.valueAt(i)) pw.print(mForegroundUids.keyAt(i) + " ");
1609 }
1610 pw.println("]");
1611 pw.println(" Forced app standby packages: " + mForcedAppStandbyPackages);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001612 final long nowRTC = System.currentTimeMillis();
1613 final long nowELAPSED = SystemClock.elapsedRealtime();
1614 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1615
Dianne Hackborna750a632015-06-16 17:18:23 -07001616 pw.print(" nowRTC="); pw.print(nowRTC);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001617 pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
Christopher Tate7f2a0352015-12-08 10:24:33 -08001618 pw.print(" nowELAPSED="); pw.print(nowELAPSED);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001619 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001620 pw.print(" mLastTimeChangeClockTime="); pw.print(mLastTimeChangeClockTime);
Dianne Hackbornc3527222015-05-13 14:03:20 -07001621 pw.print("="); pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
Dianne Hackborna750a632015-06-16 17:18:23 -07001622 pw.print(" mLastTimeChangeRealtime=");
Dianne Hackbornc3527222015-05-13 14:03:20 -07001623 TimeUtils.formatDuration(mLastTimeChangeRealtime, pw);
1624 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001625 if (!mInteractive) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001626 pw.print(" Time since non-interactive: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001627 TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
1628 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001629 pw.print(" Max wakeup delay: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001630 TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
1631 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001632 pw.print(" Time since last dispatch: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001633 TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
1634 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001635 pw.print(" Next non-wakeup delivery time: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001636 TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
1637 pw.println();
1638 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001639
1640 long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
1641 long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
Dianne Hackborna750a632015-06-16 17:18:23 -07001642 pw.print(" Next non-wakeup alarm: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001643 TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001644 pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
Dianne Hackborna750a632015-06-16 17:18:23 -07001645 pw.print(" Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001646 pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07001647 pw.print(" Last wakeup: "); TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw);
1648 pw.print(" set at "); TimeUtils.formatDuration(mLastWakeupSet, nowELAPSED, pw);
1649 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001650 pw.print(" Num time change events: "); pw.println(mNumTimeChanged);
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001651 pw.println(" mDeviceIdleUserWhitelist=" + Arrays.toString(mDeviceIdleUserWhitelist));
Christopher Tatee0a22b32013-07-11 14:43:13 -07001652
John Spurlock604a5ee2015-06-01 12:27:22 -04001653 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001654 pw.println(" Next alarm clock information: ");
John Spurlock604a5ee2015-06-01 12:27:22 -04001655 final TreeSet<Integer> users = new TreeSet<>();
1656 for (int i = 0; i < mNextAlarmClockForUser.size(); i++) {
1657 users.add(mNextAlarmClockForUser.keyAt(i));
1658 }
1659 for (int i = 0; i < mPendingSendNextAlarmClockChangedForUser.size(); i++) {
1660 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
1661 }
1662 for (int user : users) {
1663 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
1664 final long time = next != null ? next.getTriggerTime() : 0;
1665 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
Dianne Hackborna750a632015-06-16 17:18:23 -07001666 pw.print(" user:"); pw.print(user);
John Spurlock604a5ee2015-06-01 12:27:22 -04001667 pw.print(" pendingSend:"); pw.print(pendingSend);
1668 pw.print(" time:"); pw.print(time);
1669 if (time > 0) {
1670 pw.print(" = "); pw.print(sdf.format(new Date(time)));
1671 pw.print(" = "); TimeUtils.formatDuration(time, nowRTC, pw);
1672 }
1673 pw.println();
1674 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001675 if (mAlarmBatches.size() > 0) {
1676 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001677 pw.print(" Pending alarm batches: ");
Christopher Tatee0a22b32013-07-11 14:43:13 -07001678 pw.println(mAlarmBatches.size());
1679 for (Batch b : mAlarmBatches) {
1680 pw.print(b); pw.println(':');
Dianne Hackborna750a632015-06-16 17:18:23 -07001681 dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001684 pw.println();
1685 pw.println(" Pending user blocked background alarms: ");
1686 boolean blocked = false;
1687 for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
1688 final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
1689 if (blockedAlarms != null && blockedAlarms.size() > 0) {
1690 blocked = true;
1691 dumpAlarmList(pw, blockedAlarms, " ", nowELAPSED, nowRTC, sdf);
1692 }
1693 }
1694 if (!blocked) {
1695 pw.println(" none");
1696 }
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001697 if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001698 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001699 pw.println(" Idle mode state:");
1700 pw.print(" Idling until: ");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001701 if (mPendingIdleUntil != null) {
1702 pw.println(mPendingIdleUntil);
Dianne Hackbornf3831292015-10-15 14:51:06 -07001703 mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001704 } else {
1705 pw.println("null");
1706 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001707 pw.println(" Pending alarms:");
1708 dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001709 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001710 if (mNextWakeFromIdle != null) {
1711 pw.println();
1712 pw.print(" Next wake from idle: "); pw.println(mNextWakeFromIdle);
1713 mNextWakeFromIdle.dump(pw, " ", nowRTC, nowELAPSED, sdf);
1714 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001715
1716 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001717 pw.print(" Past-due non-wakeup alarms: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001718 if (mPendingNonWakeupAlarms.size() > 0) {
1719 pw.println(mPendingNonWakeupAlarms.size());
Dianne Hackborna750a632015-06-16 17:18:23 -07001720 dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001721 } else {
1722 pw.println("(none)");
1723 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001724 pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001725 pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
1726 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001727 pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001728 pw.print(", max non-interactive time: ");
1729 TimeUtils.formatDuration(mNonInteractiveTime, pw);
1730 pw.println();
1731
1732 pw.println();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001733 pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
Christopher Tateeabba732017-08-17 17:12:52 -07001734 pw.print(" PendingIntent send count: "); pw.println(mSendCount);
1735 pw.print(" PendingIntent finish count: "); pw.println(mSendFinishCount);
1736 pw.print(" Listener send count: "); pw.println(mListenerCount);
1737 pw.print(" Listener finish count: "); pw.println(mListenerFinishCount);
Dianne Hackborn81038902012-11-26 17:04:09 -08001738 pw.println();
1739
Christopher Tate7f2a0352015-12-08 10:24:33 -08001740 if (mInFlight.size() > 0) {
1741 pw.println("Outstanding deliveries:");
1742 for (int i = 0; i < mInFlight.size(); i++) {
1743 pw.print(" #"); pw.print(i); pw.print(": ");
1744 pw.println(mInFlight.get(i));
1745 }
1746 pw.println();
1747 }
1748
Dianne Hackborna750a632015-06-16 17:18:23 -07001749 pw.print(" mAllowWhileIdleMinTime=");
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001750 TimeUtils.formatDuration(mAllowWhileIdleMinTime, pw);
1751 pw.println();
1752 if (mLastAllowWhileIdleDispatch.size() > 0) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001753 pw.println(" Last allow while idle dispatch times:");
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001754 for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
1755 pw.print(" UID ");
1756 UserHandle.formatUid(pw, mLastAllowWhileIdleDispatch.keyAt(i));
1757 pw.print(": ");
1758 TimeUtils.formatDuration(mLastAllowWhileIdleDispatch.valueAt(i),
1759 nowELAPSED, pw);
1760 pw.println();
1761 }
1762 }
1763 pw.println();
1764
Dianne Hackborn81038902012-11-26 17:04:09 -08001765 if (mLog.dump(pw, " Recent problems", " ")) {
1766 pw.println();
1767 }
1768
1769 final FilterStats[] topFilters = new FilterStats[10];
1770 final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
1771 @Override
1772 public int compare(FilterStats lhs, FilterStats rhs) {
1773 if (lhs.aggregateTime < rhs.aggregateTime) {
1774 return 1;
1775 } else if (lhs.aggregateTime > rhs.aggregateTime) {
1776 return -1;
1777 }
1778 return 0;
1779 }
1780 };
1781 int len = 0;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001782 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
1783 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
1784 for (int ip=0; ip<uidStats.size(); ip++) {
1785 BroadcastStats bs = uidStats.valueAt(ip);
1786 for (int is=0; is<bs.filterStats.size(); is++) {
1787 FilterStats fs = bs.filterStats.valueAt(is);
1788 int pos = len > 0
1789 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
1790 if (pos < 0) {
1791 pos = -pos - 1;
Dianne Hackborn81038902012-11-26 17:04:09 -08001792 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001793 if (pos < topFilters.length) {
1794 int copylen = topFilters.length - pos - 1;
1795 if (copylen > 0) {
1796 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
1797 }
1798 topFilters[pos] = fs;
1799 if (len < topFilters.length) {
1800 len++;
1801 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001802 }
1803 }
1804 }
1805 }
1806 if (len > 0) {
1807 pw.println(" Top Alarms:");
1808 for (int i=0; i<len; i++) {
1809 FilterStats fs = topFilters[i];
1810 pw.print(" ");
1811 if (fs.nesting > 0) pw.print("*ACTIVE* ");
1812 TimeUtils.formatDuration(fs.aggregateTime, pw);
1813 pw.print(" running, "); pw.print(fs.numWakeup);
1814 pw.print(" wakeups, "); pw.print(fs.count);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001815 pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
1816 pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
Dianne Hackborn81038902012-11-26 17:04:09 -08001817 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001818 pw.print(" "); pw.print(fs.mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08001819 pw.println();
1820 }
1821 }
1822
1823 pw.println(" ");
1824 pw.println(" Alarm Stats:");
1825 final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001826 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
1827 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
1828 for (int ip=0; ip<uidStats.size(); ip++) {
1829 BroadcastStats bs = uidStats.valueAt(ip);
1830 pw.print(" ");
1831 if (bs.nesting > 0) pw.print("*ACTIVE* ");
1832 UserHandle.formatUid(pw, bs.mUid);
1833 pw.print(":");
1834 pw.print(bs.mPackageName);
1835 pw.print(" "); TimeUtils.formatDuration(bs.aggregateTime, pw);
1836 pw.print(" running, "); pw.print(bs.numWakeup);
1837 pw.println(" wakeups:");
1838 tmpFilters.clear();
1839 for (int is=0; is<bs.filterStats.size(); is++) {
1840 tmpFilters.add(bs.filterStats.valueAt(is));
1841 }
1842 Collections.sort(tmpFilters, comparator);
1843 for (int i=0; i<tmpFilters.size(); i++) {
1844 FilterStats fs = tmpFilters.get(i);
1845 pw.print(" ");
1846 if (fs.nesting > 0) pw.print("*ACTIVE* ");
1847 TimeUtils.formatDuration(fs.aggregateTime, pw);
1848 pw.print(" "); pw.print(fs.numWakeup);
1849 pw.print(" wakes " ); pw.print(fs.count);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001850 pw.print(" alarms, last ");
1851 TimeUtils.formatDuration(fs.lastTime, nowELAPSED, pw);
1852 pw.println(":");
1853 pw.print(" ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001854 pw.print(fs.mTag);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001855 pw.println();
1856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 }
1858 }
Christopher Tate18a75f12013-07-01 18:18:59 -07001859
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001860 if (RECORD_DEVICE_IDLE_ALARMS) {
1861 pw.println();
1862 pw.println(" Allow while idle dispatches:");
1863 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
1864 IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
1865 pw.print(" ");
1866 TimeUtils.formatDuration(ent.elapsedRealtime, nowELAPSED, pw);
1867 pw.print(": ");
1868 UserHandle.formatUid(pw, ent.uid);
1869 pw.print(":");
1870 pw.println(ent.pkg);
1871 if (ent.op != null) {
1872 pw.print(" ");
1873 pw.print(ent.op);
1874 pw.print(" / ");
1875 pw.print(ent.tag);
1876 if (ent.argRealtime != 0) {
1877 pw.print(" (");
1878 TimeUtils.formatDuration(ent.argRealtime, nowELAPSED, pw);
1879 pw.print(")");
1880 }
1881 pw.println();
1882 }
1883 }
1884 }
1885
Christopher Tate18a75f12013-07-01 18:18:59 -07001886 if (WAKEUP_STATS) {
1887 pw.println();
1888 pw.println(" Recent Wakeup History:");
Christopher Tate18a75f12013-07-01 18:18:59 -07001889 long last = -1;
1890 for (WakeupEvent event : mRecentWakeups) {
1891 pw.print(" "); pw.print(sdf.format(new Date(event.when)));
1892 pw.print('|');
1893 if (last < 0) {
1894 pw.print('0');
1895 } else {
1896 pw.print(event.when - last);
1897 }
1898 last = event.when;
1899 pw.print('|'); pw.print(event.uid);
1900 pw.print('|'); pw.print(event.action);
1901 pw.println();
1902 }
1903 pw.println();
1904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001905 }
1906 }
1907
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001908 private void logBatchesLocked(SimpleDateFormat sdf) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001909 ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
1910 PrintWriter pw = new PrintWriter(bs);
1911 final long nowRTC = System.currentTimeMillis();
1912 final long nowELAPSED = SystemClock.elapsedRealtime();
1913 final int NZ = mAlarmBatches.size();
1914 for (int iz = 0; iz < NZ; iz++) {
1915 Batch bz = mAlarmBatches.get(iz);
1916 pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001917 dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC, sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001918 pw.flush();
1919 Slog.v(TAG, bs.toString());
1920 bs.reset();
1921 }
1922 }
1923
1924 private boolean validateConsistencyLocked() {
1925 if (DEBUG_VALIDATE) {
1926 long lastTime = Long.MIN_VALUE;
1927 final int N = mAlarmBatches.size();
1928 for (int i = 0; i < N; i++) {
1929 Batch b = mAlarmBatches.get(i);
1930 if (b.start >= lastTime) {
1931 // duplicate start times are okay because of standalone batches
1932 lastTime = b.start;
1933 } else {
1934 Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001935 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1936 logBatchesLocked(sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001937 return false;
1938 }
1939 }
1940 }
1941 return true;
1942 }
1943
Christopher Tate0dab4dc2014-12-16 12:14:06 -08001944 private Batch findFirstWakeupBatchLocked() {
1945 final int N = mAlarmBatches.size();
1946 for (int i = 0; i < N; i++) {
1947 Batch b = mAlarmBatches.get(i);
1948 if (b.hasWakeups()) {
1949 return b;
1950 }
1951 }
1952 return null;
1953 }
1954
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001955 long getNextWakeFromIdleTimeImpl() {
1956 synchronized (mLock) {
1957 return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE;
1958 }
1959 }
1960
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001961 void setDeviceIdleUserWhitelistImpl(int[] appids) {
1962 synchronized (mLock) {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001963 // appids are sorted, just send pending alarms for any new appids added to the whitelist
1964 int i = 0, j = 0;
1965 while (i < appids.length) {
1966 while (j < mDeviceIdleUserWhitelist.length
1967 && mDeviceIdleUserWhitelist[j] < appids[i]) {
1968 j++;
1969 }
1970 if (j < mDeviceIdleUserWhitelist.length
1971 && appids[i] != mDeviceIdleUserWhitelist[j]) {
1972 if (DEBUG_BG_LIMIT) {
1973 Slog.d(TAG, "Sending blocked alarms for whitelisted appid " + appids[j]);
1974 }
1975 sendPendingBackgroundAlarmsForAppIdLocked(appids[j]);
1976 }
1977 i++;
1978 }
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001979 mDeviceIdleUserWhitelist = appids;
1980 }
1981 }
1982
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001983 AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001984 synchronized (mLock) {
1985 return mNextAlarmClockForUser.get(userId);
1986 }
1987 }
1988
1989 /**
1990 * Recomputes the next alarm clock for all users.
1991 */
1992 private void updateNextAlarmClockLocked() {
1993 if (!mNextAlarmClockMayChange) {
1994 return;
1995 }
1996 mNextAlarmClockMayChange = false;
1997
Jose Lima235510e2014-08-13 12:50:01 -07001998 SparseArray<AlarmManager.AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02001999 nextForUser.clear();
2000
2001 final int N = mAlarmBatches.size();
2002 for (int i = 0; i < N; i++) {
2003 ArrayList<Alarm> alarms = mAlarmBatches.get(i).alarms;
2004 final int M = alarms.size();
2005
2006 for (int j = 0; j < M; j++) {
2007 Alarm a = alarms.get(j);
2008 if (a.alarmClock != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002009 final int userId = UserHandle.getUserId(a.uid);
Christopher Tate76389c02016-08-03 14:57:47 -07002010 AlarmManager.AlarmClockInfo current = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002011
2012 if (DEBUG_ALARM_CLOCK) {
Christopher Tate76389c02016-08-03 14:57:47 -07002013 Log.v(TAG, "Found AlarmClockInfo " + a.alarmClock + " at " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01002014 formatNextAlarm(getContext(), a.alarmClock, userId) +
Adrian Roosc42a1e12014-07-07 23:35:53 +02002015 " for user " + userId);
2016 }
2017
2018 // Alarms and batches are sorted by time, no need to compare times here.
2019 if (nextForUser.get(userId) == null) {
2020 nextForUser.put(userId, a.alarmClock);
Christopher Tate76389c02016-08-03 14:57:47 -07002021 } else if (a.alarmClock.equals(current)
2022 && current.getTriggerTime() <= nextForUser.get(userId).getTriggerTime()) {
2023 // same/earlier time and it's the one we cited before, so stick with it
2024 nextForUser.put(userId, current);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002025 }
2026 }
2027 }
2028 }
2029
2030 // Update mNextAlarmForUser with new values.
2031 final int NN = nextForUser.size();
2032 for (int i = 0; i < NN; i++) {
Jose Lima235510e2014-08-13 12:50:01 -07002033 AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002034 int userId = nextForUser.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07002035 AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002036 if (!newAlarm.equals(currentAlarm)) {
2037 updateNextAlarmInfoForUserLocked(userId, newAlarm);
2038 }
2039 }
2040
2041 // Remove users without any alarm clocks scheduled.
2042 final int NNN = mNextAlarmClockForUser.size();
2043 for (int i = NNN - 1; i >= 0; i--) {
2044 int userId = mNextAlarmClockForUser.keyAt(i);
2045 if (nextForUser.get(userId) == null) {
2046 updateNextAlarmInfoForUserLocked(userId, null);
2047 }
2048 }
2049 }
2050
Jose Lima235510e2014-08-13 12:50:01 -07002051 private void updateNextAlarmInfoForUserLocked(int userId,
2052 AlarmManager.AlarmClockInfo alarmClock) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02002053 if (alarmClock != null) {
2054 if (DEBUG_ALARM_CLOCK) {
2055 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01002056 formatNextAlarm(getContext(), alarmClock, userId));
Adrian Roosc42a1e12014-07-07 23:35:53 +02002057 }
2058 mNextAlarmClockForUser.put(userId, alarmClock);
2059 } else {
2060 if (DEBUG_ALARM_CLOCK) {
2061 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None");
2062 }
2063 mNextAlarmClockForUser.remove(userId);
2064 }
2065
2066 mPendingSendNextAlarmClockChangedForUser.put(userId, true);
2067 mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
2068 mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
2069 }
2070
2071 /**
2072 * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
2073 * for which alarm clocks have changed since the last call to this.
2074 *
2075 * Do not call with a lock held. Only call from mHandler's thread.
2076 *
2077 * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
2078 */
2079 private void sendNextAlarmClockChanged() {
Jose Lima235510e2014-08-13 12:50:01 -07002080 SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02002081 pendingUsers.clear();
2082
2083 synchronized (mLock) {
2084 final int N = mPendingSendNextAlarmClockChangedForUser.size();
2085 for (int i = 0; i < N; i++) {
2086 int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i);
2087 pendingUsers.append(userId, mNextAlarmClockForUser.get(userId));
2088 }
2089 mPendingSendNextAlarmClockChangedForUser.clear();
2090 }
2091
2092 final int N = pendingUsers.size();
2093 for (int i = 0; i < N; i++) {
2094 int userId = pendingUsers.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07002095 AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002096 Settings.System.putStringForUser(getContext().getContentResolver(),
2097 Settings.System.NEXT_ALARM_FORMATTED,
Selim Cinek9c4a7072014-11-21 17:44:34 +01002098 formatNextAlarm(getContext(), alarmClock, userId),
Adrian Roosc42a1e12014-07-07 23:35:53 +02002099 userId);
2100
2101 getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT,
2102 new UserHandle(userId));
2103 }
2104 }
2105
2106 /**
2107 * Formats an alarm like platform/packages/apps/DeskClock used to.
2108 */
Selim Cinek9c4a7072014-11-21 17:44:34 +01002109 private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info,
2110 int userId) {
2111 String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma";
Adrian Roosc42a1e12014-07-07 23:35:53 +02002112 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
2113 return (info == null) ? "" :
2114 DateFormat.format(pattern, info.getTriggerTime()).toString();
2115 }
2116
Adam Lesinski182f73f2013-12-05 16:48:06 -08002117 void rescheduleKernelAlarmsLocked() {
2118 // Schedule the next upcoming wakeup alarm. If there is a deliverable batch
2119 // prior to that which contains no wakeups, we schedule that as well.
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002120 long nextNonWakeup = 0;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002121 if (mAlarmBatches.size() > 0) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002122 final Batch firstWakeup = findFirstWakeupBatchLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002123 final Batch firstBatch = mAlarmBatches.get(0);
Prashant Malani753e9e02015-06-10 17:43:49 -07002124 if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002125 mNextWakeup = firstWakeup.start;
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07002126 mLastWakeupSet = SystemClock.elapsedRealtime();
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002127 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002128 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002129 if (firstBatch != firstWakeup) {
2130 nextNonWakeup = firstBatch.start;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002131 }
2132 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002133 if (mPendingNonWakeupAlarms.size() > 0) {
2134 if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
2135 nextNonWakeup = mNextNonWakeupDeliveryTime;
2136 }
2137 }
Prashant Malani753e9e02015-06-10 17:43:49 -07002138 if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002139 mNextNonWakeup = nextNonWakeup;
2140 setLocked(ELAPSED_REALTIME, nextNonWakeup);
2141 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002142 }
2143
Christopher Tate14a7bb02015-10-01 10:24:31 -07002144 private void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08002145 boolean didRemove = false;
2146 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2147 Batch b = mAlarmBatches.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -07002148 didRemove |= b.remove(operation, directReceiver);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002149 if (b.size() == 0) {
2150 mAlarmBatches.remove(i);
2151 }
2152 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002153 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002154 if (mPendingWhileIdleAlarms.get(i).matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002155 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2156 mPendingWhileIdleAlarms.remove(i);
2157 }
2158 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002159 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
2160 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
2161 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
2162 if (alarmsForUid.get(j).matches(operation, directReceiver)) {
2163 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2164 alarmsForUid.remove(j);
2165 }
2166 }
2167 if (alarmsForUid.size() == 0) {
2168 mPendingBackgroundAlarms.removeAt(i);
2169 }
2170 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002171 if (didRemove) {
2172 if (DEBUG_BATCH) {
2173 Slog.v(TAG, "remove(operation) changed bounds; rebatching");
2174 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002175 boolean restorePending = false;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002176 if (mPendingIdleUntil != null && mPendingIdleUntil.matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002177 mPendingIdleUntil = null;
2178 restorePending = true;
2179 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002180 if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002181 mNextWakeFromIdle = null;
2182 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002183 rebatchAllAlarmsLocked(true);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002184 if (restorePending) {
2185 restorePendingWhileIdleAlarmsLocked();
2186 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02002187 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002188 }
2189 }
2190
2191 void removeLocked(String packageName) {
2192 boolean didRemove = false;
2193 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2194 Batch b = mAlarmBatches.get(i);
2195 didRemove |= b.remove(packageName);
2196 if (b.size() == 0) {
2197 mAlarmBatches.remove(i);
2198 }
2199 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002200 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002201 final Alarm a = mPendingWhileIdleAlarms.get(i);
2202 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002203 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2204 mPendingWhileIdleAlarms.remove(i);
2205 }
2206 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002207 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i --) {
2208 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
2209 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
2210 if (alarmsForUid.get(j).matches(packageName)) {
2211 alarmsForUid.remove(j);
2212 }
2213 }
2214 if (alarmsForUid.size() == 0) {
2215 mPendingBackgroundAlarms.removeAt(i);
2216 }
2217 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002218 if (didRemove) {
2219 if (DEBUG_BATCH) {
2220 Slog.v(TAG, "remove(package) changed bounds; rebatching");
2221 }
2222 rebatchAllAlarmsLocked(true);
2223 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02002224 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002225 }
2226 }
2227
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002228 void removeForStoppedLocked(int uid) {
2229 boolean didRemove = false;
2230 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2231 Batch b = mAlarmBatches.get(i);
2232 didRemove |= b.removeForStopped(uid);
2233 if (b.size() == 0) {
2234 mAlarmBatches.remove(i);
2235 }
2236 }
2237 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
2238 final Alarm a = mPendingWhileIdleAlarms.get(i);
Dianne Hackborne07641d2016-11-09 15:07:23 -08002239 if (a.uid == uid) {
2240 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2241 mPendingWhileIdleAlarms.remove(i);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002242 }
2243 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002244 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
2245 if (mPendingBackgroundAlarms.keyAt(i) == uid) {
2246 mPendingBackgroundAlarms.removeAt(i);
2247 }
2248 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002249 if (didRemove) {
2250 if (DEBUG_BATCH) {
2251 Slog.v(TAG, "remove(package) changed bounds; rebatching");
2252 }
2253 rebatchAllAlarmsLocked(true);
2254 rescheduleKernelAlarmsLocked();
2255 updateNextAlarmClockLocked();
2256 }
2257 }
2258
Adam Lesinski182f73f2013-12-05 16:48:06 -08002259 void removeUserLocked(int userHandle) {
2260 boolean didRemove = false;
2261 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2262 Batch b = mAlarmBatches.get(i);
2263 didRemove |= b.remove(userHandle);
2264 if (b.size() == 0) {
2265 mAlarmBatches.remove(i);
2266 }
2267 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002268 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002269 if (UserHandle.getUserId(mPendingWhileIdleAlarms.get(i).creatorUid)
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002270 == userHandle) {
2271 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2272 mPendingWhileIdleAlarms.remove(i);
2273 }
2274 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002275 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
2276 if (UserHandle.getUserId(mPendingBackgroundAlarms.keyAt(i)) == userHandle) {
2277 mPendingBackgroundAlarms.removeAt(i);
2278 }
2279 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002280 for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
2281 if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
2282 mLastAllowWhileIdleDispatch.removeAt(i);
2283 }
2284 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002285
2286 if (didRemove) {
2287 if (DEBUG_BATCH) {
2288 Slog.v(TAG, "remove(user) changed bounds; rebatching");
2289 }
2290 rebatchAllAlarmsLocked(true);
2291 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02002292 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002293 }
2294 }
2295
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002296 void interactiveStateChangedLocked(boolean interactive) {
2297 if (mInteractive != interactive) {
2298 mInteractive = interactive;
2299 final long nowELAPSED = SystemClock.elapsedRealtime();
2300 if (interactive) {
2301 if (mPendingNonWakeupAlarms.size() > 0) {
2302 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
2303 mTotalDelayTime += thisDelayTime;
2304 if (mMaxDelayTime < thisDelayTime) {
2305 mMaxDelayTime = thisDelayTime;
2306 }
2307 deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
2308 mPendingNonWakeupAlarms.clear();
2309 }
2310 if (mNonInteractiveStartTime > 0) {
2311 long dur = nowELAPSED - mNonInteractiveStartTime;
2312 if (dur > mNonInteractiveTime) {
2313 mNonInteractiveTime = dur;
2314 }
2315 }
2316 } else {
2317 mNonInteractiveStartTime = nowELAPSED;
2318 }
2319 }
2320 }
2321
Adam Lesinski182f73f2013-12-05 16:48:06 -08002322 boolean lookForPackageLocked(String packageName) {
2323 for (int i = 0; i < mAlarmBatches.size(); i++) {
2324 Batch b = mAlarmBatches.get(i);
2325 if (b.hasPackage(packageName)) {
2326 return true;
2327 }
2328 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002329 for (int i = 0; i < mPendingWhileIdleAlarms.size(); i++) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002330 final Alarm a = mPendingWhileIdleAlarms.get(i);
2331 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002332 return true;
2333 }
2334 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002335 return false;
2336 }
2337
2338 private void setLocked(int type, long when) {
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -08002339 if (mNativeData != 0) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08002340 // The kernel never triggers alarms with negative wakeup times
2341 // so we ensure they are positive.
2342 long alarmSeconds, alarmNanoseconds;
2343 if (when < 0) {
2344 alarmSeconds = 0;
2345 alarmNanoseconds = 0;
2346 } else {
2347 alarmSeconds = when / 1000;
2348 alarmNanoseconds = (when % 1000) * 1000 * 1000;
2349 }
2350
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -08002351 set(mNativeData, type, alarmSeconds, alarmNanoseconds);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002352 } else {
2353 Message msg = Message.obtain();
2354 msg.what = ALARM_EVENT;
2355
2356 mHandler.removeMessages(ALARM_EVENT);
2357 mHandler.sendMessageAtTime(msg, when);
2358 }
2359 }
2360
Dianne Hackborn043fcd92010-10-06 14:27:34 -07002361 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002362 String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 for (int i=list.size()-1; i>=0; i--) {
2364 Alarm a = list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002365 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
2366 pw.print(": "); pw.println(a);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002367 a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 }
2369 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002370
2371 private static final String labelForType(int type) {
2372 switch (type) {
2373 case RTC: return "RTC";
2374 case RTC_WAKEUP : return "RTC_WAKEUP";
2375 case ELAPSED_REALTIME : return "ELAPSED";
2376 case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP";
2377 default:
2378 break;
2379 }
2380 return "--unknown--";
2381 }
2382
2383 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002384 String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07002385 for (int i=list.size()-1; i>=0; i--) {
2386 Alarm a = list.get(i);
2387 final String label = labelForType(a.type);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002388 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
2389 pw.print(": "); pw.println(a);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002390 a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002391 }
2392 }
2393
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002394 private boolean isBackgroundRestricted(Alarm alarm) {
2395 if (!mConstants.BACKGROUND_ALARMS_BLOCKED) {
2396 return false;
2397 }
2398 if (alarm.alarmClock != null) {
2399 // Don't block alarm clocks
2400 return false;
2401 }
2402 if (alarm.operation != null
2403 && (alarm.operation.isActivity() || alarm.operation.isForegroundService())) {
2404 // Don't block starting foreground components
2405 return false;
2406 }
2407 final String sourcePackage =
2408 (alarm.operation != null) ? alarm.operation.getCreatorPackage() : alarm.packageName;
2409 final int sourceUid = alarm.creatorUid;
2410 return mForcedAppStandbyPackages.contains(sourcePackage) && !mForegroundUids.get(sourceUid)
2411 && Arrays.binarySearch(mDeviceIdleUserWhitelist, UserHandle.getAppId(sourceUid))
2412 < 0;
2413 }
2414
Greg Hackmanna1d6f922013-12-09 16:56:53 -08002415 private native long init();
2416 private native void close(long nativeData);
2417 private native void set(long nativeData, int type, long seconds, long nanoseconds);
2418 private native int waitForAlarm(long nativeData);
Greg Hackmann38bf5142014-02-19 16:39:36 -08002419 private native int setKernelTime(long nativeData, long millis);
Greg Hackmanna1d6f922013-12-09 16:56:53 -08002420 private native int setKernelTimezone(long nativeData, int minuteswest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002421
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002422 boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002423 final long nowRTC) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002424 boolean hasWakeup = false;
Christopher Tatee0a22b32013-07-11 14:43:13 -07002425 // batches are temporally sorted, so we need only pull from the
2426 // start of the list until we either empty it or hit a batch
2427 // that is not yet deliverable
Christopher Tate6578ad12013-09-24 17:12:46 -07002428 while (mAlarmBatches.size() > 0) {
2429 Batch batch = mAlarmBatches.get(0);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002430 if (batch.start > nowELAPSED) {
2431 // Everything else is scheduled for the future
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002432 break;
2433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002434
Christopher Tatee0a22b32013-07-11 14:43:13 -07002435 // We will (re)schedule some alarms now; don't let that interfere
2436 // with delivery of this current batch
2437 mAlarmBatches.remove(0);
Dianne Hackborn390517b2013-05-30 15:03:32 -07002438
Christopher Tatee0a22b32013-07-11 14:43:13 -07002439 final int N = batch.size();
2440 for (int i = 0; i < N; i++) {
2441 Alarm alarm = batch.get(i);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002442
2443 if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
2444 // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
2445 // schedule such alarms.
2446 long lastTime = mLastAllowWhileIdleDispatch.get(alarm.uid, 0);
2447 long minTime = lastTime + mAllowWhileIdleMinTime;
2448 if (nowELAPSED < minTime) {
2449 // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
2450 // alarm went off for this app. Reschedule the alarm to be in the
2451 // correct time period.
2452 alarm.whenElapsed = minTime;
2453 if (alarm.maxWhenElapsed < minTime) {
2454 alarm.maxWhenElapsed = minTime;
2455 }
Dianne Hackbornae78bf82015-10-26 13:33:20 -07002456 if (RECORD_DEVICE_IDLE_ALARMS) {
2457 IdleDispatchEntry ent = new IdleDispatchEntry();
2458 ent.uid = alarm.uid;
2459 ent.pkg = alarm.operation.getCreatorPackage();
2460 ent.tag = alarm.operation.getTag("");
2461 ent.op = "RESCHEDULE";
2462 ent.elapsedRealtime = nowELAPSED;
2463 ent.argRealtime = lastTime;
2464 mAllowWhileIdleDispatches.add(ent);
2465 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002466 setImplLocked(alarm, true, false);
2467 continue;
2468 }
2469 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002470 if (isBackgroundRestricted(alarm)) {
2471 // Alarms with FLAG_WAKE_FROM_IDLE or mPendingIdleUntil alarm are not deferred
2472 if (DEBUG_BG_LIMIT) {
2473 Slog.d(TAG, "Deferring alarm " + alarm + " due to user forced app standby");
2474 }
2475 ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(alarm.creatorUid);
2476 if (alarmsForUid == null) {
2477 alarmsForUid = new ArrayList<>();
2478 mPendingBackgroundAlarms.put(alarm.creatorUid, alarmsForUid);
2479 }
2480 alarmsForUid.add(alarm);
2481 continue;
2482 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002483
Christopher Tatee0a22b32013-07-11 14:43:13 -07002484 alarm.count = 1;
2485 triggerList.add(alarm);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002486 if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
2487 EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
Christopher Tate14a7bb02015-10-01 10:24:31 -07002488 alarm.statsTag);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002489 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002490 if (mPendingIdleUntil == alarm) {
2491 mPendingIdleUntil = null;
2492 rebatchAllAlarmsLocked(false);
2493 restorePendingWhileIdleAlarmsLocked();
2494 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002495 if (mNextWakeFromIdle == alarm) {
2496 mNextWakeFromIdle = null;
2497 rebatchAllAlarmsLocked(false);
2498 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002499
2500 // Recurring alarms may have passed several alarm intervals while the
2501 // phone was asleep or off, so pass a trigger count when sending them.
2502 if (alarm.repeatInterval > 0) {
2503 // this adjustment will be zero if we're late by
2504 // less than one full repeat interval
2505 alarm.count += (nowELAPSED - alarm.whenElapsed) / alarm.repeatInterval;
2506
2507 // Also schedule its next recurrence
2508 final long delta = alarm.count * alarm.repeatInterval;
2509 final long nextElapsed = alarm.whenElapsed + delta;
Christopher Tate3e04b472013-10-21 17:51:31 -07002510 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
Christopher Tatee0a22b32013-07-11 14:43:13 -07002511 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
Christopher Tate14a7bb02015-10-01 10:24:31 -07002512 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
2513 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
Christopher Tate864d42e2014-12-02 11:48:53 -08002514 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515
Christopher Tate864d42e2014-12-02 11:48:53 -08002516 if (alarm.wakeup) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002517 hasWakeup = true;
2518 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02002519
2520 // We removed an alarm clock. Let the caller recompute the next alarm clock.
2521 if (alarm.alarmClock != null) {
2522 mNextAlarmClockMayChange = true;
2523 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07002524 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002526
Christopher Tate1590f1e2014-10-02 17:27:57 -07002527 // This is a new alarm delivery set; bump the sequence number to indicate that
2528 // all apps' alarm delivery classes should be recalculated.
2529 mCurrentSeq++;
2530 calculateDeliveryPriorities(triggerList);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002531 Collections.sort(triggerList, mAlarmDispatchComparator);
2532
2533 if (localLOGV) {
2534 for (int i=0; i<triggerList.size(); i++) {
2535 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
2536 }
2537 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002538
2539 return hasWakeup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002540 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 /**
2543 * This Comparator sorts Alarms into increasing time order.
2544 */
2545 public static class IncreasingTimeOrder implements Comparator<Alarm> {
2546 public int compare(Alarm a1, Alarm a2) {
jinho.park1acd32a2015-05-27 14:44:18 +09002547 long when1 = a1.whenElapsed;
2548 long when2 = a2.whenElapsed;
Charles Tsaicdaaeee2015-05-20 18:16:48 +08002549 if (when1 > when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 return 1;
2551 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +08002552 if (when1 < when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 return -1;
2554 }
2555 return 0;
2556 }
2557 }
2558
2559 private static class Alarm {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002560 public final int type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002561 public final long origWhen;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002562 public final boolean wakeup;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002563 public final PendingIntent operation;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002564 public final IAlarmListener listener;
2565 public final String listenerTag;
2566 public final String statsTag;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002567 public final WorkSource workSource;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002568 public final int flags;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002569 public final AlarmManager.AlarmClockInfo alarmClock;
2570 public final int uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002571 public final int creatorUid;
2572 public final String packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002573 public int count;
2574 public long when;
Christopher Tate3e04b472013-10-21 17:51:31 -07002575 public long windowLength;
Christopher Tatee0a22b32013-07-11 14:43:13 -07002576 public long whenElapsed; // 'when' in the elapsed time base
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002577 public long maxWhenElapsed; // also in the elapsed time base
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 public long repeatInterval;
Christopher Tate1590f1e2014-10-02 17:27:57 -07002579 public PriorityClass priorityClass;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002580
Christopher Tate3e04b472013-10-21 17:51:31 -07002581 public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
Christopher Tate14a7bb02015-10-01 10:24:31 -07002582 long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag,
2583 WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info,
2584 int _uid, String _pkgName) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07002585 type = _type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002586 origWhen = _when;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002587 wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
2588 || _type == AlarmManager.RTC_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -07002589 when = _when;
2590 whenElapsed = _whenElapsed;
Christopher Tate3e04b472013-10-21 17:51:31 -07002591 windowLength = _windowLength;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002592 maxWhenElapsed = _maxWhen;
Christopher Tatee0a22b32013-07-11 14:43:13 -07002593 repeatInterval = _interval;
2594 operation = _op;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002595 listener = _rec;
2596 listenerTag = _listenerTag;
2597 statsTag = makeTag(_op, _listenerTag, _type);
David Christieebe51fc2013-07-26 13:23:29 -07002598 workSource = _ws;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002599 flags = _flags;
Adrian Roosc42a1e12014-07-07 23:35:53 +02002600 alarmClock = _info;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002601 uid = _uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002602 packageName = _pkgName;
2603
2604 creatorUid = (operation != null) ? operation.getCreatorUid() : uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002606
Christopher Tate14a7bb02015-10-01 10:24:31 -07002607 public static String makeTag(PendingIntent pi, String tag, int type) {
2608 final String alarmString = type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
2609 ? "*walarm*:" : "*alarm*:";
2610 return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag);
2611 }
2612
2613 public WakeupEvent makeWakeupEvent(long nowRTC) {
2614 return new WakeupEvent(nowRTC, creatorUid,
2615 (operation != null)
2616 ? operation.getIntent().getAction()
2617 : ("<listener>:" + listenerTag));
2618 }
2619
2620 // Returns true if either matches
2621 public boolean matches(PendingIntent pi, IAlarmListener rec) {
2622 return (operation != null)
2623 ? operation.equals(pi)
Lorenzo Colitti9b43ce02015-11-22 22:00:08 +09002624 : rec != null && listener.asBinder().equals(rec.asBinder());
Christopher Tate14a7bb02015-10-01 10:24:31 -07002625 }
2626
2627 public boolean matches(String packageName) {
2628 return (operation != null)
2629 ? packageName.equals(operation.getTargetPackage())
2630 : packageName.equals(this.packageName);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002631 }
2632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002633 @Override
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002634 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002635 StringBuilder sb = new StringBuilder(128);
2636 sb.append("Alarm{");
2637 sb.append(Integer.toHexString(System.identityHashCode(this)));
2638 sb.append(" type ");
2639 sb.append(type);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002640 sb.append(" when ");
2641 sb.append(when);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002642 sb.append(" ");
Christopher Tate14a7bb02015-10-01 10:24:31 -07002643 if (operation != null) {
2644 sb.append(operation.getTargetPackage());
2645 } else {
Dianne Hackborn2fefbcf2016-03-18 15:34:54 -07002646 sb.append(packageName);
Christopher Tate14a7bb02015-10-01 10:24:31 -07002647 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002648 sb.append('}');
2649 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002650 }
2651
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002652 public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED,
2653 SimpleDateFormat sdf) {
2654 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
Christopher Tate14a7bb02015-10-01 10:24:31 -07002655 pw.print(prefix); pw.print("tag="); pw.println(statsTag);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002656 pw.print(prefix); pw.print("type="); pw.print(type);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002657 pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
2658 nowELAPSED, pw);
Christopher Tate14a7bb02015-10-01 10:24:31 -07002659 pw.print(" when=");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002660 if (isRtc) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002661 pw.print(sdf.format(new Date(when)));
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002662 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002663 TimeUtils.formatDuration(when, nowELAPSED, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002664 }
2665 pw.println();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002666 pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002667 pw.print(" repeatInterval="); pw.print(repeatInterval);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002668 pw.print(" count="); pw.print(count);
2669 pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002670 if (alarmClock != null) {
2671 pw.print(prefix); pw.println("Alarm clock:");
2672 pw.print(prefix); pw.print(" triggerTime=");
2673 pw.println(sdf.format(new Date(alarmClock.getTriggerTime())));
2674 pw.print(prefix); pw.print(" showIntent="); pw.println(alarmClock.getShowIntent());
2675 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002676 pw.print(prefix); pw.print("operation="); pw.println(operation);
Christopher Tate14a7bb02015-10-01 10:24:31 -07002677 if (listener != null) {
2678 pw.print(prefix); pw.print("listener="); pw.println(listener.asBinder());
2679 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680 }
2681 }
Christopher Tate18a75f12013-07-01 18:18:59 -07002682
Christopher Tatee0a22b32013-07-11 14:43:13 -07002683 void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) {
2684 final int numBatches = batches.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07002685 for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) {
2686 Batch b = batches.get(nextBatch);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002687 if (b.start > nowELAPSED) {
Christopher Tate18a75f12013-07-01 18:18:59 -07002688 break;
2689 }
2690
Christopher Tatee0a22b32013-07-11 14:43:13 -07002691 final int numAlarms = b.alarms.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07002692 for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) {
2693 Alarm a = b.alarms.get(nextAlarm);
Christopher Tate14a7bb02015-10-01 10:24:31 -07002694 mRecentWakeups.add(a.makeWakeupEvent(nowRTC));
Christopher Tatee0a22b32013-07-11 14:43:13 -07002695 }
Christopher Tate18a75f12013-07-01 18:18:59 -07002696 }
2697 }
2698
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002699 long currentNonWakeupFuzzLocked(long nowELAPSED) {
2700 long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
2701 if (timeSinceOn < 5*60*1000) {
2702 // If the screen has been off for 5 minutes, only delay by at most two minutes.
2703 return 2*60*1000;
2704 } else if (timeSinceOn < 30*60*1000) {
2705 // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
2706 return 15*60*1000;
2707 } else {
2708 // Otherwise, we will delay by at most an hour.
2709 return 60*60*1000;
2710 }
2711 }
2712
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002713 static int fuzzForDuration(long duration) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002714 if (duration < 15*60*1000) {
2715 // If the duration until the time is less than 15 minutes, the maximum fuzz
2716 // is the duration.
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002717 return (int)duration;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002718 } else if (duration < 90*60*1000) {
2719 // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes,
2720 return 15*60*1000;
2721 } else {
2722 // Otherwise, we will fuzz by at most half an hour.
2723 return 30*60*1000;
2724 }
2725 }
2726
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002727 boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
2728 if (mInteractive) {
2729 return false;
2730 }
2731 if (mLastAlarmDeliveryTime <= 0) {
2732 return false;
2733 }
minho.choo649acab2014-12-12 16:13:55 +09002734 if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002735 // This is just a little paranoia, if somehow we have pending non-wakeup alarms
2736 // and the next delivery time is in the past, then just deliver them all. This
2737 // avoids bugs where we get stuck in a loop trying to poll for alarms.
2738 return false;
2739 }
2740 long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
2741 return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
2742 }
2743
2744 void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
2745 mLastAlarmDeliveryTime = nowELAPSED;
2746 for (int i=0; i<triggerList.size(); i++) {
2747 Alarm alarm = triggerList.get(i);
Dianne Hackborna750a632015-06-16 17:18:23 -07002748 final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002749 try {
Christopher Tate2ff5a732014-09-18 13:47:57 -07002750 if (localLOGV) {
2751 Slog.v(TAG, "sending alarm " + alarm);
2752 }
Dianne Hackborn1e383822015-04-10 14:02:33 -07002753 if (RECORD_ALARMS_IN_HISTORY) {
2754 if (alarm.workSource != null && alarm.workSource.size() > 0) {
2755 for (int wi=0; wi<alarm.workSource.size(); wi++) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002756 ActivityManager.noteAlarmStart(
Christopher Tate14a7bb02015-10-01 10:24:31 -07002757 alarm.operation, alarm.workSource.get(wi), alarm.statsTag);
Dianne Hackborn1e383822015-04-10 14:02:33 -07002758 }
2759 } else {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002760 ActivityManager.noteAlarmStart(
Christopher Tate14a7bb02015-10-01 10:24:31 -07002761 alarm.operation, alarm.uid, alarm.statsTag);
Dianne Hackborn1e383822015-04-10 14:02:33 -07002762 }
2763 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002764 mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002765 } catch (RuntimeException e) {
2766 Slog.w(TAG, "Failure sending alarm.", e);
2767 }
2768 }
2769 }
2770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002771 private class AlarmThread extends Thread
2772 {
2773 public AlarmThread()
2774 {
2775 super("AlarmManager");
2776 }
2777
2778 public void run()
2779 {
Dianne Hackborn390517b2013-05-30 15:03:32 -07002780 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
2781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002782 while (true)
2783 {
Greg Hackmanna1d6f922013-12-09 16:56:53 -08002784 int result = waitForAlarm(mNativeData);
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07002785 mLastWakeup = SystemClock.elapsedRealtime();
Dianne Hackborn390517b2013-05-30 15:03:32 -07002786
2787 triggerList.clear();
2788
Dianne Hackbornc3527222015-05-13 14:03:20 -07002789 final long nowRTC = System.currentTimeMillis();
2790 final long nowELAPSED = SystemClock.elapsedRealtime();
2791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792 if ((result & TIME_CHANGED_MASK) != 0) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07002793 // The kernel can give us spurious time change notifications due to
2794 // small adjustments it makes internally; we want to filter those out.
2795 final long lastTimeChangeClockTime;
2796 final long expectedClockTime;
Dianne Hackborn998e6082014-09-11 19:13:23 -07002797 synchronized (mLock) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07002798 lastTimeChangeClockTime = mLastTimeChangeClockTime;
2799 expectedClockTime = lastTimeChangeClockTime
2800 + (nowELAPSED - mLastTimeChangeRealtime);
Dianne Hackborn998e6082014-09-11 19:13:23 -07002801 }
Christopher Tate2b6e459e2017-02-17 14:33:52 -08002802 if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-1000)
2803 || nowRTC > (expectedClockTime+1000)) {
2804 // The change is by at least +/- 1000 ms (or this is the first change),
Dianne Hackbornc3527222015-05-13 14:03:20 -07002805 // let's do it!
2806 if (DEBUG_BATCH) {
2807 Slog.v(TAG, "Time changed notification from kernel; rebatching");
2808 }
2809 removeImpl(mTimeTickSender);
Christopher Tatecf024712016-08-05 13:21:45 -07002810 removeImpl(mDateChangeSender);
Dianne Hackbornc3527222015-05-13 14:03:20 -07002811 rebatchAllAlarms();
2812 mClockReceiver.scheduleTimeTickEvent();
Christopher Tatecf024712016-08-05 13:21:45 -07002813 mClockReceiver.scheduleDateChangedEvent();
Dianne Hackbornc3527222015-05-13 14:03:20 -07002814 synchronized (mLock) {
2815 mNumTimeChanged++;
2816 mLastTimeChangeClockTime = nowRTC;
2817 mLastTimeChangeRealtime = nowELAPSED;
2818 }
2819 Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
2820 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
Christopher Tate2b6e459e2017-02-17 14:33:52 -08002821 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
Chad Brubaker291df4f2017-03-14 10:23:02 -07002822 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
2823 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Dianne Hackbornc3527222015-05-13 14:03:20 -07002824 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
2825
2826 // The world has changed on us, so we need to re-evaluate alarms
2827 // regardless of whether the kernel has told us one went off.
2828 result |= IS_WAKEUP_MASK;
2829 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002830 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002831
Dianne Hackbornc3527222015-05-13 14:03:20 -07002832 if (result != TIME_CHANGED_MASK) {
2833 // If this was anything besides just a time change, then figure what if
2834 // anything to do about alarms.
2835 synchronized (mLock) {
2836 if (localLOGV) Slog.v(
2837 TAG, "Checking for alarms... rtc=" + nowRTC
2838 + ", elapsed=" + nowELAPSED);
Christopher Tate18a75f12013-07-01 18:18:59 -07002839
Dianne Hackbornc3527222015-05-13 14:03:20 -07002840 if (WAKEUP_STATS) {
2841 if ((result & IS_WAKEUP_MASK) != 0) {
2842 long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
2843 int n = 0;
2844 for (WakeupEvent event : mRecentWakeups) {
2845 if (event.when > newEarliest) break;
2846 n++; // number of now-stale entries at the list head
2847 }
2848 for (int i = 0; i < n; i++) {
2849 mRecentWakeups.remove();
2850 }
Christopher Tate18a75f12013-07-01 18:18:59 -07002851
Dianne Hackbornc3527222015-05-13 14:03:20 -07002852 recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002853 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002854 }
Dianne Hackbornc3527222015-05-13 14:03:20 -07002855
2856 boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2857 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
2858 // if there are no wakeup alarms and the screen is off, we can
2859 // delay what we have so far until the future.
2860 if (mPendingNonWakeupAlarms.size() == 0) {
2861 mStartCurrentDelayTime = nowELAPSED;
2862 mNextNonWakeupDeliveryTime = nowELAPSED
2863 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
2864 }
2865 mPendingNonWakeupAlarms.addAll(triggerList);
2866 mNumDelayedAlarms += triggerList.size();
2867 rescheduleKernelAlarmsLocked();
2868 updateNextAlarmClockLocked();
2869 } else {
2870 // now deliver the alarm intents; if there are pending non-wakeup
2871 // alarms, we need to merge them in to the list. note we don't
2872 // just deliver them first because we generally want non-wakeup
2873 // alarms delivered after wakeup alarms.
2874 rescheduleKernelAlarmsLocked();
2875 updateNextAlarmClockLocked();
2876 if (mPendingNonWakeupAlarms.size() > 0) {
2877 calculateDeliveryPriorities(mPendingNonWakeupAlarms);
2878 triggerList.addAll(mPendingNonWakeupAlarms);
2879 Collections.sort(triggerList, mAlarmDispatchComparator);
2880 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
2881 mTotalDelayTime += thisDelayTime;
2882 if (mMaxDelayTime < thisDelayTime) {
2883 mMaxDelayTime = thisDelayTime;
2884 }
2885 mPendingNonWakeupAlarms.clear();
2886 }
2887 deliverAlarmsLocked(triggerList, nowELAPSED);
2888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002889 }
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07002890
2891 } else {
2892 // Just in case -- even though no wakeup flag was set, make sure
2893 // we have updated the kernel to the next alarm time.
Christopher Tate7b5b7cb2016-07-07 14:41:36 -07002894 synchronized (mLock) {
2895 rescheduleKernelAlarmsLocked();
2896 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 }
2898 }
2899 }
2900 }
Christopher Tatec4a07d12012-04-06 14:19:13 -07002901
David Christieebe51fc2013-07-26 13:23:29 -07002902 /**
2903 * Attribute blame for a WakeLock.
2904 * @param pi PendingIntent to attribute blame to if ws is null.
2905 * @param ws WorkSource to attribute blame.
Christopher Tate14a7bb02015-10-01 10:24:31 -07002906 * @param knownUid attribution uid; < 0 if we need to derive it from the PendingIntent sender
David Christieebe51fc2013-07-26 13:23:29 -07002907 */
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002908 void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
Christopher Tate14a7bb02015-10-01 10:24:31 -07002909 int knownUid, boolean first) {
Christopher Tatec4a07d12012-04-06 14:19:13 -07002910 try {
Dianne Hackborna1bd7922014-03-21 11:07:11 -07002911 final boolean unimportant = pi == mTimeTickSender;
2912 mWakeLock.setUnimportantForLogging(unimportant);
Dianne Hackborn4590e522014-03-24 13:36:46 -07002913 if (first || mLastWakeLockUnimportantForLogging) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002914 mWakeLock.setHistoryTag(tag);
Dianne Hackborn4590e522014-03-24 13:36:46 -07002915 } else {
2916 mWakeLock.setHistoryTag(null);
2917 }
2918 mLastWakeLockUnimportantForLogging = unimportant;
David Christieebe51fc2013-07-26 13:23:29 -07002919 if (ws != null) {
2920 mWakeLock.setWorkSource(ws);
2921 return;
2922 }
2923
Christopher Tate14a7bb02015-10-01 10:24:31 -07002924 final int uid = (knownUid >= 0)
2925 ? knownUid
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002926 : ActivityManager.getService().getUidForIntentSender(pi.getTarget());
Christopher Tatec4a07d12012-04-06 14:19:13 -07002927 if (uid >= 0) {
2928 mWakeLock.setWorkSource(new WorkSource(uid));
2929 return;
2930 }
2931 } catch (Exception e) {
2932 }
2933
2934 // Something went wrong; fall back to attributing the lock to the OS
2935 mWakeLock.setWorkSource(null);
2936 }
2937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 private class AlarmHandler extends Handler {
2939 public static final int ALARM_EVENT = 1;
Dianne Hackborn627dfa12015-11-11 18:10:30 -08002940 public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2;
2941 public static final int LISTENER_TIMEOUT = 3;
2942 public static final int REPORT_ALARMS_ACTIVE = 4;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002943
2944 public AlarmHandler() {
2945 }
2946
2947 public void handleMessage(Message msg) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002948 switch (msg.what) {
2949 case ALARM_EVENT: {
2950 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
2951 synchronized (mLock) {
2952 final long nowRTC = System.currentTimeMillis();
2953 final long nowELAPSED = SystemClock.elapsedRealtime();
2954 triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
2955 updateNextAlarmClockLocked();
2956 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02002957
Christopher Tate14a7bb02015-10-01 10:24:31 -07002958 // now trigger the alarms without the lock held
2959 for (int i=0; i<triggerList.size(); i++) {
2960 Alarm alarm = triggerList.get(i);
2961 try {
2962 alarm.operation.send();
2963 } catch (PendingIntent.CanceledException e) {
2964 if (alarm.repeatInterval > 0) {
2965 // This IntentSender is no longer valid, but this
2966 // is a repeating alarm, so toss the hoser.
2967 removeImpl(alarm.operation);
2968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002969 }
2970 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002971 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002972 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002973
2974 case SEND_NEXT_ALARM_CLOCK_CHANGED:
2975 sendNextAlarmClockChanged();
2976 break;
2977
2978 case LISTENER_TIMEOUT:
2979 mDeliveryTracker.alarmTimedOut((IBinder) msg.obj);
2980 break;
2981
Dianne Hackborn627dfa12015-11-11 18:10:30 -08002982 case REPORT_ALARMS_ACTIVE:
2983 if (mLocalDeviceIdleController != null) {
2984 mLocalDeviceIdleController.setAlarmsActive(msg.arg1 != 0);
2985 }
2986 break;
2987
Christopher Tate14a7bb02015-10-01 10:24:31 -07002988 default:
2989 // nope, just ignore it
2990 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 }
2992 }
2993 }
2994
2995 class ClockReceiver extends BroadcastReceiver {
2996 public ClockReceiver() {
2997 IntentFilter filter = new IntentFilter();
2998 filter.addAction(Intent.ACTION_TIME_TICK);
2999 filter.addAction(Intent.ACTION_DATE_CHANGED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003000 getContext().registerReceiver(this, filter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001 }
3002
3003 @Override
3004 public void onReceive(Context context, Intent intent) {
3005 if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
Christopher Tate385e4982013-07-23 18:22:29 -07003006 if (DEBUG_BATCH) {
3007 Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
3008 }
3009 scheduleTimeTickEvent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003010 } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
3011 // Since the kernel does not keep track of DST, we need to
3012 // reset the TZ information at the beginning of each day
3013 // based off of the current Zone gmt offset + userspace tracked
3014 // daylight savings information.
3015 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
Lavettacn Xiaoc84cc4f2010-08-30 12:47:23 +02003016 int gmtOffset = zone.getOffset(System.currentTimeMillis());
Greg Hackmanna1d6f922013-12-09 16:56:53 -08003017 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
Christopher Tate385e4982013-07-23 18:22:29 -07003018 scheduleDateChangedEvent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 }
3020 }
3021
3022 public void scheduleTimeTickEvent() {
Paul Westbrook51608a52011-08-25 13:18:54 -07003023 final long currentTime = System.currentTimeMillis();
Sungmin Choi563914a2013-01-10 17:28:40 +09003024 final long nextTime = 60000 * ((currentTime / 60000) + 1);
Paul Westbrook51608a52011-08-25 13:18:54 -07003025
3026 // Schedule this event for the amount of time that it would take to get to
3027 // the top of the next minute.
Sungmin Choi563914a2013-01-10 17:28:40 +09003028 final long tickEventDelay = nextTime - currentTime;
Paul Westbrook51608a52011-08-25 13:18:54 -07003029
David Christieebe51fc2013-07-26 13:23:29 -07003030 final WorkSource workSource = null; // Let system take blame for time tick events.
Adam Lesinski182f73f2013-12-05 16:48:06 -08003031 setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003032 0, mTimeTickSender, null, null, AlarmManager.FLAG_STANDALONE, workSource,
3033 null, Process.myUid(), "android");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 }
Christopher Tate385e4982013-07-23 18:22:29 -07003035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 public void scheduleDateChangedEvent() {
3037 Calendar calendar = Calendar.getInstance();
3038 calendar.setTimeInMillis(System.currentTimeMillis());
Christopher Tateafa8b982016-08-10 16:15:48 -07003039 calendar.set(Calendar.HOUR_OF_DAY, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003040 calendar.set(Calendar.MINUTE, 0);
3041 calendar.set(Calendar.SECOND, 0);
3042 calendar.set(Calendar.MILLISECOND, 0);
3043 calendar.add(Calendar.DAY_OF_MONTH, 1);
David Christieebe51fc2013-07-26 13:23:29 -07003044
3045 final WorkSource workSource = null; // Let system take blame for date change events.
Christopher Tate14a7bb02015-10-01 10:24:31 -07003046 setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
3047 AlarmManager.FLAG_STANDALONE, workSource, null,
3048 Process.myUid(), "android");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 }
3050 }
3051
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003052 class InteractiveStateReceiver extends BroadcastReceiver {
3053 public InteractiveStateReceiver() {
3054 IntentFilter filter = new IntentFilter();
3055 filter.addAction(Intent.ACTION_SCREEN_OFF);
3056 filter.addAction(Intent.ACTION_SCREEN_ON);
3057 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
3058 getContext().registerReceiver(this, filter);
3059 }
3060
3061 @Override
3062 public void onReceive(Context context, Intent intent) {
3063 synchronized (mLock) {
3064 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
3065 }
3066 }
3067 }
3068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 class UninstallReceiver extends BroadcastReceiver {
3070 public UninstallReceiver() {
3071 IntentFilter filter = new IntentFilter();
3072 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
3073 filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003074 filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 filter.addDataScheme("package");
Adam Lesinski182f73f2013-12-05 16:48:06 -08003076 getContext().registerReceiver(this, filter);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003077 // Register for events related to sdcard installation.
3078 IntentFilter sdFilter = new IntentFilter();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08003079 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003080 sdFilter.addAction(Intent.ACTION_USER_STOPPED);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003081 sdFilter.addAction(Intent.ACTION_UID_REMOVED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003082 getContext().registerReceiver(this, sdFilter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 }
3084
3085 @Override
3086 public void onReceive(Context context, Intent intent) {
3087 synchronized (mLock) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003088 String action = intent.getAction();
3089 String pkgList[] = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003090 if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
3091 pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3092 for (String packageName : pkgList) {
3093 if (lookForPackageLocked(packageName)) {
3094 setResultCode(Activity.RESULT_OK);
3095 return;
3096 }
3097 }
3098 return;
3099 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003100 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003101 } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
3102 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
3103 if (userHandle >= 0) {
3104 removeUserLocked(userHandle);
3105 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003106 } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
3107 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
3108 if (uid >= 0) {
3109 mLastAllowWhileIdleDispatch.delete(uid);
3110 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003111 } else {
Dianne Hackborn409578f2010-03-10 17:23:43 -08003112 if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
3113 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
3114 // This package is being updated; don't kill its alarms.
3115 return;
3116 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003117 Uri data = intent.getData();
3118 if (data != null) {
3119 String pkg = data.getSchemeSpecificPart();
3120 if (pkg != null) {
3121 pkgList = new String[]{pkg};
3122 }
3123 }
3124 }
3125 if (pkgList != null && (pkgList.length > 0)) {
3126 for (String pkg : pkgList) {
3127 removeLocked(pkg);
Christopher Tate1590f1e2014-10-02 17:27:57 -07003128 mPriorities.remove(pkg);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003129 for (int i=mBroadcastStats.size()-1; i>=0; i--) {
3130 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
3131 if (uidStats.remove(pkg) != null) {
3132 if (uidStats.size() <= 0) {
3133 mBroadcastStats.removeAt(i);
3134 }
3135 }
3136 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003137 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138 }
3139 }
3140 }
3141 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003142
3143 final class UidObserver extends IUidObserver.Stub {
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003144 @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003145 }
3146
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003147 @Override public void onUidGone(int uid, boolean disabled) {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003148 synchronized (mLock) {
3149 if (disabled) {
Dianne Hackborne07641d2016-11-09 15:07:23 -08003150 removeForStoppedLocked(uid);
3151 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003152 mForegroundUids.delete(uid);
Dianne Hackborne07641d2016-11-09 15:07:23 -08003153 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003154 }
3155
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003156 @Override public void onUidActive(int uid) {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003157 synchronized (mLock) {
3158 if (!mForegroundUids.get(uid)) {
3159 mForegroundUids.put(uid, true);
3160 sendPendingBackgroundAlarmsLocked(uid, null);
3161 }
3162 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003163 }
3164
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003165 @Override public void onUidIdle(int uid, boolean disabled) {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003166 synchronized (mLock) {
3167 if (disabled) {
Dianne Hackborne07641d2016-11-09 15:07:23 -08003168 removeForStoppedLocked(uid);
3169 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003170 mForegroundUids.delete(uid);
Dianne Hackbornde9c48b2015-11-20 14:49:59 -08003171 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003172 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003173
3174 @Override public void onUidCachedChanged(int uid, boolean cached) {
3175 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003176 };
3177
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003178 private final class AppOpsWatcher extends IAppOpsCallback.Stub {
3179 @Override
3180 public void opChanged(int op, int uid, String packageName) throws RemoteException {
3181 synchronized (mLock) {
3182 final int mode = mAppOpsService.checkOperation(op, uid, packageName);
3183 if (DEBUG_BG_LIMIT) {
3184 Slog.d(TAG,
3185 "Appop changed for " + uid + ", " + packageName + " to " + mode);
3186 }
3187 final boolean changed;
3188 if (mode != AppOpsManager.MODE_ALLOWED) {
3189 changed = mForcedAppStandbyPackages.add(packageName);
3190 } else {
3191 changed = mForcedAppStandbyPackages.remove(packageName);
3192 }
3193 if (changed && mode == AppOpsManager.MODE_ALLOWED) {
3194 sendPendingBackgroundAlarmsLocked(uid, packageName);
3195 }
3196 }
3197 }
3198 }
3199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003200 private final BroadcastStats getStatsLocked(PendingIntent pi) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003201 String pkg = pi.getCreatorPackage();
3202 int uid = pi.getCreatorUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07003203 return getStatsLocked(uid, pkg);
3204 }
3205
3206 private final BroadcastStats getStatsLocked(int uid, String pkgName) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003207 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
3208 if (uidStats == null) {
3209 uidStats = new ArrayMap<String, BroadcastStats>();
3210 mBroadcastStats.put(uid, uidStats);
3211 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003212 BroadcastStats bs = uidStats.get(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 if (bs == null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003214 bs = new BroadcastStats(uid, pkgName);
3215 uidStats.put(pkgName, bs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003216 }
3217 return bs;
3218 }
Dianne Hackborn81038902012-11-26 17:04:09 -08003219
Christopher Tate21e9f192017-08-08 13:49:11 -07003220 /**
3221 * Canonical count of (operation.send() - onSendFinished()) and
3222 * listener send/complete/timeout invocations.
3223 * Guarded by the usual lock.
3224 */
3225 @GuardedBy("mLock")
3226 private int mSendCount = 0;
3227 @GuardedBy("mLock")
Christopher Tateeabba732017-08-17 17:12:52 -07003228 private int mSendFinishCount = 0;
3229 @GuardedBy("mLock")
Christopher Tate21e9f192017-08-08 13:49:11 -07003230 private int mListenerCount = 0;
Christopher Tateeabba732017-08-17 17:12:52 -07003231 @GuardedBy("mLock")
3232 private int mListenerFinishCount = 0;
Christopher Tate21e9f192017-08-08 13:49:11 -07003233
Christopher Tate14a7bb02015-10-01 10:24:31 -07003234 class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished {
Christopher Tate21e9f192017-08-08 13:49:11 -07003235
Christopher Tate14a7bb02015-10-01 10:24:31 -07003236 private InFlight removeLocked(PendingIntent pi, Intent intent) {
3237 for (int i = 0; i < mInFlight.size(); i++) {
Christopher Tatedb9ae422017-08-21 11:24:30 -07003238 if (mInFlight.get(i).mPendingIntent == pi) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003239 return mInFlight.remove(i);
3240 }
3241 }
3242 mLog.w("No in-flight alarm for " + pi + " " + intent);
3243 return null;
3244 }
3245
3246 private InFlight removeLocked(IBinder listener) {
3247 for (int i = 0; i < mInFlight.size(); i++) {
3248 if (mInFlight.get(i).mListener == listener) {
3249 return mInFlight.remove(i);
3250 }
3251 }
3252 mLog.w("No in-flight alarm for listener " + listener);
3253 return null;
3254 }
3255
3256 private void updateStatsLocked(InFlight inflight) {
3257 final long nowELAPSED = SystemClock.elapsedRealtime();
3258 BroadcastStats bs = inflight.mBroadcastStats;
3259 bs.nesting--;
3260 if (bs.nesting <= 0) {
3261 bs.nesting = 0;
3262 bs.aggregateTime += nowELAPSED - bs.startTime;
3263 }
3264 FilterStats fs = inflight.mFilterStats;
3265 fs.nesting--;
3266 if (fs.nesting <= 0) {
3267 fs.nesting = 0;
3268 fs.aggregateTime += nowELAPSED - fs.startTime;
3269 }
3270 if (RECORD_ALARMS_IN_HISTORY) {
3271 if (inflight.mWorkSource != null && inflight.mWorkSource.size() > 0) {
3272 for (int wi=0; wi<inflight.mWorkSource.size(); wi++) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003273 ActivityManager.noteAlarmFinish(
Christopher Tate14a7bb02015-10-01 10:24:31 -07003274 inflight.mPendingIntent, inflight.mWorkSource.get(wi), inflight.mTag);
3275 }
3276 } else {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003277 ActivityManager.noteAlarmFinish(
Christopher Tate14a7bb02015-10-01 10:24:31 -07003278 inflight.mPendingIntent, inflight.mUid, inflight.mTag);
3279 }
3280 }
3281 }
3282
3283 private void updateTrackingLocked(InFlight inflight) {
3284 if (inflight != null) {
3285 updateStatsLocked(inflight);
3286 }
3287 mBroadcastRefCount--;
Makoto Onuki3e7d8452017-03-02 15:33:17 -08003288 if (DEBUG_WAKELOCK) {
3289 Slog.d(TAG, "mBroadcastRefCount -> " + mBroadcastRefCount);
3290 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003291 if (mBroadcastRefCount == 0) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003292 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07003293 mWakeLock.release();
3294 if (mInFlight.size() > 0) {
3295 mLog.w("Finished all dispatches with " + mInFlight.size()
3296 + " remaining inflights");
3297 for (int i=0; i<mInFlight.size(); i++) {
3298 mLog.w(" Remaining #" + i + ": " + mInFlight.get(i));
3299 }
3300 mInFlight.clear();
3301 }
3302 } else {
3303 // the next of our alarms is now in flight. reattribute the wakelock.
3304 if (mInFlight.size() > 0) {
3305 InFlight inFlight = mInFlight.get(0);
3306 setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
3307 inFlight.mAlarmType, inFlight.mTag, -1, false);
3308 } else {
3309 // should never happen
3310 mLog.w("Alarm wakelock still held but sent queue empty");
3311 mWakeLock.setWorkSource(null);
3312 }
3313 }
3314 }
3315
3316 /**
3317 * Callback that arrives when a direct-call alarm reports that delivery has finished
3318 */
3319 @Override
3320 public void alarmComplete(IBinder who) {
3321 if (who == null) {
Christopher Tate21e9f192017-08-08 13:49:11 -07003322 mLog.w("Invalid alarmComplete: uid=" + Binder.getCallingUid()
Christopher Tate14a7bb02015-10-01 10:24:31 -07003323 + " pid=" + Binder.getCallingPid());
3324 return;
3325 }
3326
3327 final long ident = Binder.clearCallingIdentity();
3328 try {
3329 synchronized (mLock) {
3330 mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who);
3331 InFlight inflight = removeLocked(who);
3332 if (inflight != null) {
3333 if (DEBUG_LISTENER_CALLBACK) {
3334 Slog.i(TAG, "alarmComplete() from " + who);
3335 }
3336 updateTrackingLocked(inflight);
Christopher Tateeabba732017-08-17 17:12:52 -07003337 mListenerFinishCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003338 } else {
3339 // Delivery timed out, and the timeout handling already took care of
3340 // updating our tracking here, so we needn't do anything further.
3341 if (DEBUG_LISTENER_CALLBACK) {
3342 Slog.i(TAG, "Late alarmComplete() from " + who);
3343 }
3344 }
3345 }
3346 } finally {
3347 Binder.restoreCallingIdentity(ident);
3348 }
3349 }
3350
3351 /**
3352 * Callback that arrives when a PendingIntent alarm has finished delivery
3353 */
3354 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003355 public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
3356 String resultData, Bundle resultExtras) {
3357 synchronized (mLock) {
Christopher Tateeabba732017-08-17 17:12:52 -07003358 mSendFinishCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003359 updateTrackingLocked(removeLocked(pi, intent));
3360 }
3361 }
3362
3363 /**
3364 * Timeout of a direct-call alarm delivery
3365 */
3366 public void alarmTimedOut(IBinder who) {
3367 synchronized (mLock) {
3368 InFlight inflight = removeLocked(who);
Dianne Hackborn81038902012-11-26 17:04:09 -08003369 if (inflight != null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003370 // TODO: implement ANR policy for the target
3371 if (DEBUG_LISTENER_CALLBACK) {
3372 Slog.i(TAG, "Alarm listener " + who + " timed out in delivery");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003373 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003374 updateTrackingLocked(inflight);
Christopher Tateeabba732017-08-17 17:12:52 -07003375 mListenerFinishCount++;
Dianne Hackborn81038902012-11-26 17:04:09 -08003376 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003377 if (DEBUG_LISTENER_CALLBACK) {
3378 Slog.i(TAG, "Spurious timeout of listener " + who);
3379 }
Christopher Tate21e9f192017-08-08 13:49:11 -07003380 mLog.w("Spurious timeout of listener " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003381 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003382 }
3383 }
3384
3385 /**
3386 * Deliver an alarm and set up the post-delivery handling appropriately
3387 */
3388 public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
3389 if (alarm.operation != null) {
3390 // PendingIntent alarm
Christopher Tate21e9f192017-08-08 13:49:11 -07003391 mSendCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003392 try {
3393 alarm.operation.send(getContext(), 0,
3394 mBackgroundIntent.putExtra(
3395 Intent.EXTRA_ALARM_COUNT, alarm.count),
3396 mDeliveryTracker, mHandler, null,
3397 allowWhileIdle ? mIdleOptions : null);
3398 } catch (PendingIntent.CanceledException e) {
3399 if (alarm.repeatInterval > 0) {
3400 // This IntentSender is no longer valid, but this
3401 // is a repeating alarm, so toss it
3402 removeImpl(alarm.operation);
3403 }
Christopher Tate7f2a0352015-12-08 10:24:33 -08003404 // No actual delivery was possible, so the delivery tracker's
3405 // 'finished' callback won't be invoked. We also don't need
3406 // to do any wakelock or stats tracking, so we have nothing
3407 // left to do here but go on to the next thing.
Christopher Tateeabba732017-08-17 17:12:52 -07003408 mSendFinishCount++;
Christopher Tate7f2a0352015-12-08 10:24:33 -08003409 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003410 }
3411 } else {
3412 // Direct listener callback alarm
Christopher Tate21e9f192017-08-08 13:49:11 -07003413 mListenerCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003414 try {
3415 if (DEBUG_LISTENER_CALLBACK) {
3416 Slog.v(TAG, "Alarm to uid=" + alarm.uid
3417 + " listener=" + alarm.listener.asBinder());
3418 }
3419 alarm.listener.doAlarm(this);
3420 mHandler.sendMessageDelayed(
3421 mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
3422 alarm.listener.asBinder()),
3423 mConstants.LISTENER_TIMEOUT);
3424 } catch (Exception e) {
3425 if (DEBUG_LISTENER_CALLBACK) {
3426 Slog.i(TAG, "Alarm undeliverable to listener "
3427 + alarm.listener.asBinder(), e);
3428 }
Christopher Tate7f2a0352015-12-08 10:24:33 -08003429 // As in the PendingIntent.CanceledException case, delivery of the
3430 // alarm was not possible, so we have no wakelock or timeout or
3431 // stats management to do. It threw before we posted the delayed
3432 // timeout message, so we're done here.
Christopher Tateeabba732017-08-17 17:12:52 -07003433 mListenerFinishCount++;
Christopher Tate7f2a0352015-12-08 10:24:33 -08003434 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003435 }
3436 }
3437
3438 // The alarm is now in flight; now arrange wakelock and stats tracking
Makoto Onuki3e7d8452017-03-02 15:33:17 -08003439 if (DEBUG_WAKELOCK) {
3440 Slog.d(TAG, "mBroadcastRefCount -> " + (mBroadcastRefCount + 1));
3441 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003442 if (mBroadcastRefCount == 0) {
3443 setWakelockWorkSource(alarm.operation, alarm.workSource,
3444 alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1,
3445 true);
3446 mWakeLock.acquire();
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003447 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07003448 }
3449 final InFlight inflight = new InFlight(AlarmManagerService.this,
3450 alarm.operation, alarm.listener, alarm.workSource, alarm.uid,
3451 alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
3452 mInFlight.add(inflight);
3453 mBroadcastRefCount++;
3454
3455 if (allowWhileIdle) {
3456 // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
3457 mLastAllowWhileIdleDispatch.put(alarm.uid, nowELAPSED);
3458 if (RECORD_DEVICE_IDLE_ALARMS) {
3459 IdleDispatchEntry ent = new IdleDispatchEntry();
3460 ent.uid = alarm.uid;
3461 ent.pkg = alarm.packageName;
3462 ent.tag = alarm.statsTag;
3463 ent.op = "DELIVER";
3464 ent.elapsedRealtime = nowELAPSED;
3465 mAllowWhileIdleDispatches.add(ent);
3466 }
3467 }
3468
3469 final BroadcastStats bs = inflight.mBroadcastStats;
3470 bs.count++;
3471 if (bs.nesting == 0) {
3472 bs.nesting = 1;
3473 bs.startTime = nowELAPSED;
3474 } else {
3475 bs.nesting++;
3476 }
3477 final FilterStats fs = inflight.mFilterStats;
3478 fs.count++;
3479 if (fs.nesting == 0) {
3480 fs.nesting = 1;
3481 fs.startTime = nowELAPSED;
3482 } else {
3483 fs.nesting++;
3484 }
3485 if (alarm.type == ELAPSED_REALTIME_WAKEUP
3486 || alarm.type == RTC_WAKEUP) {
3487 bs.numWakeup++;
3488 fs.numWakeup++;
3489 if (alarm.workSource != null && alarm.workSource.size() > 0) {
3490 for (int wi=0; wi<alarm.workSource.size(); wi++) {
Christopher Tate0029f572016-06-14 10:16:28 -07003491 final String wsName = alarm.workSource.getName(wi);
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003492 ActivityManager.noteWakeupAlarm(
Christopher Tate14a7bb02015-10-01 10:24:31 -07003493 alarm.operation, alarm.workSource.get(wi),
Christopher Tate0029f572016-06-14 10:16:28 -07003494 (wsName != null) ? wsName : alarm.packageName,
3495 alarm.statsTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08003496 }
Christopher Tatec4a07d12012-04-06 14:19:13 -07003497 } else {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003498 ActivityManager.noteWakeupAlarm(
Joe Onorato78bcdf92016-05-09 10:10:29 -07003499 alarm.operation, alarm.uid, alarm.packageName, alarm.statsTag);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003500 }
3501 }
3502 }
3503 }
3504}