blob: 5f449fefef1bb3d008377d285e6772b6d60c1dd5 [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
Suprabh Shukla75edab12018-01-29 14:09:06 -080019import android.annotation.UserIdInt;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080020import android.app.Activity;
Adrian Roosc42a1e12014-07-07 23:35:53 +020021import android.app.ActivityManager;
Christopher Tate57ceaaa2013-07-19 16:30:43 -070022import android.app.AlarmManager;
Christopher Tate14a7bb02015-10-01 10:24:31 -070023import android.app.AppOpsManager;
Dianne Hackborna750a632015-06-16 17:18:23 -070024import android.app.BroadcastOptions;
Christopher Tate14a7bb02015-10-01 10:24:31 -070025import android.app.IAlarmCompleteListener;
26import android.app.IAlarmListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.app.IAlarmManager;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070028import android.app.IUidObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.app.PendingIntent;
Suprabh Shukla75edab12018-01-29 14:09:06 -080030import android.app.usage.UsageStatsManager;
31import android.app.usage.UsageStatsManagerInternal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.content.BroadcastReceiver;
Dianne Hackborna750a632015-06-16 17:18:23 -070033import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.content.Context;
35import android.content.Intent;
36import android.content.IntentFilter;
Christopher Tatebb9cce52017-04-18 14:19:43 -070037import android.content.pm.ApplicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.content.pm.PackageManager;
Christopher Tatebb9cce52017-04-18 14:19:43 -070039import android.content.pm.PackageManager.NameNotFoundException;
40import android.content.pm.PermissionInfo;
Dianne Hackborna750a632015-06-16 17:18:23 -070041import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.net.Uri;
43import android.os.Binder;
44import android.os.Bundle;
Christopher Tate247571462017-04-10 11:45:05 -070045import android.os.Environment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.os.Handler;
Adam Lesinski182f73f2013-12-05 16:48:06 -080047import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.os.Message;
49import android.os.PowerManager;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -070050import android.os.Process;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070051import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.os.SystemClock;
53import android.os.SystemProperties;
Tim Murray175c0f92017-11-28 15:01:04 -080054import android.os.Trace;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070055import android.os.UserHandle;
Christopher Tatec4a07d12012-04-06 14:19:13 -070056import android.os.WorkSource;
Adrian Roosc42a1e12014-07-07 23:35:53 +020057import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.text.TextUtils;
Adrian Roosc42a1e12014-07-07 23:35:53 +020059import android.text.format.DateFormat;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080060import android.util.ArrayMap;
Suprabh Shukla92994ab2018-01-31 17:39:30 -080061import android.util.ArraySet;
Dianne Hackborna750a632015-06-16 17:18:23 -070062import android.util.KeyValueListParser;
Adrian Roosc42a1e12014-07-07 23:35:53 +020063import android.util.Log;
Suprabh Shukla75edab12018-01-29 14:09:06 -080064import android.util.Pair;
Joe Onorato8a9b2202010-02-26 18:56:32 -080065import android.util.Slog;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080066import android.util.SparseArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +020067import android.util.SparseBooleanArray;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -070068import android.util.SparseLongArray;
Dianne Hackborn043fcd92010-10-06 14:27:34 -070069import android.util.TimeUtils;
Kweku Adams61e03292017-10-19 14:27:12 -070070import android.util.proto.ProtoOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071
Christopher Tate4cb338d2013-07-26 13:11:31 -070072import java.io.ByteArrayOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import java.io.FileDescriptor;
74import java.io.PrintWriter;
Dianne Hackborn043fcd92010-10-06 14:27:34 -070075import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import java.util.ArrayList;
Dianne Hackborn81038902012-11-26 17:04:09 -080077import java.util.Arrays;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import java.util.Calendar;
79import java.util.Collections;
80import java.util.Comparator;
Mike Lockwood1f7b4132009-11-20 15:12:51 -050081import java.util.Date;
Christopher Tate1590f1e2014-10-02 17:27:57 -070082import java.util.HashMap;
Christopher Tate18a75f12013-07-01 18:18:59 -070083import java.util.LinkedList;
Adrian Roosc42a1e12014-07-07 23:35:53 +020084import java.util.Locale;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -070085import java.util.Random;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import java.util.TimeZone;
John Spurlock604a5ee2015-06-01 12:27:22 -040087import java.util.TreeSet;
Makoto Onuki2206af32017-11-21 16:25:35 -080088import java.util.function.Predicate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089
Suprabh Shuklac25447d2018-01-19 16:43:35 -080090import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE;
Christopher Tatee0a22b32013-07-11 14:43:13 -070091import static android.app.AlarmManager.RTC_WAKEUP;
92import static android.app.AlarmManager.RTC;
93import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
94import static android.app.AlarmManager.ELAPSED_REALTIME;
95
Christopher Tate21e9f192017-08-08 13:49:11 -070096import com.android.internal.annotations.GuardedBy;
Makoto Onuki2206af32017-11-21 16:25:35 -080097import com.android.internal.annotations.VisibleForTesting;
Makoto Onuki5d93b832018-01-10 16:12:39 -080098import com.android.internal.util.ArrayUtils;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060099import com.android.internal.util.DumpUtils;
Dianne Hackborn81038902012-11-26 17:04:09 -0800100import com.android.internal.util.LocalLog;
Makoto Onuki2206af32017-11-21 16:25:35 -0800101import com.android.server.ForceAppStandbyTracker.Listener;
Dianne Hackborn81038902012-11-26 17:04:09 -0800102
Makoto Onuki2206af32017-11-21 16:25:35 -0800103/**
104 * Alarm manager implementaion.
105 *
106 * Unit test:
107 atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java
108 */
Adam Lesinski182f73f2013-12-05 16:48:06 -0800109class AlarmManagerService extends SystemService {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700110 private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
111 private static final int RTC_MASK = 1 << RTC;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800112 private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700113 private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800114 static final int TIME_CHANGED_MASK = 1 << 16;
115 static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
Christopher Tateb8849c12011-02-08 13:39:01 -0800116
Christopher Tatee0a22b32013-07-11 14:43:13 -0700117 // Mask for testing whether a given alarm type is wakeup vs non-wakeup
Adam Lesinski182f73f2013-12-05 16:48:06 -0800118 static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
Christopher Tateb8849c12011-02-08 13:39:01 -0800119
Adam Lesinski182f73f2013-12-05 16:48:06 -0800120 static final String TAG = "AlarmManager";
Adam Lesinski182f73f2013-12-05 16:48:06 -0800121 static final boolean localLOGV = false;
122 static final boolean DEBUG_BATCH = localLOGV || false;
123 static final boolean DEBUG_VALIDATE = localLOGV || false;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200124 static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700125 static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
Makoto Onuki3e7d8452017-03-02 15:33:17 -0800126 static final boolean DEBUG_WAKELOCK = localLOGV || false;
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700127 static final boolean DEBUG_BG_LIMIT = localLOGV || false;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800128 static final boolean DEBUG_STANDBY = localLOGV || false;
Dianne Hackborn1e383822015-04-10 14:02:33 -0700129 static final boolean RECORD_ALARMS_IN_HISTORY = true;
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700130 static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800131 static final int ALARM_EVENT = 1;
132 static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
Adrian Roosc42a1e12014-07-07 23:35:53 +0200133
Christopher Tate14a7bb02015-10-01 10:24:31 -0700134 private final Intent mBackgroundIntent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800136 static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700137
Adam Lesinski182f73f2013-12-05 16:48:06 -0800138 static final boolean WAKEUP_STATS = false;
Christopher Tate18a75f12013-07-01 18:18:59 -0700139
Christopher Tate24cd46f2016-02-02 14:28:01 -0800140 private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT =
141 new Intent(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)
Christopher Tate50191db2017-05-09 16:02:25 -0700142 .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
143 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Adrian Roosc42a1e12014-07-07 23:35:53 +0200144
Adam Lesinski182f73f2013-12-05 16:48:06 -0800145 final LocalLog mLog = new LocalLog(TAG);
Dianne Hackborn81038902012-11-26 17:04:09 -0800146
Christopher Tate14a7bb02015-10-01 10:24:31 -0700147 AppOpsManager mAppOps;
Dianne Hackborn627dfa12015-11-11 18:10:30 -0800148 DeviceIdleController.LocalService mLocalDeviceIdleController;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800149 private UsageStatsManagerInternal mUsageStatsManagerInternal;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700150
Adam Lesinski182f73f2013-12-05 16:48:06 -0800151 final Object mLock = new Object();
Dianne Hackborn81038902012-11-26 17:04:09 -0800152
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700153 // List of alarms per uid deferred due to user applied background restrictions on the source app
154 SparseArray<ArrayList<Alarm>> mPendingBackgroundAlarms = new SparseArray<>();
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -0800155 long mNativeData;
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800156 private long mNextWakeup;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700157 private long mNextNonWakeup;
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -0700158 private long mLastWakeupSet;
159 private long mLastWakeup;
Christopher Tate12cf0b62018-01-05 18:40:14 -0800160 private long mLastTickSet;
161 private long mLastTickIssued; // elapsed
162 private long mLastTickReceived;
Makoto Onuki5d93b832018-01-10 16:12:39 -0800163 private long mLastTickAdded;
164 private long mLastTickRemoved;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800165 int mBroadcastRefCount = 0;
166 PowerManager.WakeLock mWakeLock;
Dianne Hackborna1bd7922014-03-21 11:07:11 -0700167 boolean mLastWakeLockUnimportantForLogging;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700168 ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
169 ArrayList<InFlight> mInFlight = new ArrayList<>();
Adam Lesinski182f73f2013-12-05 16:48:06 -0800170 final AlarmHandler mHandler = new AlarmHandler();
171 ClockReceiver mClockReceiver;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700172 InteractiveStateReceiver mInteractiveStateReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 private UninstallReceiver mUninstallReceiver;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700174 final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
Adam Lesinski182f73f2013-12-05 16:48:06 -0800175 PendingIntent mTimeTickSender;
176 PendingIntent mDateChangeSender;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700177 Random mRandom;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700178 boolean mInteractive = true;
179 long mNonInteractiveStartTime;
180 long mNonInteractiveTime;
181 long mLastAlarmDeliveryTime;
182 long mStartCurrentDelayTime;
183 long mNextNonWakeupDeliveryTime;
Dianne Hackbornc3527222015-05-13 14:03:20 -0700184 long mLastTimeChangeClockTime;
185 long mLastTimeChangeRealtime;
Dianne Hackborn998e6082014-09-11 19:13:23 -0700186 int mNumTimeChanged;
Dianne Hackborn81038902012-11-26 17:04:09 -0800187
Christopher Tatebb9cce52017-04-18 14:19:43 -0700188 // Bookkeeping about the identity of the "System UI" package, determined at runtime.
189
190 /**
191 * This permission must be defined by the canonical System UI package,
192 * with protection level "signature".
193 */
194 private static final String SYSTEM_UI_SELF_PERMISSION =
195 "android.permission.systemui.IDENTITY";
196
197 /**
198 * At boot we use SYSTEM_UI_SELF_PERMISSION to look up the definer's uid.
199 */
200 int mSystemUiUid;
201
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700202 /**
203 * For each uid, this is the last time we dispatched an "allow while idle" alarm,
Kweku Adams61e03292017-10-19 14:27:12 -0700204 * used to determine the earliest we can dispatch the next such alarm. Times are in the
205 * 'elapsed' timebase.
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700206 */
207 final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
208
Suprabh Shuklac25447d2018-01-19 16:43:35 -0800209 /**
210 * For each uid, we store whether the last allow-while-idle alarm was dispatched while
211 * the uid was in foreground or not. We will use the allow_while_idle_short_time in such cases.
212 */
213 final SparseBooleanArray mUseAllowWhileIdleShortTime = new SparseBooleanArray();
214
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700215 final static class IdleDispatchEntry {
216 int uid;
217 String pkg;
218 String tag;
219 String op;
220 long elapsedRealtime;
221 long argRealtime;
222 }
223 final ArrayList<IdleDispatchEntry> mAllowWhileIdleDispatches = new ArrayList();
224
Suprabh Shukla75edab12018-01-29 14:09:06 -0800225 interface Stats {
226 int REBATCH_ALL_ALARMS = 0;
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800227 int REORDER_ALARMS_FOR_STANDBY = 1;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800228 }
229
230 private final StatLogger mStatLogger = new StatLogger(new String[] {
231 "REBATCH_ALL_ALARMS",
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800232 "REORDER_ALARMS_FOR_STANDBY",
Suprabh Shukla75edab12018-01-29 14:09:06 -0800233 });
234
Dianne Hackborna750a632015-06-16 17:18:23 -0700235 /**
236 * Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
237 */
238 Bundle mIdleOptions;
239
Jose Lima235510e2014-08-13 12:50:01 -0700240 private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
241 new SparseArray<>();
242 private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
243 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200244 private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
245 new SparseBooleanArray();
246 private boolean mNextAlarmClockMayChange;
247
248 // May only use on mHandler's thread, locking not required.
Jose Lima235510e2014-08-13 12:50:01 -0700249 private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
250 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200251
Makoto Onuki2206af32017-11-21 16:25:35 -0800252 private final ForceAppStandbyTracker mForceAppStandbyTracker;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800253 private boolean mAppStandbyParole;
254 private ArrayMap<Pair<String, Integer>, Long> mLastAlarmDeliveredForPackage = new ArrayMap<>();
Makoto Onuki2206af32017-11-21 16:25:35 -0800255
Dianne Hackborna750a632015-06-16 17:18:23 -0700256 /**
257 * All times are in milliseconds. These constants are kept synchronized with the system
258 * global Settings. Any access to this class or its fields should be done while
259 * holding the AlarmManagerService.mLock lock.
260 */
261 private final class Constants extends ContentObserver {
262 // Key names stored in the settings value.
263 private static final String KEY_MIN_FUTURITY = "min_futurity";
264 private static final String KEY_MIN_INTERVAL = "min_interval";
265 private static final String KEY_ALLOW_WHILE_IDLE_SHORT_TIME = "allow_while_idle_short_time";
266 private static final String KEY_ALLOW_WHILE_IDLE_LONG_TIME = "allow_while_idle_long_time";
267 private static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
268 = "allow_while_idle_whitelist_duration";
Christopher Tate14a7bb02015-10-01 10:24:31 -0700269 private static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
Dianne Hackborna750a632015-06-16 17:18:23 -0700270
Suprabh Shukla75edab12018-01-29 14:09:06 -0800271 // Keys for specifying throttling delay based on app standby bucketing
272 private final String[] KEYS_APP_STANDBY_DELAY = {
273 "standby_active_delay",
274 "standby_working_delay",
275 "standby_frequent_delay",
276 "standby_rare_delay",
277 "standby_never_delay",
278 };
279
Dianne Hackborna750a632015-06-16 17:18:23 -0700280 private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
281 private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
Christopher Tateaa244da2015-08-27 15:57:57 -0700282 private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
Dianne Hackborn7682b262015-10-26 17:51:57 -0700283 private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000;
Dianne Hackborna750a632015-06-16 17:18:23 -0700284 private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700285 private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800286 private final long[] DEFAULT_APP_STANDBY_DELAYS = {
287 0, // Active
288 6 * 60_000, // Working
289 30 * 60_000, // Frequent
290 2 * 60 * 60_000, // Rare
291 10 * 24 * 60 * 60_000 // Never
292 };
Christopher Tate14a7bb02015-10-01 10:24:31 -0700293
Dianne Hackborna750a632015-06-16 17:18:23 -0700294 // Minimum futurity of a new alarm
295 public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
296
297 // Minimum alarm recurrence interval
298 public long MIN_INTERVAL = DEFAULT_MIN_INTERVAL;
299
300 // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
301 public long ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME;
302
303 // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
304 public long ALLOW_WHILE_IDLE_LONG_TIME = DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME;
305
306 // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
307 public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
308 = DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
309
Christopher Tate14a7bb02015-10-01 10:24:31 -0700310 // Direct alarm listener callback timeout
311 public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
312
Suprabh Shukla75edab12018-01-29 14:09:06 -0800313 public long[] APP_STANDBY_MIN_DELAYS = new long[DEFAULT_APP_STANDBY_DELAYS.length];
314
Dianne Hackborna750a632015-06-16 17:18:23 -0700315 private ContentResolver mResolver;
316 private final KeyValueListParser mParser = new KeyValueListParser(',');
317 private long mLastAllowWhileIdleWhitelistDuration = -1;
318
319 public Constants(Handler handler) {
320 super(handler);
Dianne Hackborna750a632015-06-16 17:18:23 -0700321 updateAllowWhileIdleWhitelistDurationLocked();
322 }
323
324 public void start(ContentResolver resolver) {
325 mResolver = resolver;
326 mResolver.registerContentObserver(Settings.Global.getUriFor(
327 Settings.Global.ALARM_MANAGER_CONSTANTS), false, this);
328 updateConstants();
329 }
330
Dianne Hackborna750a632015-06-16 17:18:23 -0700331 public void updateAllowWhileIdleWhitelistDurationLocked() {
332 if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
333 mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
334 BroadcastOptions opts = BroadcastOptions.makeBasic();
335 opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
336 mIdleOptions = opts.toBundle();
337 }
338 }
339
340 @Override
341 public void onChange(boolean selfChange, Uri uri) {
342 updateConstants();
343 }
344
345 private void updateConstants() {
346 synchronized (mLock) {
347 try {
348 mParser.setString(Settings.Global.getString(mResolver,
349 Settings.Global.ALARM_MANAGER_CONSTANTS));
350 } catch (IllegalArgumentException e) {
351 // Failed to parse the settings string, log this and move on
352 // with defaults.
Dianne Hackborn0ef403e2017-01-24 18:22:15 -0800353 Slog.e(TAG, "Bad alarm manager settings", e);
Dianne Hackborna750a632015-06-16 17:18:23 -0700354 }
355
356 MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
357 MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
358 ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
359 DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
360 ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME,
361 DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
362 ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong(
363 KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
364 DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700365 LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
366 DEFAULT_LISTENER_TIMEOUT);
Suprabh Shukla75edab12018-01-29 14:09:06 -0800367 APP_STANDBY_MIN_DELAYS[0] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[0],
368 DEFAULT_APP_STANDBY_DELAYS[0]);
369 for (int i = 1; i < KEYS_APP_STANDBY_DELAY.length; i++) {
370 APP_STANDBY_MIN_DELAYS[i] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[i],
371 Math.max(APP_STANDBY_MIN_DELAYS[i-1], DEFAULT_APP_STANDBY_DELAYS[i]));
372 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700373 updateAllowWhileIdleWhitelistDurationLocked();
374 }
375 }
376
377 void dump(PrintWriter pw) {
378 pw.println(" Settings:");
379
380 pw.print(" "); pw.print(KEY_MIN_FUTURITY); pw.print("=");
381 TimeUtils.formatDuration(MIN_FUTURITY, pw);
382 pw.println();
383
384 pw.print(" "); pw.print(KEY_MIN_INTERVAL); pw.print("=");
385 TimeUtils.formatDuration(MIN_INTERVAL, pw);
386 pw.println();
387
Christopher Tate14a7bb02015-10-01 10:24:31 -0700388 pw.print(" "); pw.print(KEY_LISTENER_TIMEOUT); pw.print("=");
389 TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
390 pw.println();
391
Dianne Hackborna750a632015-06-16 17:18:23 -0700392 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME); pw.print("=");
393 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw);
394 pw.println();
395
396 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME); pw.print("=");
397 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw);
398 pw.println();
399
400 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); pw.print("=");
401 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
402 pw.println();
Suprabh Shukla75edab12018-01-29 14:09:06 -0800403
404 for (int i = 0; i < KEYS_APP_STANDBY_DELAY.length; i++) {
405 pw.print(" "); pw.print(KEYS_APP_STANDBY_DELAY[i]); pw.print("=");
406 TimeUtils.formatDuration(APP_STANDBY_MIN_DELAYS[i], pw);
407 pw.println();
408 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700409 }
Kweku Adams61e03292017-10-19 14:27:12 -0700410
411 void dumpProto(ProtoOutputStream proto, long fieldId) {
412 final long token = proto.start(fieldId);
413
414 proto.write(ConstantsProto.MIN_FUTURITY_DURATION_MS, MIN_FUTURITY);
415 proto.write(ConstantsProto.MIN_INTERVAL_DURATION_MS, MIN_INTERVAL);
416 proto.write(ConstantsProto.LISTENER_TIMEOUT_DURATION_MS, LISTENER_TIMEOUT);
417 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_SHORT_DURATION_MS,
418 ALLOW_WHILE_IDLE_SHORT_TIME);
419 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_LONG_DURATION_MS,
420 ALLOW_WHILE_IDLE_LONG_TIME);
421 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_WHITELIST_DURATION_MS,
422 ALLOW_WHILE_IDLE_WHITELIST_DURATION);
423
424 proto.end(token);
425 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700426 }
427
428 final Constants mConstants;
429
Christopher Tate1590f1e2014-10-02 17:27:57 -0700430 // Alarm delivery ordering bookkeeping
431 static final int PRIO_TICK = 0;
432 static final int PRIO_WAKEUP = 1;
433 static final int PRIO_NORMAL = 2;
434
Dianne Hackborna750a632015-06-16 17:18:23 -0700435 final class PriorityClass {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700436 int seq;
437 int priority;
438
439 PriorityClass() {
440 seq = mCurrentSeq - 1;
441 priority = PRIO_NORMAL;
442 }
443 }
444
Dianne Hackborna750a632015-06-16 17:18:23 -0700445 final HashMap<String, PriorityClass> mPriorities = new HashMap<>();
Christopher Tate1590f1e2014-10-02 17:27:57 -0700446 int mCurrentSeq = 0;
447
Dianne Hackborna750a632015-06-16 17:18:23 -0700448 static final class WakeupEvent {
Christopher Tate18a75f12013-07-01 18:18:59 -0700449 public long when;
450 public int uid;
451 public String action;
452
453 public WakeupEvent(long theTime, int theUid, String theAction) {
454 when = theTime;
455 uid = theUid;
456 action = theAction;
457 }
458 }
459
Adam Lesinski182f73f2013-12-05 16:48:06 -0800460 final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
461 final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
Christopher Tate18a75f12013-07-01 18:18:59 -0700462
Adrian Roosc42a1e12014-07-07 23:35:53 +0200463 final class Batch {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700464 long start; // These endpoints are always in ELAPSED
465 long end;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700466 int flags; // Flags for alarms, such as FLAG_STANDALONE.
Christopher Tatee0a22b32013-07-11 14:43:13 -0700467
468 final ArrayList<Alarm> alarms = new ArrayList<Alarm>();
469
470 Batch() {
471 start = 0;
472 end = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700473 flags = 0;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700474 }
475
476 Batch(Alarm seed) {
477 start = seed.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700478 end = seed.maxWhenElapsed;
479 flags = seed.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700480 alarms.add(seed);
Makoto Onuki5d93b832018-01-10 16:12:39 -0800481 if (seed.operation == mTimeTickSender) {
482 mLastTickAdded = System.currentTimeMillis();
483 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700484 }
485
486 int size() {
487 return alarms.size();
488 }
489
490 Alarm get(int index) {
491 return alarms.get(index);
492 }
493
494 boolean canHold(long whenElapsed, long maxWhen) {
495 return (end >= whenElapsed) && (start <= maxWhen);
496 }
497
498 boolean add(Alarm alarm) {
499 boolean newStart = false;
500 // narrows the batch if necessary; presumes that canHold(alarm) is true
501 int index = Collections.binarySearch(alarms, alarm, sIncreasingTimeOrder);
502 if (index < 0) {
503 index = 0 - index - 1;
504 }
505 alarms.add(index, alarm);
Makoto Onuki5d93b832018-01-10 16:12:39 -0800506 if (alarm.operation == mTimeTickSender) {
507 mLastTickAdded = System.currentTimeMillis();
508 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700509 if (DEBUG_BATCH) {
510 Slog.v(TAG, "Adding " + alarm + " to " + this);
511 }
512 if (alarm.whenElapsed > start) {
513 start = alarm.whenElapsed;
514 newStart = true;
515 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700516 if (alarm.maxWhenElapsed < end) {
517 end = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700518 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700519 flags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700520
521 if (DEBUG_BATCH) {
522 Slog.v(TAG, " => now " + this);
523 }
524 return newStart;
525 }
526
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800527 boolean remove(Alarm alarm) {
528 return remove(a -> (a == alarm));
529 }
530
Christopher Tate1d99c392017-12-07 16:54:04 -0800531 boolean remove(Predicate<Alarm> predicate) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700532 boolean didRemove = false;
533 long newStart = 0; // recalculate endpoints as we go
534 long newEnd = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700535 int newFlags = 0;
Christopher Tateae269d52013-09-26 13:11:55 -0700536 for (int i = 0; i < alarms.size(); ) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700537 Alarm alarm = alarms.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -0800538 if (predicate.test(alarm)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700539 alarms.remove(i);
540 didRemove = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200541 if (alarm.alarmClock != null) {
542 mNextAlarmClockMayChange = true;
543 }
Makoto Onuki5d93b832018-01-10 16:12:39 -0800544 if (alarm.operation == mTimeTickSender) {
545 mLastTickRemoved = System.currentTimeMillis();
546 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700547 } else {
548 if (alarm.whenElapsed > newStart) {
549 newStart = alarm.whenElapsed;
550 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700551 if (alarm.maxWhenElapsed < newEnd) {
552 newEnd = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700553 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700554 newFlags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700555 i++;
556 }
557 }
558 if (didRemove) {
559 // commit the new batch bounds
560 start = newStart;
561 end = newEnd;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700562 flags = newFlags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700563 }
564 return didRemove;
565 }
566
Christopher Tatee0a22b32013-07-11 14:43:13 -0700567 boolean hasPackage(final String packageName) {
568 final int N = alarms.size();
569 for (int i = 0; i < N; i++) {
570 Alarm a = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700571 if (a.matches(packageName)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700572 return true;
573 }
574 }
575 return false;
576 }
577
578 boolean hasWakeups() {
579 final int N = alarms.size();
580 for (int i = 0; i < N; i++) {
581 Alarm a = alarms.get(i);
582 // non-wakeup alarms are types 1 and 3, i.e. have the low bit set
583 if ((a.type & TYPE_NONWAKEUP_MASK) == 0) {
584 return true;
585 }
586 }
587 return false;
588 }
589
590 @Override
591 public String toString() {
592 StringBuilder b = new StringBuilder(40);
593 b.append("Batch{"); b.append(Integer.toHexString(this.hashCode()));
594 b.append(" num="); b.append(size());
595 b.append(" start="); b.append(start);
596 b.append(" end="); b.append(end);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700597 if (flags != 0) {
598 b.append(" flgs=0x");
599 b.append(Integer.toHexString(flags));
Christopher Tatee0a22b32013-07-11 14:43:13 -0700600 }
601 b.append('}');
602 return b.toString();
603 }
Kweku Adams61e03292017-10-19 14:27:12 -0700604
605 public void writeToProto(ProtoOutputStream proto, long fieldId, long nowElapsed,
606 long nowRTC) {
607 final long token = proto.start(fieldId);
608
609 proto.write(BatchProto.START_REALTIME, start);
610 proto.write(BatchProto.END_REALTIME, end);
611 proto.write(BatchProto.FLAGS, flags);
612 for (Alarm a : alarms) {
613 a.writeToProto(proto, BatchProto.ALARMS, nowElapsed, nowRTC);
614 }
615
616 proto.end(token);
617 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700618 }
619
620 static class BatchTimeOrder implements Comparator<Batch> {
621 public int compare(Batch b1, Batch b2) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800622 long when1 = b1.start;
623 long when2 = b2.start;
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800624 if (when1 > when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700625 return 1;
626 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800627 if (when1 < when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700628 return -1;
629 }
630 return 0;
631 }
632 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800633
634 final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
635 @Override
636 public int compare(Alarm lhs, Alarm rhs) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700637 // priority class trumps everything. TICK < WAKEUP < NORMAL
638 if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
639 return -1;
640 } else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
641 return 1;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800642 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700643
644 // within each class, sort by nominal delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800645 if (lhs.whenElapsed < rhs.whenElapsed) {
646 return -1;
647 } else if (lhs.whenElapsed > rhs.whenElapsed) {
648 return 1;
649 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700650
651 // same priority class + same target delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800652 return 0;
653 }
654 };
655
Christopher Tate1590f1e2014-10-02 17:27:57 -0700656 void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
657 final int N = alarms.size();
658 for (int i = 0; i < N; i++) {
659 Alarm a = alarms.get(i);
660
661 final int alarmPrio;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700662 if (a.operation != null
663 && Intent.ACTION_TIME_TICK.equals(a.operation.getIntent().getAction())) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700664 alarmPrio = PRIO_TICK;
665 } else if (a.wakeup) {
666 alarmPrio = PRIO_WAKEUP;
667 } else {
668 alarmPrio = PRIO_NORMAL;
669 }
670
671 PriorityClass packagePrio = a.priorityClass;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800672 String alarmPackage = a.sourcePackage;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700673 if (packagePrio == null) packagePrio = mPriorities.get(alarmPackage);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700674 if (packagePrio == null) {
675 packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
Christopher Tate14a7bb02015-10-01 10:24:31 -0700676 mPriorities.put(alarmPackage, packagePrio);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700677 }
678 a.priorityClass = packagePrio;
679
680 if (packagePrio.seq != mCurrentSeq) {
681 // first alarm we've seen in the current delivery generation from this package
682 packagePrio.priority = alarmPrio;
683 packagePrio.seq = mCurrentSeq;
684 } else {
685 // Multiple alarms from this package being delivered in this generation;
686 // bump the package's delivery class if it's warranted.
687 // TICK < WAKEUP < NORMAL
688 if (alarmPrio < packagePrio.priority) {
689 packagePrio.priority = alarmPrio;
690 }
691 }
692 }
693 }
694
Christopher Tatee0a22b32013-07-11 14:43:13 -0700695 // minimum recurrence period or alarm futurity for us to be able to fuzz it
Adam Lesinski182f73f2013-12-05 16:48:06 -0800696 static final long MIN_FUZZABLE_INTERVAL = 10000;
697 static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700698 final ArrayList<Batch> mAlarmBatches = new ArrayList<>();
699
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700700 // 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 -0700701 // to run during this time are placed in mPendingWhileIdleAlarms
702 Alarm mPendingIdleUntil = null;
Dianne Hackbornf70faed2015-04-21 14:11:38 -0700703 Alarm mNextWakeFromIdle = null;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700704 ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
Christopher Tatee0a22b32013-07-11 14:43:13 -0700705
Jeff Brownb880d882014-02-10 19:47:07 -0800706 public AlarmManagerService(Context context) {
707 super(context);
Dianne Hackborna750a632015-06-16 17:18:23 -0700708 mConstants = new Constants(mHandler);
Makoto Onuki2206af32017-11-21 16:25:35 -0800709
710 mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
711 mForceAppStandbyTracker.addListener(mForceAppStandbyListener);
Christopher Tate1d99c392017-12-07 16:54:04 -0800712
713 publishLocalService(AlarmManagerInternal.class, new LocalService());
Jeff Brownb880d882014-02-10 19:47:07 -0800714 }
715
Christopher Tatee0a22b32013-07-11 14:43:13 -0700716 static long convertToElapsed(long when, int type) {
717 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
718 if (isRtc) {
719 when -= System.currentTimeMillis() - SystemClock.elapsedRealtime();
720 }
721 return when;
722 }
723
724 // Apply a heuristic to { recurrence interval, futurity of the trigger time } to
725 // calculate the end of our nominal delivery window for the alarm.
726 static long maxTriggerTime(long now, long triggerAtTime, long interval) {
727 // Current heuristic: batchable window is 75% of either the recurrence interval
728 // [for a periodic alarm] or of the time from now to the desired delivery time,
729 // with a minimum delay/interval of 10 seconds, under which we will simply not
730 // defer the alarm.
731 long futurity = (interval == 0)
732 ? (triggerAtTime - now)
733 : interval;
Christopher Tate57ceaaa2013-07-19 16:30:43 -0700734 if (futurity < MIN_FUZZABLE_INTERVAL) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700735 futurity = 0;
736 }
737 return triggerAtTime + (long)(.75 * futurity);
738 }
739
740 // returns true if the batch was added at the head
741 static boolean addBatchLocked(ArrayList<Batch> list, Batch newBatch) {
742 int index = Collections.binarySearch(list, newBatch, sBatchOrder);
743 if (index < 0) {
744 index = 0 - index - 1;
745 }
746 list.add(index, newBatch);
747 return (index == 0);
748 }
749
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800750 private void insertAndBatchAlarmLocked(Alarm alarm) {
751 final int whichBatch = ((alarm.flags & AlarmManager.FLAG_STANDALONE) != 0) ? -1
752 : attemptCoalesceLocked(alarm.whenElapsed, alarm.maxWhenElapsed);
753
754 if (whichBatch < 0) {
755 addBatchLocked(mAlarmBatches, new Batch(alarm));
756 } else {
757 final Batch batch = mAlarmBatches.get(whichBatch);
758 if (batch.add(alarm)) {
759 // The start time of this batch advanced, so batch ordering may
760 // have just been broken. Move it to where it now belongs.
761 mAlarmBatches.remove(whichBatch);
762 addBatchLocked(mAlarmBatches, batch);
763 }
764 }
765 }
766
Christopher Tate385e4982013-07-23 18:22:29 -0700767 // Return the index of the matching batch, or -1 if none found.
768 int attemptCoalesceLocked(long whenElapsed, long maxWhen) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700769 final int N = mAlarmBatches.size();
770 for (int i = 0; i < N; i++) {
771 Batch b = mAlarmBatches.get(i);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700772 if ((b.flags&AlarmManager.FLAG_STANDALONE) == 0 && b.canHold(whenElapsed, maxWhen)) {
Christopher Tate385e4982013-07-23 18:22:29 -0700773 return i;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700774 }
775 }
Christopher Tate385e4982013-07-23 18:22:29 -0700776 return -1;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700777 }
Makoto Onuki5d93b832018-01-10 16:12:39 -0800778 /** @return total count of the alarms in a set of alarm batches. */
779 static int getAlarmCount(ArrayList<Batch> batches) {
780 int ret = 0;
781
782 final int size = batches.size();
783 for (int i = 0; i < size; i++) {
784 ret += batches.get(i).size();
785 }
786 return ret;
787 }
788
789 boolean haveAlarmsTimeTickAlarm(ArrayList<Alarm> alarms) {
790 if (alarms.size() == 0) {
791 return false;
792 }
793 final int batchSize = alarms.size();
794 for (int j = 0; j < batchSize; j++) {
795 if (alarms.get(j).operation == mTimeTickSender) {
796 return true;
797 }
798 }
799 return false;
800 }
801
802 boolean haveBatchesTimeTickAlarm(ArrayList<Batch> batches) {
803 final int numBatches = batches.size();
804 for (int i = 0; i < numBatches; i++) {
805 if (haveAlarmsTimeTickAlarm(batches.get(i).alarms)) {
806 return true;
807 }
808 }
809 return false;
810 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700811
812 // The RTC clock has moved arbitrarily, so we need to recalculate all the batching
813 void rebatchAllAlarms() {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700814 synchronized (mLock) {
Christopher Tate4cb338d2013-07-26 13:11:31 -0700815 rebatchAllAlarmsLocked(true);
816 }
817 }
818
819 void rebatchAllAlarmsLocked(boolean doValidate) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800820 final long start = mStatLogger.getTime();
Makoto Onuki5d93b832018-01-10 16:12:39 -0800821 final int oldCount =
822 getAlarmCount(mAlarmBatches) + ArrayUtils.size(mPendingWhileIdleAlarms);
823 final boolean oldHasTick = haveBatchesTimeTickAlarm(mAlarmBatches)
824 || haveAlarmsTimeTickAlarm(mPendingWhileIdleAlarms);
825
Christopher Tate4cb338d2013-07-26 13:11:31 -0700826 ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone();
827 mAlarmBatches.clear();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700828 Alarm oldPendingIdleUntil = mPendingIdleUntil;
Christopher Tate4cb338d2013-07-26 13:11:31 -0700829 final long nowElapsed = SystemClock.elapsedRealtime();
830 final int oldBatches = oldSet.size();
831 for (int batchNum = 0; batchNum < oldBatches; batchNum++) {
832 Batch batch = oldSet.get(batchNum);
833 final int N = batch.size();
834 for (int i = 0; i < N; i++) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700835 reAddAlarmLocked(batch.get(i), nowElapsed, doValidate);
Christopher Tatee0a22b32013-07-11 14:43:13 -0700836 }
837 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700838 if (oldPendingIdleUntil != null && oldPendingIdleUntil != mPendingIdleUntil) {
839 Slog.wtf(TAG, "Rebatching: idle until changed from " + oldPendingIdleUntil
840 + " to " + mPendingIdleUntil);
841 if (mPendingIdleUntil == null) {
842 // Somehow we lost this... we need to restore all of the pending alarms.
843 restorePendingWhileIdleAlarmsLocked();
844 }
845 }
Makoto Onuki5d93b832018-01-10 16:12:39 -0800846 final int newCount =
847 getAlarmCount(mAlarmBatches) + ArrayUtils.size(mPendingWhileIdleAlarms);
848 final boolean newHasTick = haveBatchesTimeTickAlarm(mAlarmBatches)
849 || haveAlarmsTimeTickAlarm(mPendingWhileIdleAlarms);
850
851 if (oldCount != newCount) {
852 Slog.wtf(TAG, "Rebatching: total count changed from " + oldCount + " to " + newCount);
853 }
854 if (oldHasTick != newHasTick) {
855 Slog.wtf(TAG, "Rebatching: hasTick changed from " + oldHasTick + " to " + newHasTick);
856 }
857
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700858 rescheduleKernelAlarmsLocked();
859 updateNextAlarmClockLocked();
Suprabh Shukla75edab12018-01-29 14:09:06 -0800860 mStatLogger.logDurationStat(Stats.REBATCH_ALL_ALARMS, start);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700861 }
862
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800863 /**
864 * Re-orders the alarm batches based on newly evaluated send times based on the current
865 * app-standby buckets
866 * @param targetPackages [Package, User] pairs for which alarms need to be re-evaluated,
867 * null indicates all
868 * @return True if there was any reordering done to the current list.
869 */
870 boolean reorderAlarmsBasedOnStandbyBuckets(ArraySet<Pair<String, Integer>> targetPackages) {
871 final long start = mStatLogger.getTime();
872 final ArrayList<Alarm> rescheduledAlarms = new ArrayList<>();
873
874 for (int batchIndex = mAlarmBatches.size() - 1; batchIndex >= 0; batchIndex--) {
875 final Batch batch = mAlarmBatches.get(batchIndex);
876 for (int alarmIndex = batch.size() - 1; alarmIndex >= 0; alarmIndex--) {
877 final Alarm alarm = batch.get(alarmIndex);
878 final Pair<String, Integer> packageUser =
879 Pair.create(alarm.sourcePackage, UserHandle.getUserId(alarm.creatorUid));
880 if (targetPackages != null && !targetPackages.contains(packageUser)) {
881 continue;
882 }
883 if (adjustDeliveryTimeBasedOnStandbyBucketLocked(alarm)) {
884 batch.remove(alarm);
885 rescheduledAlarms.add(alarm);
886 }
887 }
888 if (batch.size() == 0) {
889 mAlarmBatches.remove(batchIndex);
890 }
891 }
892 for (int i = 0; i < rescheduledAlarms.size(); i++) {
893 final Alarm a = rescheduledAlarms.get(i);
894 insertAndBatchAlarmLocked(a);
895 }
896
897 mStatLogger.logDurationStat(Stats.REORDER_ALARMS_FOR_STANDBY, start);
898 return rescheduledAlarms.size() > 0;
899 }
900
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700901 void reAddAlarmLocked(Alarm a, long nowElapsed, boolean doValidate) {
902 a.when = a.origWhen;
903 long whenElapsed = convertToElapsed(a.when, a.type);
904 final long maxElapsed;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700905 if (a.windowLength == AlarmManager.WINDOW_EXACT) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700906 // Exact
907 maxElapsed = whenElapsed;
908 } else {
909 // Not exact. Preserve any explicit window, otherwise recalculate
910 // the window based on the alarm's new futurity. Note that this
911 // reflects a policy of preferring timely to deferred delivery.
912 maxElapsed = (a.windowLength > 0)
913 ? (whenElapsed + a.windowLength)
914 : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
915 }
916 a.whenElapsed = whenElapsed;
917 a.maxWhenElapsed = maxElapsed;
918 setImplLocked(a, true, doValidate);
919 }
920
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700921 /**
922 * Sends alarms that were blocked due to user applied background restrictions - either because
923 * the user lifted those or the uid came to foreground.
924 *
925 * @param uid uid to filter on
926 * @param packageName package to filter on, or null for all packages in uid
927 */
928 void sendPendingBackgroundAlarmsLocked(int uid, String packageName) {
929 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(uid);
930 if (alarmsForUid == null || alarmsForUid.size() == 0) {
931 return;
932 }
933 final ArrayList<Alarm> alarmsToDeliver;
934 if (packageName != null) {
935 if (DEBUG_BG_LIMIT) {
936 Slog.d(TAG, "Sending blocked alarms for uid " + uid + ", package " + packageName);
937 }
938 alarmsToDeliver = new ArrayList<>();
939 for (int i = alarmsForUid.size() - 1; i >= 0; i--) {
940 final Alarm a = alarmsForUid.get(i);
941 if (a.matches(packageName)) {
942 alarmsToDeliver.add(alarmsForUid.remove(i));
943 }
944 }
945 if (alarmsForUid.size() == 0) {
946 mPendingBackgroundAlarms.remove(uid);
947 }
948 } else {
949 if (DEBUG_BG_LIMIT) {
950 Slog.d(TAG, "Sending blocked alarms for uid " + uid);
951 }
952 alarmsToDeliver = alarmsForUid;
953 mPendingBackgroundAlarms.remove(uid);
954 }
955 deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, SystemClock.elapsedRealtime());
956 }
957
Makoto Onuki2206af32017-11-21 16:25:35 -0800958 /**
959 * Check all alarms in {@link #mPendingBackgroundAlarms} and send the ones that are not
960 * restricted.
961 *
962 * This is only called when the global "force all apps-standby" flag changes or when the
963 * power save whitelist changes, so it's okay to be slow.
964 */
965 void sendAllUnrestrictedPendingBackgroundAlarmsLocked() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700966 final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
Makoto Onuki2206af32017-11-21 16:25:35 -0800967
968 findAllUnrestrictedPendingBackgroundAlarmsLockedInner(
969 mPendingBackgroundAlarms, alarmsToDeliver, this::isBackgroundRestricted);
970
971 if (alarmsToDeliver.size() > 0) {
972 deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, SystemClock.elapsedRealtime());
973 }
974 }
975
976 @VisibleForTesting
977 static void findAllUnrestrictedPendingBackgroundAlarmsLockedInner(
978 SparseArray<ArrayList<Alarm>> pendingAlarms, ArrayList<Alarm> unrestrictedAlarms,
979 Predicate<Alarm> isBackgroundRestricted) {
980
981 for (int uidIndex = pendingAlarms.size() - 1; uidIndex >= 0; uidIndex--) {
982 final int uid = pendingAlarms.keyAt(uidIndex);
983 final ArrayList<Alarm> alarmsForUid = pendingAlarms.valueAt(uidIndex);
984
985 for (int alarmIndex = alarmsForUid.size() - 1; alarmIndex >= 0; alarmIndex--) {
986 final Alarm alarm = alarmsForUid.get(alarmIndex);
987
988 if (isBackgroundRestricted.test(alarm)) {
989 continue;
990 }
991
992 unrestrictedAlarms.add(alarm);
993 alarmsForUid.remove(alarmIndex);
994 }
995
996 if (alarmsForUid.size() == 0) {
997 pendingAlarms.removeAt(uidIndex);
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700998 }
999 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001000 }
1001
1002 private void deliverPendingBackgroundAlarmsLocked(ArrayList<Alarm> alarms, long nowELAPSED) {
1003 final int N = alarms.size();
1004 boolean hasWakeup = false;
1005 for (int i = 0; i < N; i++) {
1006 final Alarm alarm = alarms.get(i);
1007 if (alarm.wakeup) {
1008 hasWakeup = true;
1009 }
1010 alarm.count = 1;
1011 // Recurring alarms may have passed several alarm intervals while the
1012 // alarm was kept pending. Send the appropriate trigger count.
1013 if (alarm.repeatInterval > 0) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08001014 alarm.count += (nowELAPSED - alarm.requestedWhenElapsed) / alarm.repeatInterval;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001015 // Also schedule its next recurrence
1016 final long delta = alarm.count * alarm.repeatInterval;
1017 final long nextElapsed = alarm.whenElapsed + delta;
1018 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
1019 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
1020 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
1021 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
1022 // Kernel alarms will be rescheduled as needed in setImplLocked
1023 }
1024 }
1025 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
1026 // No need to wakeup for non wakeup alarms
1027 if (mPendingNonWakeupAlarms.size() == 0) {
1028 mStartCurrentDelayTime = nowELAPSED;
1029 mNextNonWakeupDeliveryTime = nowELAPSED
1030 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
1031 }
1032 mPendingNonWakeupAlarms.addAll(alarms);
1033 mNumDelayedAlarms += alarms.size();
1034 } else {
1035 if (DEBUG_BG_LIMIT) {
1036 Slog.d(TAG, "Waking up to deliver pending blocked alarms");
1037 }
1038 // Since we are waking up, also deliver any pending non wakeup alarms we have.
1039 if (mPendingNonWakeupAlarms.size() > 0) {
1040 alarms.addAll(mPendingNonWakeupAlarms);
1041 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
1042 mTotalDelayTime += thisDelayTime;
1043 if (mMaxDelayTime < thisDelayTime) {
1044 mMaxDelayTime = thisDelayTime;
1045 }
1046 mPendingNonWakeupAlarms.clear();
1047 }
1048 calculateDeliveryPriorities(alarms);
1049 Collections.sort(alarms, mAlarmDispatchComparator);
1050 deliverAlarmsLocked(alarms, nowELAPSED);
1051 }
1052 }
1053
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001054 void restorePendingWhileIdleAlarmsLocked() {
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001055 if (RECORD_DEVICE_IDLE_ALARMS) {
1056 IdleDispatchEntry ent = new IdleDispatchEntry();
1057 ent.uid = 0;
1058 ent.pkg = "FINISH IDLE";
1059 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1060 mAllowWhileIdleDispatches.add(ent);
1061 }
1062
Dianne Hackborn35d54032015-04-23 10:30:43 -07001063 // Bring pending alarms back into the main list.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001064 if (mPendingWhileIdleAlarms.size() > 0) {
1065 ArrayList<Alarm> alarms = mPendingWhileIdleAlarms;
1066 mPendingWhileIdleAlarms = new ArrayList<>();
1067 final long nowElapsed = SystemClock.elapsedRealtime();
1068 for (int i=alarms.size() - 1; i >= 0; i--) {
1069 Alarm a = alarms.get(i);
1070 reAddAlarmLocked(a, nowElapsed, false);
1071 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001072 }
Dianne Hackborn35d54032015-04-23 10:30:43 -07001073
1074 // Reschedule everything.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001075 rescheduleKernelAlarmsLocked();
1076 updateNextAlarmClockLocked();
Dianne Hackborn35d54032015-04-23 10:30:43 -07001077
1078 // And send a TIME_TICK right now, since it is important to get the UI updated.
1079 try {
1080 mTimeTickSender.send();
1081 } catch (PendingIntent.CanceledException e) {
1082 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001083 }
1084
Christopher Tate14a7bb02015-10-01 10:24:31 -07001085 static final class InFlight {
Dianne Hackborn81038902012-11-26 17:04:09 -08001086 final PendingIntent mPendingIntent;
Christopher Tateeabba732017-08-17 17:12:52 -07001087 final long mWhenElapsed;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001088 final IBinder mListener;
David Christieebe51fc2013-07-26 13:23:29 -07001089 final WorkSource mWorkSource;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001090 final int mUid;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001091 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001092 final BroadcastStats mBroadcastStats;
1093 final FilterStats mFilterStats;
Dianne Hackborne5167ca2014-03-08 14:39:10 -08001094 final int mAlarmType;
Dianne Hackborn81038902012-11-26 17:04:09 -08001095
Christopher Tate14a7bb02015-10-01 10:24:31 -07001096 InFlight(AlarmManagerService service, PendingIntent pendingIntent, IAlarmListener listener,
1097 WorkSource workSource, int uid, String alarmPkg, int alarmType, String tag,
1098 long nowELAPSED) {
Dianne Hackborn81038902012-11-26 17:04:09 -08001099 mPendingIntent = pendingIntent;
Christopher Tateeabba732017-08-17 17:12:52 -07001100 mWhenElapsed = nowELAPSED;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001101 mListener = listener != null ? listener.asBinder() : null;
David Christieebe51fc2013-07-26 13:23:29 -07001102 mWorkSource = workSource;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001103 mUid = uid;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001104 mTag = tag;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001105 mBroadcastStats = (pendingIntent != null)
1106 ? service.getStatsLocked(pendingIntent)
1107 : service.getStatsLocked(uid, alarmPkg);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001108 FilterStats fs = mBroadcastStats.filterStats.get(mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08001109 if (fs == null) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001110 fs = new FilterStats(mBroadcastStats, mTag);
1111 mBroadcastStats.filterStats.put(mTag, fs);
Dianne Hackborn81038902012-11-26 17:04:09 -08001112 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001113 fs.lastTime = nowELAPSED;
Dianne Hackborn81038902012-11-26 17:04:09 -08001114 mFilterStats = fs;
Dianne Hackborne5167ca2014-03-08 14:39:10 -08001115 mAlarmType = alarmType;
Dianne Hackborn81038902012-11-26 17:04:09 -08001116 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001117
1118 @Override
1119 public String toString() {
1120 return "InFlight{"
1121 + "pendingIntent=" + mPendingIntent
Christopher Tateeabba732017-08-17 17:12:52 -07001122 + ", when=" + mWhenElapsed
Makoto Onuki33955e12017-03-01 18:11:00 -08001123 + ", workSource=" + mWorkSource
1124 + ", uid=" + mUid
1125 + ", tag=" + mTag
1126 + ", broadcastStats=" + mBroadcastStats
1127 + ", filterStats=" + mFilterStats
1128 + ", alarmType=" + mAlarmType
1129 + "}";
1130 }
Kweku Adams61e03292017-10-19 14:27:12 -07001131
1132 public void writeToProto(ProtoOutputStream proto, long fieldId) {
1133 final long token = proto.start(fieldId);
1134
1135 proto.write(InFlightProto.UID, mUid);
1136 proto.write(InFlightProto.TAG, mTag);
1137 proto.write(InFlightProto.WHEN_ELAPSED_MS, mWhenElapsed);
1138 proto.write(InFlightProto.ALARM_TYPE, mAlarmType);
1139 if (mPendingIntent != null) {
1140 mPendingIntent.writeToProto(proto, InFlightProto.PENDING_INTENT);
1141 }
1142 if (mBroadcastStats != null) {
1143 mBroadcastStats.writeToProto(proto, InFlightProto.BROADCAST_STATS);
1144 }
1145 if (mFilterStats != null) {
1146 mFilterStats.writeToProto(proto, InFlightProto.FILTER_STATS);
1147 }
1148 if (mWorkSource != null) {
1149 mWorkSource.writeToProto(proto, InFlightProto.WORK_SOURCE);
1150 }
1151
1152 proto.end(token);
1153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001155
Adam Lesinski182f73f2013-12-05 16:48:06 -08001156 static final class FilterStats {
Dianne Hackborn81038902012-11-26 17:04:09 -08001157 final BroadcastStats mBroadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001158 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001159
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001160 long lastTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 long aggregateTime;
Dianne Hackborn81038902012-11-26 17:04:09 -08001162 int count;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 int numWakeup;
1164 long startTime;
1165 int nesting;
Dianne Hackborn81038902012-11-26 17:04:09 -08001166
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001167 FilterStats(BroadcastStats broadcastStats, String tag) {
Dianne Hackborn81038902012-11-26 17:04:09 -08001168 mBroadcastStats = broadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001169 mTag = tag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001170 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001171
1172 @Override
1173 public String toString() {
1174 return "FilterStats{"
1175 + "tag=" + mTag
1176 + ", lastTime=" + lastTime
1177 + ", aggregateTime=" + aggregateTime
1178 + ", count=" + count
1179 + ", numWakeup=" + numWakeup
1180 + ", startTime=" + startTime
1181 + ", nesting=" + nesting
1182 + "}";
1183 }
Kweku Adams61e03292017-10-19 14:27:12 -07001184
1185 public void writeToProto(ProtoOutputStream proto, long fieldId) {
1186 final long token = proto.start(fieldId);
1187
1188 proto.write(FilterStatsProto.TAG, mTag);
1189 proto.write(FilterStatsProto.LAST_FLIGHT_TIME_REALTIME, lastTime);
1190 proto.write(FilterStatsProto.TOTAL_FLIGHT_DURATION_MS, aggregateTime);
1191 proto.write(FilterStatsProto.COUNT, count);
1192 proto.write(FilterStatsProto.WAKEUP_COUNT, numWakeup);
1193 proto.write(FilterStatsProto.START_TIME_REALTIME, startTime);
1194 proto.write(FilterStatsProto.NESTING, nesting);
1195
1196 proto.end(token);
1197 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001198 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001199
Adam Lesinski182f73f2013-12-05 16:48:06 -08001200 static final class BroadcastStats {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001201 final int mUid;
Dianne Hackborn81038902012-11-26 17:04:09 -08001202 final String mPackageName;
1203
1204 long aggregateTime;
1205 int count;
1206 int numWakeup;
1207 long startTime;
1208 int nesting;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001209 final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
Dianne Hackborn81038902012-11-26 17:04:09 -08001210
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001211 BroadcastStats(int uid, String packageName) {
1212 mUid = uid;
Dianne Hackborn81038902012-11-26 17:04:09 -08001213 mPackageName = packageName;
1214 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001215
1216 @Override
1217 public String toString() {
1218 return "BroadcastStats{"
1219 + "uid=" + mUid
1220 + ", packageName=" + mPackageName
1221 + ", aggregateTime=" + aggregateTime
1222 + ", count=" + count
1223 + ", numWakeup=" + numWakeup
1224 + ", startTime=" + startTime
1225 + ", nesting=" + nesting
1226 + "}";
1227 }
Kweku Adams61e03292017-10-19 14:27:12 -07001228
1229 public void writeToProto(ProtoOutputStream proto, long fieldId) {
1230 final long token = proto.start(fieldId);
1231
1232 proto.write(BroadcastStatsProto.UID, mUid);
1233 proto.write(BroadcastStatsProto.PACKAGE_NAME, mPackageName);
1234 proto.write(BroadcastStatsProto.TOTAL_FLIGHT_DURATION_MS, aggregateTime);
1235 proto.write(BroadcastStatsProto.COUNT, count);
1236 proto.write(BroadcastStatsProto.WAKEUP_COUNT, numWakeup);
1237 proto.write(BroadcastStatsProto.START_TIME_REALTIME, startTime);
1238 proto.write(BroadcastStatsProto.NESTING, nesting);
1239
1240 proto.end(token);
1241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001243
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001244 final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
1245 = new SparseArray<ArrayMap<String, BroadcastStats>>();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001246
1247 int mNumDelayedAlarms = 0;
1248 long mTotalDelayTime = 0;
1249 long mMaxDelayTime = 0;
1250
Adam Lesinski182f73f2013-12-05 16:48:06 -08001251 @Override
1252 public void onStart() {
Greg Hackmanna1d6f922013-12-09 16:56:53 -08001253 mNativeData = init();
Christopher Tate0dab4dc2014-12-16 12:14:06 -08001254 mNextWakeup = mNextNonWakeup = 0;
Robert CH Chou64ba8e42009-11-04 21:38:49 +08001255
1256 // We have to set current TimeZone info to kernel
1257 // because kernel doesn't keep this after reboot
Adam Lesinski182f73f2013-12-05 16:48:06 -08001258 setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
Robert CH Chou64ba8e42009-11-04 21:38:49 +08001259
Christopher Tate247571462017-04-10 11:45:05 -07001260 // Also sure that we're booting with a halfway sensible current time
1261 if (mNativeData != 0) {
1262 final long systemBuildTime = Environment.getRootDirectory().lastModified();
1263 if (System.currentTimeMillis() < systemBuildTime) {
1264 Slog.i(TAG, "Current time only " + System.currentTimeMillis()
1265 + ", advancing to build time " + systemBuildTime);
1266 setKernelTime(mNativeData, systemBuildTime);
1267 }
1268 }
1269
Christopher Tatebb9cce52017-04-18 14:19:43 -07001270 // Determine SysUI's uid
1271 final PackageManager packMan = getContext().getPackageManager();
1272 try {
1273 PermissionInfo sysUiPerm = packMan.getPermissionInfo(SYSTEM_UI_SELF_PERMISSION, 0);
1274 ApplicationInfo sysUi = packMan.getApplicationInfo(sysUiPerm.packageName, 0);
1275 if ((sysUi.privateFlags&ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
1276 mSystemUiUid = sysUi.uid;
1277 } else {
1278 Slog.e(TAG, "SysUI permission " + SYSTEM_UI_SELF_PERMISSION
1279 + " defined by non-privileged app " + sysUi.packageName
1280 + " - ignoring");
1281 }
1282 } catch (NameNotFoundException e) {
1283 }
1284
1285 if (mSystemUiUid <= 0) {
1286 Slog.wtf(TAG, "SysUI package not found!");
1287 }
1288
Adam Lesinski182f73f2013-12-05 16:48:06 -08001289 PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001290 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
Dianne Hackborna1f1a3c2014-02-24 18:12:28 -08001291
Adam Lesinski182f73f2013-12-05 16:48:06 -08001292 mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293 new Intent(Intent.ACTION_TIME_TICK).addFlags(
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07001294 Intent.FLAG_RECEIVER_REGISTERED_ONLY
Chad Brubaker291df4f2017-03-14 10:23:02 -07001295 | Intent.FLAG_RECEIVER_FOREGROUND
1296 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS), 0,
Dianne Hackborndb5aca92012-10-26 13:39:41 -07001297 UserHandle.ALL);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001298 Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
Chad Brubaker291df4f2017-03-14 10:23:02 -07001299 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
1300 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001301 mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
Dianne Hackborndb5aca92012-10-26 13:39:41 -07001302 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
Kweku Adams61e03292017-10-19 14:27:12 -07001303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304 // now that we have initied the driver schedule the alarm
Adam Lesinski182f73f2013-12-05 16:48:06 -08001305 mClockReceiver = new ClockReceiver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001306 mClockReceiver.scheduleTimeTickEvent();
1307 mClockReceiver.scheduleDateChangedEvent();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001308 mInteractiveStateReceiver = new InteractiveStateReceiver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001309 mUninstallReceiver = new UninstallReceiver();
Kweku Adams61e03292017-10-19 14:27:12 -07001310
Greg Hackmanna1d6f922013-12-09 16:56:53 -08001311 if (mNativeData != 0) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001312 AlarmThread waitThread = new AlarmThread();
1313 waitThread.start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001315 Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001317
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001318 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001319 ActivityManager.getService().registerUidObserver(new UidObserver(),
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001320 ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
1321 | ActivityManager.UID_OBSERVER_ACTIVE,
1322 ActivityManager.PROCESS_STATE_UNKNOWN, null);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001323 } catch (RemoteException e) {
1324 // ignored; both services live in system_server
1325 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001326 publishBinderService(Context.ALARM_SERVICE, mService);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001328
1329 @Override
Dianne Hackborna750a632015-06-16 17:18:23 -07001330 public void onBootPhase(int phase) {
1331 if (phase == PHASE_SYSTEM_SERVICES_READY) {
Suprabh Shukla4deb8522018-01-08 16:27:10 -08001332 mForceAppStandbyTracker.start();
Dianne Hackborna750a632015-06-16 17:18:23 -07001333 mConstants.start(getContext().getContentResolver());
Christopher Tate14a7bb02015-10-01 10:24:31 -07001334 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001335 mLocalDeviceIdleController
1336 = LocalServices.getService(DeviceIdleController.LocalService.class);
Suprabh Shukla75edab12018-01-29 14:09:06 -08001337 mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
1338 mUsageStatsManagerInternal.addAppIdleStateChangeListener(new AppStandbyTracker());
Dianne Hackborna750a632015-06-16 17:18:23 -07001339 }
1340 }
1341
1342 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 protected void finalize() throws Throwable {
1344 try {
Greg Hackmanna1d6f922013-12-09 16:56:53 -08001345 close(mNativeData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 } finally {
1347 super.finalize();
1348 }
1349 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001350
Adam Lesinski182f73f2013-12-05 16:48:06 -08001351 void setTimeZoneImpl(String tz) {
1352 if (TextUtils.isEmpty(tz)) {
1353 return;
David Christieebe51fc2013-07-26 13:23:29 -07001354 }
1355
Adam Lesinski182f73f2013-12-05 16:48:06 -08001356 TimeZone zone = TimeZone.getTimeZone(tz);
1357 // Prevent reentrant calls from stepping on each other when writing
1358 // the time zone property
1359 boolean timeZoneWasChanged = false;
1360 synchronized (this) {
1361 String current = SystemProperties.get(TIMEZONE_PROPERTY);
1362 if (current == null || !current.equals(zone.getID())) {
1363 if (localLOGV) {
1364 Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
1365 }
1366 timeZoneWasChanged = true;
1367 SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
1368 }
1369
1370 // Update the kernel timezone information
1371 // Kernel tracks time offsets as 'minutes west of GMT'
1372 int gmtOffset = zone.getOffset(System.currentTimeMillis());
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -08001373 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
Adam Lesinski182f73f2013-12-05 16:48:06 -08001374 }
1375
1376 TimeZone.setDefault(null);
1377
1378 if (timeZoneWasChanged) {
1379 Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
Chad Brubaker291df4f2017-03-14 10:23:02 -07001380 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
Christopher Tate5cdf9f82017-05-03 18:10:39 -07001381 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
Chad Brubaker291df4f2017-03-14 10:23:02 -07001382 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001383 intent.putExtra("time-zone", zone.getID());
1384 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
1385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001386 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001387
Adam Lesinski182f73f2013-12-05 16:48:06 -08001388 void removeImpl(PendingIntent operation) {
1389 if (operation == null) {
1390 return;
1391 }
1392 synchronized (mLock) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07001393 removeLocked(operation, null);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001394 }
1395 }
1396
1397 void setImpl(int type, long triggerAtTime, long windowLength, long interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001398 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1399 int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
1400 int callingUid, String callingPackage) {
1401 // must be *either* PendingIntent or AlarmReceiver, but not both
1402 if ((operation == null && directReceiver == null)
1403 || (operation != null && directReceiver != null)) {
1404 Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver");
1405 // NB: previous releases failed silently here, so we are continuing to do the same
1406 // rather than throw an IllegalArgumentException.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 return;
1408 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001409
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001410 // Sanity check the window length. This will catch people mistakenly
1411 // trying to pass an end-of-window timestamp rather than a duration.
1412 if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
1413 Slog.w(TAG, "Window length " + windowLength
1414 + "ms suspiciously long; limiting to 1 hour");
1415 windowLength = AlarmManager.INTERVAL_HOUR;
1416 }
1417
Christopher Tate498c6cb2014-11-17 16:09:27 -08001418 // Sanity check the recurrence interval. This will catch people who supply
1419 // seconds when the API expects milliseconds.
Dianne Hackborna750a632015-06-16 17:18:23 -07001420 final long minInterval = mConstants.MIN_INTERVAL;
1421 if (interval > 0 && interval < minInterval) {
Christopher Tate498c6cb2014-11-17 16:09:27 -08001422 Slog.w(TAG, "Suspiciously short interval " + interval
Dianne Hackborna750a632015-06-16 17:18:23 -07001423 + " millis; expanding to " + (minInterval/1000)
Christopher Tate498c6cb2014-11-17 16:09:27 -08001424 + " seconds");
Dianne Hackborna750a632015-06-16 17:18:23 -07001425 interval = minInterval;
Christopher Tate498c6cb2014-11-17 16:09:27 -08001426 }
1427
Christopher Tatee0a22b32013-07-11 14:43:13 -07001428 if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
1429 throw new IllegalArgumentException("Invalid alarm type " + type);
1430 }
1431
Christopher Tate5f221e82013-07-30 17:13:15 -07001432 if (triggerAtTime < 0) {
Christopher Tate5f221e82013-07-30 17:13:15 -07001433 final long what = Binder.getCallingPid();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001434 Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
Christopher Tate5f221e82013-07-30 17:13:15 -07001435 + " pid=" + what);
1436 triggerAtTime = 0;
1437 }
1438
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001439 final long nowElapsed = SystemClock.elapsedRealtime();
Christopher Tate498c6cb2014-11-17 16:09:27 -08001440 final long nominalTrigger = convertToElapsed(triggerAtTime, type);
1441 // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
Dianne Hackborna750a632015-06-16 17:18:23 -07001442 final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
Christopher Tate498c6cb2014-11-17 16:09:27 -08001443 final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
1444
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001445 final long maxElapsed;
1446 if (windowLength == AlarmManager.WINDOW_EXACT) {
1447 maxElapsed = triggerElapsed;
1448 } else if (windowLength < 0) {
1449 maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001450 // Fix this window in place, so that as time approaches we don't collapse it.
1451 windowLength = maxElapsed - triggerElapsed;
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001452 } else {
1453 maxElapsed = triggerElapsed + windowLength;
1454 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 synchronized (mLock) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07001457 if (DEBUG_BATCH) {
1458 Slog.v(TAG, "set(" + operation + ") : type=" + type
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001459 + " triggerAtTime=" + triggerAtTime + " win=" + windowLength
Christopher Tatee0a22b32013-07-11 14:43:13 -07001460 + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001461 + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 }
Christopher Tate3e04b472013-10-21 17:51:31 -07001463 setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001464 interval, operation, directReceiver, listenerTag, flags, true, workSource,
1465 alarmClock, callingUid, callingPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 }
1467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001468
Christopher Tate3e04b472013-10-21 17:51:31 -07001469 private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001470 long maxWhen, long interval, PendingIntent operation, IAlarmListener directReceiver,
1471 String listenerTag, int flags, boolean doValidate, WorkSource workSource,
1472 AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) {
Christopher Tate3e04b472013-10-21 17:51:31 -07001473 Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001474 operation, directReceiver, listenerTag, workSource, flags, alarmClock,
1475 callingUid, callingPackage);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001476 try {
Dianne Hackbornc3af19a2017-01-20 17:00:44 -08001477 if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001478 Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
1479 + " -- package not allowed to start");
1480 return;
1481 }
1482 } catch (RemoteException e) {
1483 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07001484 removeLocked(operation, directReceiver);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001485 setImplLocked(a, false, doValidate);
1486 }
Christopher Tateb8849c12011-02-08 13:39:01 -08001487
Suprabh Shukla75edab12018-01-29 14:09:06 -08001488 private long getMinDelayForBucketLocked(int bucket) {
1489 // Return the minimum time that should elapse before an app in the specified bucket
1490 // can receive alarms again
1491 if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) {
1492 return mConstants.APP_STANDBY_MIN_DELAYS[4];
1493 }
1494 else if (bucket >= UsageStatsManager.STANDBY_BUCKET_RARE) {
1495 return mConstants.APP_STANDBY_MIN_DELAYS[3];
1496 }
1497 else if (bucket >= UsageStatsManager.STANDBY_BUCKET_FREQUENT) {
1498 return mConstants.APP_STANDBY_MIN_DELAYS[2];
1499 }
1500 else if (bucket >= UsageStatsManager.STANDBY_BUCKET_WORKING_SET) {
1501 return mConstants.APP_STANDBY_MIN_DELAYS[1];
1502 }
1503 else return mConstants.APP_STANDBY_MIN_DELAYS[0];
1504 }
1505
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001506 /**
1507 * Adjusts the alarm delivery time based on the current app standby bucket.
1508 * @param alarm The alarm to adjust
1509 * @return true if the alarm delivery time was updated.
1510 * TODO: Reduce the number of calls to getAppStandbyBucket by batching the calls per
1511 * {package, user} pairs
1512 */
1513 private boolean adjustDeliveryTimeBasedOnStandbyBucketLocked(Alarm alarm) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08001514 if (alarm.alarmClock != null || UserHandle.isCore(alarm.creatorUid)) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001515 return false;
1516 }
1517 // TODO: short term fix for b/72816079, remove after a proper fix is in place
1518 if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
1519 return false;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001520 }
1521 if (mAppStandbyParole) {
1522 if (alarm.whenElapsed > alarm.requestedWhenElapsed) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001523 // We did defer this alarm earlier, restore original requirements
Suprabh Shukla75edab12018-01-29 14:09:06 -08001524 alarm.whenElapsed = alarm.requestedWhenElapsed;
1525 alarm.maxWhenElapsed = alarm.requestedMaxWhenElapsed;
1526 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001527 return true;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001528 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001529 final long oldWhenElapsed = alarm.whenElapsed;
1530 final long oldMaxWhenElapsed = alarm.maxWhenElapsed;
1531
Suprabh Shukla75edab12018-01-29 14:09:06 -08001532 final String sourcePackage = alarm.sourcePackage;
1533 final int sourceUserId = UserHandle.getUserId(alarm.creatorUid);
1534 final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket(
1535 sourcePackage, sourceUserId, SystemClock.elapsedRealtime());
1536
1537 final Pair<String, Integer> packageUser = Pair.create(sourcePackage, sourceUserId);
1538 final long lastElapsed = mLastAlarmDeliveredForPackage.getOrDefault(packageUser, 0L);
1539 if (lastElapsed > 0) {
1540 final long minElapsed = lastElapsed + getMinDelayForBucketLocked(standbyBucket);
1541 if (alarm.requestedWhenElapsed < minElapsed) {
1542 alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001543 } else {
1544 // app is now eligible to run alarms at the originally requested window.
1545 // Restore original requirements in case they were changed earlier.
1546 alarm.whenElapsed = alarm.requestedWhenElapsed;
1547 alarm.maxWhenElapsed = alarm.requestedMaxWhenElapsed;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001548 }
1549 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001550 return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed);
Suprabh Shukla75edab12018-01-29 14:09:06 -08001551 }
1552
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001553 private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
1554 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001555 // This is a special alarm that will put the system into idle until it goes off.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001556 // The caller has given the time they want this to happen at, however we need
1557 // to pull that earlier if there are existing alarms that have requested to
Dianne Hackbornf3831292015-10-15 14:51:06 -07001558 // bring us out of idle at an earlier time.
1559 if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001560 a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001561 }
1562 // Add fuzz to make the alarm go off some time before the actual desired time.
1563 final long nowElapsed = SystemClock.elapsedRealtime();
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001564 final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001565 if (fuzz > 0) {
1566 if (mRandom == null) {
1567 mRandom = new Random();
1568 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001569 final int delta = mRandom.nextInt(fuzz);
1570 a.whenElapsed -= delta;
1571 if (false) {
1572 Slog.d(TAG, "Alarm when: " + a.whenElapsed);
1573 Slog.d(TAG, "Delta until alarm: " + (a.whenElapsed-nowElapsed));
1574 Slog.d(TAG, "Applied fuzz: " + fuzz);
1575 Slog.d(TAG, "Final delta: " + delta);
1576 Slog.d(TAG, "Final when: " + a.whenElapsed);
1577 }
1578 a.when = a.maxWhenElapsed = a.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001579 }
1580
1581 } else if (mPendingIdleUntil != null) {
1582 // We currently have an idle until alarm scheduled; if the new alarm has
1583 // not explicitly stated it wants to run while idle, then put it on hold.
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001584 if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
1585 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
1586 | AlarmManager.FLAG_WAKE_FROM_IDLE))
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001587 == 0) {
1588 mPendingWhileIdleAlarms.add(a);
1589 return;
1590 }
1591 }
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001592 if (RECORD_DEVICE_IDLE_ALARMS) {
1593 if ((a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
1594 IdleDispatchEntry ent = new IdleDispatchEntry();
1595 ent.uid = a.uid;
1596 ent.pkg = a.operation.getCreatorPackage();
1597 ent.tag = a.operation.getTag("");
1598 ent.op = "SET";
1599 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1600 ent.argRealtime = a.whenElapsed;
1601 mAllowWhileIdleDispatches.add(ent);
1602 }
1603 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08001604 adjustDeliveryTimeBasedOnStandbyBucketLocked(a);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001605 insertAndBatchAlarmLocked(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001607 if (a.alarmClock != null) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001608 mNextAlarmClockMayChange = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +02001609 }
1610
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001611 boolean needRebatch = false;
1612
1613 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001614 if (RECORD_DEVICE_IDLE_ALARMS) {
1615 if (mPendingIdleUntil == null) {
1616 IdleDispatchEntry ent = new IdleDispatchEntry();
1617 ent.uid = 0;
1618 ent.pkg = "START IDLE";
1619 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1620 mAllowWhileIdleDispatches.add(ent);
1621 }
1622 }
Makoto Onuki4274a6d2017-04-21 12:21:25 -07001623 if ((mPendingIdleUntil != a) && (mPendingIdleUntil != null)) {
1624 Slog.wtfStack(TAG, "setImplLocked: idle until changed from " + mPendingIdleUntil
1625 + " to " + a);
1626 }
1627
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001628 mPendingIdleUntil = a;
1629 needRebatch = true;
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001630 } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
1631 if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
1632 mNextWakeFromIdle = a;
1633 // If this wake from idle is earlier than whatever was previously scheduled,
1634 // and we are currently idling, then we need to rebatch alarms in case the idle
1635 // until time needs to be updated.
1636 if (mPendingIdleUntil != null) {
1637 needRebatch = true;
1638 }
1639 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001640 }
1641
1642 if (!rebatching) {
1643 if (DEBUG_VALIDATE) {
1644 if (doValidate && !validateConsistencyLocked()) {
1645 Slog.v(TAG, "Tipping-point operation: type=" + a.type + " when=" + a.when
1646 + " when(hex)=" + Long.toHexString(a.when)
1647 + " whenElapsed=" + a.whenElapsed
1648 + " maxWhenElapsed=" + a.maxWhenElapsed
1649 + " interval=" + a.repeatInterval + " op=" + a.operation
1650 + " flags=0x" + Integer.toHexString(a.flags));
1651 rebatchAllAlarmsLocked(false);
1652 needRebatch = false;
1653 }
1654 }
1655
1656 if (needRebatch) {
Christopher Tate4cb338d2013-07-26 13:11:31 -07001657 rebatchAllAlarmsLocked(false);
Christopher Tate4cb338d2013-07-26 13:11:31 -07001658 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001659
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001660 rescheduleKernelAlarmsLocked();
1661 updateNextAlarmClockLocked();
1662 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001663 }
1664
Christopher Tate1d99c392017-12-07 16:54:04 -08001665 /**
1666 * System-process internal API
1667 */
1668 private final class LocalService implements AlarmManagerInternal {
1669 @Override
1670 public void removeAlarmsForUid(int uid) {
1671 synchronized (mLock) {
1672 removeLocked(uid);
1673 }
1674 }
1675 }
1676
1677 /**
1678 * Public-facing binder interface
1679 */
Adam Lesinski182f73f2013-12-05 16:48:06 -08001680 private final IBinder mService = new IAlarmManager.Stub() {
1681 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07001682 public void set(String callingPackage,
1683 int type, long triggerAtTime, long windowLength, long interval, int flags,
1684 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1685 WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001686 final int callingUid = Binder.getCallingUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07001687
1688 // make sure the caller is not lying about which package should be blamed for
1689 // wakelock time spent in alarm delivery
1690 mAppOps.checkPackage(callingUid, callingPackage);
1691
1692 // Repeating alarms must use PendingIntent, not direct listener
1693 if (interval != 0) {
1694 if (directReceiver != null) {
1695 throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers");
1696 }
1697 }
1698
Adam Lesinski182f73f2013-12-05 16:48:06 -08001699 if (workSource != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001700 getContext().enforcePermission(
Adam Lesinski182f73f2013-12-05 16:48:06 -08001701 android.Manifest.permission.UPDATE_DEVICE_STATS,
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001702 Binder.getCallingPid(), callingUid, "AlarmManager.set");
Christopher Tate89779822012-08-31 14:40:03 -07001703 }
1704
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001705 // No incoming callers can request either WAKE_FROM_IDLE or
1706 // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
1707 flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
1708 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
1709
1710 // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
1711 // manager when to come out of idle mode, which is only for DeviceIdleController.
1712 if (callingUid != Process.SYSTEM_UID) {
1713 flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
1714 }
1715
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001716 // If this is an exact time alarm, then it can't be batched with other alarms.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001717 if (windowLength == AlarmManager.WINDOW_EXACT) {
1718 flags |= AlarmManager.FLAG_STANDALONE;
1719 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001720
1721 // If this alarm is for an alarm clock, then it must be standalone and we will
1722 // use it to wake early from idle if needed.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001723 if (alarmClock != null) {
1724 flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001725
1726 // If the caller is a core system component or on the user's whitelist, and not calling
1727 // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
1728 // This means we will allow these alarms to go off as normal even while idle, with no
1729 // timing restrictions.
1730 } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
Christopher Tatebb9cce52017-04-18 14:19:43 -07001731 || callingUid == mSystemUiUid
Makoto Onuki2206af32017-11-21 16:25:35 -08001732 || mForceAppStandbyTracker.isUidPowerSaveWhitelisted(callingUid))) {
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001733 flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
1734 flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001735 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001736
Christopher Tate14a7bb02015-10-01 10:24:31 -07001737 setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
1738 listenerTag, flags, workSource, alarmClock, callingUid, callingPackage);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001739 }
Christopher Tate89779822012-08-31 14:40:03 -07001740
Adam Lesinski182f73f2013-12-05 16:48:06 -08001741 @Override
Greg Hackmann0cab8962014-02-21 16:35:52 -08001742 public boolean setTime(long millis) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001743 getContext().enforceCallingOrSelfPermission(
1744 "android.permission.SET_TIME",
1745 "setTime");
1746
Greg Hackmann0cab8962014-02-21 16:35:52 -08001747 if (mNativeData == 0) {
1748 Slog.w(TAG, "Not setting time since no alarm driver is available.");
1749 return false;
Christopher Tate89779822012-08-31 14:40:03 -07001750 }
Greg Hackmann0cab8962014-02-21 16:35:52 -08001751
1752 synchronized (mLock) {
1753 return setKernelTime(mNativeData, millis) == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001756
1757 @Override
1758 public void setTimeZone(String tz) {
1759 getContext().enforceCallingOrSelfPermission(
1760 "android.permission.SET_TIME_ZONE",
1761 "setTimeZone");
1762
1763 final long oldId = Binder.clearCallingIdentity();
1764 try {
1765 setTimeZoneImpl(tz);
1766 } finally {
1767 Binder.restoreCallingIdentity(oldId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 }
1769 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001770
Adam Lesinski182f73f2013-12-05 16:48:06 -08001771 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07001772 public void remove(PendingIntent operation, IAlarmListener listener) {
1773 if (operation == null && listener == null) {
1774 Slog.w(TAG, "remove() with no intent or listener");
1775 return;
1776 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001777
Christopher Tate14a7bb02015-10-01 10:24:31 -07001778 synchronized (mLock) {
1779 removeLocked(operation, listener);
1780 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001782
Adam Lesinski182f73f2013-12-05 16:48:06 -08001783 @Override
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001784 public long getNextWakeFromIdleTime() {
1785 return getNextWakeFromIdleTimeImpl();
1786 }
1787
1788 @Override
Jose Lima235510e2014-08-13 12:50:01 -07001789 public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001790 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1791 Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */,
1792 "getNextAlarmClock", null);
1793
1794 return getNextAlarmClockImpl(userId);
1795 }
1796
1797 @Override
Adam Lesinski182f73f2013-12-05 16:48:06 -08001798 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -06001799 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
Kweku Adams61e03292017-10-19 14:27:12 -07001800
1801 if (args.length > 0 && "--proto".equals(args[0])) {
1802 dumpProto(fd);
1803 } else {
1804 dumpImpl(pw);
1805 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001806 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001807 };
Christopher Tate4cb338d2013-07-26 13:11:31 -07001808
Adam Lesinski182f73f2013-12-05 16:48:06 -08001809 void dumpImpl(PrintWriter pw) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810 synchronized (mLock) {
1811 pw.println("Current Alarm Manager state:");
Dianne Hackborna750a632015-06-16 17:18:23 -07001812 mConstants.dump(pw);
1813 pw.println();
1814
Makoto Onuki2206af32017-11-21 16:25:35 -08001815 mForceAppStandbyTracker.dump(pw, " ");
Christopher Tate12cf0b62018-01-05 18:40:14 -08001816 pw.println();
Makoto Onuki2206af32017-11-21 16:25:35 -08001817
Suprabh Shukla75edab12018-01-29 14:09:06 -08001818 pw.println(" App Standby Parole: " + mAppStandbyParole);
1819 pw.println();
1820
Christopher Tatee0a22b32013-07-11 14:43:13 -07001821 final long nowRTC = System.currentTimeMillis();
1822 final long nowELAPSED = SystemClock.elapsedRealtime();
Makoto Onuki5d93b832018-01-10 16:12:39 -08001823 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Christopher Tatee0a22b32013-07-11 14:43:13 -07001824
Dianne Hackborna750a632015-06-16 17:18:23 -07001825 pw.print(" nowRTC="); pw.print(nowRTC);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001826 pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
Christopher Tate7f2a0352015-12-08 10:24:33 -08001827 pw.print(" nowELAPSED="); pw.print(nowELAPSED);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001828 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001829 pw.print(" mLastTimeChangeClockTime="); pw.print(mLastTimeChangeClockTime);
Dianne Hackbornc3527222015-05-13 14:03:20 -07001830 pw.print("="); pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
Christopher Tate12cf0b62018-01-05 18:40:14 -08001831 pw.print(" mLastTimeChangeRealtime="); pw.println(mLastTimeChangeRealtime);
1832 pw.print(" mLastTickIssued=");
Makoto Onuki5d93b832018-01-10 16:12:39 -08001833 pw.println(sdf.format(new Date(nowRTC - (nowELAPSED - mLastTickIssued))));
Christopher Tate12cf0b62018-01-05 18:40:14 -08001834 pw.print(" mLastTickReceived="); pw.println(sdf.format(new Date(mLastTickReceived)));
1835 pw.print(" mLastTickSet="); pw.println(sdf.format(new Date(mLastTickSet)));
Makoto Onuki5d93b832018-01-10 16:12:39 -08001836 pw.print(" mLastTickAdded="); pw.println(sdf.format(new Date(mLastTickAdded)));
1837 pw.print(" mLastTickRemoved="); pw.println(sdf.format(new Date(mLastTickRemoved)));
Dianne Hackbornc3527222015-05-13 14:03:20 -07001838 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001839 if (!mInteractive) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001840 pw.print(" Time since non-interactive: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001841 TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
1842 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001843 pw.print(" Max wakeup delay: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001844 TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
1845 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001846 pw.print(" Time since last dispatch: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001847 TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
1848 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001849 pw.print(" Next non-wakeup delivery time: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001850 TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
1851 pw.println();
1852 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001853
1854 long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
1855 long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
Dianne Hackborna750a632015-06-16 17:18:23 -07001856 pw.print(" Next non-wakeup alarm: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001857 TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001858 pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
Dianne Hackborna750a632015-06-16 17:18:23 -07001859 pw.print(" Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001860 pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07001861 pw.print(" Last wakeup: "); TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw);
1862 pw.print(" set at "); TimeUtils.formatDuration(mLastWakeupSet, nowELAPSED, pw);
1863 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001864 pw.print(" Num time change events: "); pw.println(mNumTimeChanged);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001865
John Spurlock604a5ee2015-06-01 12:27:22 -04001866 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001867 pw.println(" Next alarm clock information: ");
John Spurlock604a5ee2015-06-01 12:27:22 -04001868 final TreeSet<Integer> users = new TreeSet<>();
1869 for (int i = 0; i < mNextAlarmClockForUser.size(); i++) {
1870 users.add(mNextAlarmClockForUser.keyAt(i));
1871 }
1872 for (int i = 0; i < mPendingSendNextAlarmClockChangedForUser.size(); i++) {
1873 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
1874 }
1875 for (int user : users) {
1876 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
1877 final long time = next != null ? next.getTriggerTime() : 0;
1878 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
Dianne Hackborna750a632015-06-16 17:18:23 -07001879 pw.print(" user:"); pw.print(user);
John Spurlock604a5ee2015-06-01 12:27:22 -04001880 pw.print(" pendingSend:"); pw.print(pendingSend);
1881 pw.print(" time:"); pw.print(time);
1882 if (time > 0) {
1883 pw.print(" = "); pw.print(sdf.format(new Date(time)));
1884 pw.print(" = "); TimeUtils.formatDuration(time, nowRTC, pw);
1885 }
1886 pw.println();
1887 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001888 if (mAlarmBatches.size() > 0) {
1889 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001890 pw.print(" Pending alarm batches: ");
Christopher Tatee0a22b32013-07-11 14:43:13 -07001891 pw.println(mAlarmBatches.size());
1892 for (Batch b : mAlarmBatches) {
1893 pw.print(b); pw.println(':');
Dianne Hackborna750a632015-06-16 17:18:23 -07001894 dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001895 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001897 pw.println();
1898 pw.println(" Pending user blocked background alarms: ");
1899 boolean blocked = false;
1900 for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
1901 final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
1902 if (blockedAlarms != null && blockedAlarms.size() > 0) {
1903 blocked = true;
1904 dumpAlarmList(pw, blockedAlarms, " ", nowELAPSED, nowRTC, sdf);
1905 }
1906 }
1907 if (!blocked) {
1908 pw.println(" none");
1909 }
Suprabh Shuklac25447d2018-01-19 16:43:35 -08001910 pw.print(" mUseAllowWhileIdleShortTime: [");
1911 for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
1912 if (mUseAllowWhileIdleShortTime.valueAt(i)) {
1913 UserHandle.formatUid(pw, mUseAllowWhileIdleShortTime.keyAt(i));
1914 pw.print(" ");
1915 }
1916 }
1917 pw.println("]");
1918
Suprabh Shukla75edab12018-01-29 14:09:06 -08001919 pw.println(" mLastAlarmDeliveredForPackage:");
1920 for (int i = 0; i < mLastAlarmDeliveredForPackage.size(); i++) {
1921 Pair<String, Integer> packageUser = mLastAlarmDeliveredForPackage.keyAt(i);
1922 pw.print(" Package " + packageUser.first + ", User " + packageUser.second + ":");
1923 TimeUtils.formatDuration(mLastAlarmDeliveredForPackage.valueAt(i), nowELAPSED, pw);
1924 pw.println();
1925 }
1926 pw.println();
1927
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001928 if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001929 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001930 pw.println(" Idle mode state:");
1931 pw.print(" Idling until: ");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001932 if (mPendingIdleUntil != null) {
1933 pw.println(mPendingIdleUntil);
Kweku Adams61e03292017-10-19 14:27:12 -07001934 mPendingIdleUntil.dump(pw, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001935 } else {
1936 pw.println("null");
1937 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001938 pw.println(" Pending alarms:");
1939 dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001940 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001941 if (mNextWakeFromIdle != null) {
1942 pw.println();
1943 pw.print(" Next wake from idle: "); pw.println(mNextWakeFromIdle);
Kweku Adams61e03292017-10-19 14:27:12 -07001944 mNextWakeFromIdle.dump(pw, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001945 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001946
1947 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001948 pw.print(" Past-due non-wakeup alarms: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001949 if (mPendingNonWakeupAlarms.size() > 0) {
1950 pw.println(mPendingNonWakeupAlarms.size());
Dianne Hackborna750a632015-06-16 17:18:23 -07001951 dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001952 } else {
1953 pw.println("(none)");
1954 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001955 pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001956 pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
1957 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001958 pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001959 pw.print(", max non-interactive time: ");
1960 TimeUtils.formatDuration(mNonInteractiveTime, pw);
1961 pw.println();
1962
1963 pw.println();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001964 pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
Christopher Tateeabba732017-08-17 17:12:52 -07001965 pw.print(" PendingIntent send count: "); pw.println(mSendCount);
1966 pw.print(" PendingIntent finish count: "); pw.println(mSendFinishCount);
1967 pw.print(" Listener send count: "); pw.println(mListenerCount);
1968 pw.print(" Listener finish count: "); pw.println(mListenerFinishCount);
Dianne Hackborn81038902012-11-26 17:04:09 -08001969 pw.println();
1970
Christopher Tate7f2a0352015-12-08 10:24:33 -08001971 if (mInFlight.size() > 0) {
1972 pw.println("Outstanding deliveries:");
1973 for (int i = 0; i < mInFlight.size(); i++) {
1974 pw.print(" #"); pw.print(i); pw.print(": ");
1975 pw.println(mInFlight.get(i));
1976 }
1977 pw.println();
1978 }
1979
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001980 if (mLastAllowWhileIdleDispatch.size() > 0) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001981 pw.println(" Last allow while idle dispatch times:");
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001982 for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
1983 pw.print(" UID ");
1984 UserHandle.formatUid(pw, mLastAllowWhileIdleDispatch.keyAt(i));
1985 pw.print(": ");
1986 TimeUtils.formatDuration(mLastAllowWhileIdleDispatch.valueAt(i),
1987 nowELAPSED, pw);
1988 pw.println();
1989 }
1990 }
1991 pw.println();
1992
Dianne Hackborn81038902012-11-26 17:04:09 -08001993 if (mLog.dump(pw, " Recent problems", " ")) {
1994 pw.println();
1995 }
1996
1997 final FilterStats[] topFilters = new FilterStats[10];
1998 final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
1999 @Override
2000 public int compare(FilterStats lhs, FilterStats rhs) {
2001 if (lhs.aggregateTime < rhs.aggregateTime) {
2002 return 1;
2003 } else if (lhs.aggregateTime > rhs.aggregateTime) {
2004 return -1;
2005 }
2006 return 0;
2007 }
2008 };
2009 int len = 0;
Kweku Adams61e03292017-10-19 14:27:12 -07002010 // Get the top 10 FilterStats, ordered by aggregateTime.
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002011 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
2012 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2013 for (int ip=0; ip<uidStats.size(); ip++) {
2014 BroadcastStats bs = uidStats.valueAt(ip);
2015 for (int is=0; is<bs.filterStats.size(); is++) {
2016 FilterStats fs = bs.filterStats.valueAt(is);
2017 int pos = len > 0
2018 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
2019 if (pos < 0) {
2020 pos = -pos - 1;
Dianne Hackborn81038902012-11-26 17:04:09 -08002021 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002022 if (pos < topFilters.length) {
2023 int copylen = topFilters.length - pos - 1;
2024 if (copylen > 0) {
2025 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
2026 }
2027 topFilters[pos] = fs;
2028 if (len < topFilters.length) {
2029 len++;
2030 }
Dianne Hackborn81038902012-11-26 17:04:09 -08002031 }
2032 }
2033 }
2034 }
2035 if (len > 0) {
2036 pw.println(" Top Alarms:");
2037 for (int i=0; i<len; i++) {
2038 FilterStats fs = topFilters[i];
2039 pw.print(" ");
2040 if (fs.nesting > 0) pw.print("*ACTIVE* ");
2041 TimeUtils.formatDuration(fs.aggregateTime, pw);
2042 pw.print(" running, "); pw.print(fs.numWakeup);
2043 pw.print(" wakeups, "); pw.print(fs.count);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002044 pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
2045 pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
Dianne Hackborn81038902012-11-26 17:04:09 -08002046 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002047 pw.print(" "); pw.print(fs.mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08002048 pw.println();
2049 }
2050 }
2051
2052 pw.println(" ");
2053 pw.println(" Alarm Stats:");
2054 final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002055 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
2056 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2057 for (int ip=0; ip<uidStats.size(); ip++) {
2058 BroadcastStats bs = uidStats.valueAt(ip);
2059 pw.print(" ");
2060 if (bs.nesting > 0) pw.print("*ACTIVE* ");
2061 UserHandle.formatUid(pw, bs.mUid);
2062 pw.print(":");
2063 pw.print(bs.mPackageName);
2064 pw.print(" "); TimeUtils.formatDuration(bs.aggregateTime, pw);
2065 pw.print(" running, "); pw.print(bs.numWakeup);
2066 pw.println(" wakeups:");
2067 tmpFilters.clear();
2068 for (int is=0; is<bs.filterStats.size(); is++) {
2069 tmpFilters.add(bs.filterStats.valueAt(is));
2070 }
2071 Collections.sort(tmpFilters, comparator);
2072 for (int i=0; i<tmpFilters.size(); i++) {
2073 FilterStats fs = tmpFilters.get(i);
2074 pw.print(" ");
2075 if (fs.nesting > 0) pw.print("*ACTIVE* ");
2076 TimeUtils.formatDuration(fs.aggregateTime, pw);
2077 pw.print(" "); pw.print(fs.numWakeup);
2078 pw.print(" wakes " ); pw.print(fs.count);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002079 pw.print(" alarms, last ");
2080 TimeUtils.formatDuration(fs.lastTime, nowELAPSED, pw);
2081 pw.println(":");
2082 pw.print(" ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002083 pw.print(fs.mTag);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002084 pw.println();
2085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002086 }
2087 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08002088 pw.println();
2089 mStatLogger.dump(pw, " ");
Christopher Tate18a75f12013-07-01 18:18:59 -07002090
Dianne Hackbornae78bf82015-10-26 13:33:20 -07002091 if (RECORD_DEVICE_IDLE_ALARMS) {
2092 pw.println();
2093 pw.println(" Allow while idle dispatches:");
2094 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
2095 IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
2096 pw.print(" ");
2097 TimeUtils.formatDuration(ent.elapsedRealtime, nowELAPSED, pw);
2098 pw.print(": ");
2099 UserHandle.formatUid(pw, ent.uid);
2100 pw.print(":");
2101 pw.println(ent.pkg);
2102 if (ent.op != null) {
2103 pw.print(" ");
2104 pw.print(ent.op);
2105 pw.print(" / ");
2106 pw.print(ent.tag);
2107 if (ent.argRealtime != 0) {
2108 pw.print(" (");
2109 TimeUtils.formatDuration(ent.argRealtime, nowELAPSED, pw);
2110 pw.print(")");
2111 }
2112 pw.println();
2113 }
2114 }
2115 }
2116
Christopher Tate18a75f12013-07-01 18:18:59 -07002117 if (WAKEUP_STATS) {
2118 pw.println();
2119 pw.println(" Recent Wakeup History:");
Christopher Tate18a75f12013-07-01 18:18:59 -07002120 long last = -1;
2121 for (WakeupEvent event : mRecentWakeups) {
2122 pw.print(" "); pw.print(sdf.format(new Date(event.when)));
2123 pw.print('|');
2124 if (last < 0) {
2125 pw.print('0');
2126 } else {
2127 pw.print(event.when - last);
2128 }
2129 last = event.when;
2130 pw.print('|'); pw.print(event.uid);
2131 pw.print('|'); pw.print(event.action);
2132 pw.println();
2133 }
2134 pw.println();
2135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136 }
2137 }
2138
Kweku Adams61e03292017-10-19 14:27:12 -07002139 void dumpProto(FileDescriptor fd) {
2140 final ProtoOutputStream proto = new ProtoOutputStream(fd);
2141
2142 synchronized (mLock) {
2143 final long nowRTC = System.currentTimeMillis();
2144 final long nowElapsed = SystemClock.elapsedRealtime();
2145 proto.write(AlarmManagerServiceProto.CURRENT_TIME, nowRTC);
2146 proto.write(AlarmManagerServiceProto.ELAPSED_REALTIME, nowElapsed);
2147 proto.write(AlarmManagerServiceProto.LAST_TIME_CHANGE_CLOCK_TIME,
2148 mLastTimeChangeClockTime);
2149 proto.write(AlarmManagerServiceProto.LAST_TIME_CHANGE_REALTIME,
2150 mLastTimeChangeRealtime);
2151
2152 mConstants.dumpProto(proto, AlarmManagerServiceProto.SETTINGS);
2153
Makoto Onuki2206af32017-11-21 16:25:35 -08002154 mForceAppStandbyTracker.dumpProto(proto,
2155 AlarmManagerServiceProto.FORCE_APP_STANDBY_TRACKER);
Kweku Adams61e03292017-10-19 14:27:12 -07002156
2157 proto.write(AlarmManagerServiceProto.IS_INTERACTIVE, mInteractive);
2158 if (!mInteractive) {
2159 // Durations
2160 proto.write(AlarmManagerServiceProto.TIME_SINCE_NON_INTERACTIVE_MS,
2161 nowElapsed - mNonInteractiveStartTime);
2162 proto.write(AlarmManagerServiceProto.MAX_WAKEUP_DELAY_MS,
2163 currentNonWakeupFuzzLocked(nowElapsed));
2164 proto.write(AlarmManagerServiceProto.TIME_SINCE_LAST_DISPATCH_MS,
2165 nowElapsed - mLastAlarmDeliveryTime);
2166 proto.write(AlarmManagerServiceProto.TIME_UNTIL_NEXT_NON_WAKEUP_DELIVERY_MS,
2167 nowElapsed - mNextNonWakeupDeliveryTime);
2168 }
2169
2170 proto.write(AlarmManagerServiceProto.TIME_UNTIL_NEXT_NON_WAKEUP_ALARM_MS,
2171 mNextNonWakeup - nowElapsed);
2172 proto.write(AlarmManagerServiceProto.TIME_UNTIL_NEXT_WAKEUP_MS,
2173 mNextWakeup - nowElapsed);
2174 proto.write(AlarmManagerServiceProto.TIME_SINCE_LAST_WAKEUP_MS,
2175 nowElapsed - mLastWakeup);
2176 proto.write(AlarmManagerServiceProto.TIME_SINCE_LAST_WAKEUP_SET_MS,
2177 nowElapsed - mLastWakeupSet);
2178 proto.write(AlarmManagerServiceProto.TIME_CHANGE_EVENT_COUNT, mNumTimeChanged);
Kweku Adams61e03292017-10-19 14:27:12 -07002179
2180 final TreeSet<Integer> users = new TreeSet<>();
2181 final int nextAlarmClockForUserSize = mNextAlarmClockForUser.size();
2182 for (int i = 0; i < nextAlarmClockForUserSize; i++) {
2183 users.add(mNextAlarmClockForUser.keyAt(i));
2184 }
2185 final int pendingSendNextAlarmClockChangedForUserSize =
2186 mPendingSendNextAlarmClockChangedForUser.size();
2187 for (int i = 0; i < pendingSendNextAlarmClockChangedForUserSize; i++) {
2188 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
2189 }
2190 for (int user : users) {
2191 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
2192 final long time = next != null ? next.getTriggerTime() : 0;
2193 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
2194 final long aToken = proto.start(AlarmManagerServiceProto.NEXT_ALARM_CLOCK_METADATA);
2195 proto.write(AlarmClockMetadataProto.USER, user);
2196 proto.write(AlarmClockMetadataProto.IS_PENDING_SEND, pendingSend);
2197 proto.write(AlarmClockMetadataProto.TRIGGER_TIME_MS, time);
2198 proto.end(aToken);
2199 }
2200 for (Batch b : mAlarmBatches) {
2201 b.writeToProto(proto, AlarmManagerServiceProto.PENDING_ALARM_BATCHES,
2202 nowElapsed, nowRTC);
2203 }
2204 for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
2205 final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
2206 if (blockedAlarms != null) {
2207 for (Alarm a : blockedAlarms) {
2208 a.writeToProto(proto,
2209 AlarmManagerServiceProto.PENDING_USER_BLOCKED_BACKGROUND_ALARMS,
2210 nowElapsed, nowRTC);
2211 }
2212 }
2213 }
2214 if (mPendingIdleUntil != null) {
2215 mPendingIdleUntil.writeToProto(
2216 proto, AlarmManagerServiceProto.PENDING_IDLE_UNTIL, nowElapsed, nowRTC);
2217 }
2218 for (Alarm a : mPendingWhileIdleAlarms) {
2219 a.writeToProto(proto, AlarmManagerServiceProto.PENDING_WHILE_IDLE_ALARMS,
2220 nowElapsed, nowRTC);
2221 }
2222 if (mNextWakeFromIdle != null) {
2223 mNextWakeFromIdle.writeToProto(proto, AlarmManagerServiceProto.NEXT_WAKE_FROM_IDLE,
2224 nowElapsed, nowRTC);
2225 }
2226
2227 for (Alarm a : mPendingNonWakeupAlarms) {
2228 a.writeToProto(proto, AlarmManagerServiceProto.PAST_DUE_NON_WAKEUP_ALARMS,
2229 nowElapsed, nowRTC);
2230 }
2231
2232 proto.write(AlarmManagerServiceProto.DELAYED_ALARM_COUNT, mNumDelayedAlarms);
2233 proto.write(AlarmManagerServiceProto.TOTAL_DELAY_TIME_MS, mTotalDelayTime);
2234 proto.write(AlarmManagerServiceProto.MAX_DELAY_DURATION_MS, mMaxDelayTime);
2235 proto.write(AlarmManagerServiceProto.MAX_NON_INTERACTIVE_DURATION_MS,
2236 mNonInteractiveTime);
2237
2238 proto.write(AlarmManagerServiceProto.BROADCAST_REF_COUNT, mBroadcastRefCount);
2239 proto.write(AlarmManagerServiceProto.PENDING_INTENT_SEND_COUNT, mSendCount);
2240 proto.write(AlarmManagerServiceProto.PENDING_INTENT_FINISH_COUNT, mSendFinishCount);
2241 proto.write(AlarmManagerServiceProto.LISTENER_SEND_COUNT, mListenerCount);
2242 proto.write(AlarmManagerServiceProto.LISTENER_FINISH_COUNT, mListenerFinishCount);
2243
2244 for (InFlight f : mInFlight) {
2245 f.writeToProto(proto, AlarmManagerServiceProto.OUTSTANDING_DELIVERIES);
2246 }
2247
Kweku Adams61e03292017-10-19 14:27:12 -07002248 for (int i = 0; i < mLastAllowWhileIdleDispatch.size(); ++i) {
2249 final long token = proto.start(
2250 AlarmManagerServiceProto.LAST_ALLOW_WHILE_IDLE_DISPATCH_TIMES);
2251 proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.UID,
2252 mLastAllowWhileIdleDispatch.keyAt(i));
2253 proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.TIME_MS,
2254 mLastAllowWhileIdleDispatch.valueAt(i));
2255 proto.end(token);
2256 }
2257
2258 mLog.writeToProto(proto, AlarmManagerServiceProto.RECENT_PROBLEMS);
2259
2260 final FilterStats[] topFilters = new FilterStats[10];
2261 final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
2262 @Override
2263 public int compare(FilterStats lhs, FilterStats rhs) {
2264 if (lhs.aggregateTime < rhs.aggregateTime) {
2265 return 1;
2266 } else if (lhs.aggregateTime > rhs.aggregateTime) {
2267 return -1;
2268 }
2269 return 0;
2270 }
2271 };
2272 int len = 0;
2273 // Get the top 10 FilterStats, ordered by aggregateTime.
2274 for (int iu = 0; iu < mBroadcastStats.size(); ++iu) {
2275 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2276 for (int ip = 0; ip < uidStats.size(); ++ip) {
2277 BroadcastStats bs = uidStats.valueAt(ip);
2278 for (int is = 0; is < bs.filterStats.size(); ++is) {
2279 FilterStats fs = bs.filterStats.valueAt(is);
2280 int pos = len > 0
2281 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
2282 if (pos < 0) {
2283 pos = -pos - 1;
2284 }
2285 if (pos < topFilters.length) {
2286 int copylen = topFilters.length - pos - 1;
2287 if (copylen > 0) {
2288 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
2289 }
2290 topFilters[pos] = fs;
2291 if (len < topFilters.length) {
2292 len++;
2293 }
2294 }
2295 }
2296 }
2297 }
2298 for (int i = 0; i < len; ++i) {
2299 final long token = proto.start(AlarmManagerServiceProto.TOP_ALARMS);
2300 FilterStats fs = topFilters[i];
2301
2302 proto.write(AlarmManagerServiceProto.TopAlarm.UID, fs.mBroadcastStats.mUid);
2303 proto.write(AlarmManagerServiceProto.TopAlarm.PACKAGE_NAME,
2304 fs.mBroadcastStats.mPackageName);
2305 fs.writeToProto(proto, AlarmManagerServiceProto.TopAlarm.FILTER);
2306
2307 proto.end(token);
2308 }
2309
2310 final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
2311 for (int iu = 0; iu < mBroadcastStats.size(); ++iu) {
2312 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2313 for (int ip = 0; ip < uidStats.size(); ++ip) {
2314 final long token = proto.start(AlarmManagerServiceProto.ALARM_STATS);
2315
2316 BroadcastStats bs = uidStats.valueAt(ip);
2317 bs.writeToProto(proto, AlarmManagerServiceProto.AlarmStat.BROADCAST);
2318
2319 // uidStats is an ArrayMap, which we can't sort.
2320 tmpFilters.clear();
2321 for (int is = 0; is < bs.filterStats.size(); ++is) {
2322 tmpFilters.add(bs.filterStats.valueAt(is));
2323 }
2324 Collections.sort(tmpFilters, comparator);
2325 for (FilterStats fs : tmpFilters) {
2326 fs.writeToProto(proto, AlarmManagerServiceProto.AlarmStat.FILTERS);
2327 }
2328
2329 proto.end(token);
2330 }
2331 }
2332
2333 if (RECORD_DEVICE_IDLE_ALARMS) {
2334 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
2335 IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
2336 final long token = proto.start(
2337 AlarmManagerServiceProto.ALLOW_WHILE_IDLE_DISPATCHES);
2338
2339 proto.write(IdleDispatchEntryProto.UID, ent.uid);
2340 proto.write(IdleDispatchEntryProto.PKG, ent.pkg);
2341 proto.write(IdleDispatchEntryProto.TAG, ent.tag);
2342 proto.write(IdleDispatchEntryProto.OP, ent.op);
2343 proto.write(IdleDispatchEntryProto.ENTRY_CREATION_REALTIME,
2344 ent.elapsedRealtime);
2345 proto.write(IdleDispatchEntryProto.ARG_REALTIME, ent.argRealtime);
2346
2347 proto.end(token);
2348 }
2349 }
2350
2351 if (WAKEUP_STATS) {
2352 for (WakeupEvent event : mRecentWakeups) {
2353 final long token = proto.start(AlarmManagerServiceProto.RECENT_WAKEUP_HISTORY);
2354 proto.write(WakeupEventProto.UID, event.uid);
2355 proto.write(WakeupEventProto.ACTION, event.action);
2356 proto.write(WakeupEventProto.WHEN, event.when);
2357 proto.end(token);
2358 }
2359 }
2360 }
2361
2362 proto.flush();
2363 }
2364
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002365 private void logBatchesLocked(SimpleDateFormat sdf) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08002366 ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
2367 PrintWriter pw = new PrintWriter(bs);
2368 final long nowRTC = System.currentTimeMillis();
2369 final long nowELAPSED = SystemClock.elapsedRealtime();
2370 final int NZ = mAlarmBatches.size();
2371 for (int iz = 0; iz < NZ; iz++) {
2372 Batch bz = mAlarmBatches.get(iz);
2373 pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002374 dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC, sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002375 pw.flush();
2376 Slog.v(TAG, bs.toString());
2377 bs.reset();
2378 }
2379 }
2380
2381 private boolean validateConsistencyLocked() {
2382 if (DEBUG_VALIDATE) {
2383 long lastTime = Long.MIN_VALUE;
2384 final int N = mAlarmBatches.size();
2385 for (int i = 0; i < N; i++) {
2386 Batch b = mAlarmBatches.get(i);
2387 if (b.start >= lastTime) {
2388 // duplicate start times are okay because of standalone batches
2389 lastTime = b.start;
2390 } else {
2391 Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002392 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2393 logBatchesLocked(sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002394 return false;
2395 }
2396 }
2397 }
2398 return true;
2399 }
2400
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002401 private Batch findFirstWakeupBatchLocked() {
2402 final int N = mAlarmBatches.size();
2403 for (int i = 0; i < N; i++) {
2404 Batch b = mAlarmBatches.get(i);
2405 if (b.hasWakeups()) {
2406 return b;
2407 }
2408 }
2409 return null;
2410 }
2411
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002412 long getNextWakeFromIdleTimeImpl() {
2413 synchronized (mLock) {
2414 return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE;
2415 }
2416 }
2417
2418 AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02002419 synchronized (mLock) {
2420 return mNextAlarmClockForUser.get(userId);
2421 }
2422 }
2423
2424 /**
2425 * Recomputes the next alarm clock for all users.
2426 */
2427 private void updateNextAlarmClockLocked() {
2428 if (!mNextAlarmClockMayChange) {
2429 return;
2430 }
2431 mNextAlarmClockMayChange = false;
2432
Jose Lima235510e2014-08-13 12:50:01 -07002433 SparseArray<AlarmManager.AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02002434 nextForUser.clear();
2435
2436 final int N = mAlarmBatches.size();
2437 for (int i = 0; i < N; i++) {
2438 ArrayList<Alarm> alarms = mAlarmBatches.get(i).alarms;
2439 final int M = alarms.size();
2440
2441 for (int j = 0; j < M; j++) {
2442 Alarm a = alarms.get(j);
2443 if (a.alarmClock != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002444 final int userId = UserHandle.getUserId(a.uid);
Christopher Tate76389c02016-08-03 14:57:47 -07002445 AlarmManager.AlarmClockInfo current = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002446
2447 if (DEBUG_ALARM_CLOCK) {
Christopher Tate76389c02016-08-03 14:57:47 -07002448 Log.v(TAG, "Found AlarmClockInfo " + a.alarmClock + " at " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01002449 formatNextAlarm(getContext(), a.alarmClock, userId) +
Adrian Roosc42a1e12014-07-07 23:35:53 +02002450 " for user " + userId);
2451 }
2452
2453 // Alarms and batches are sorted by time, no need to compare times here.
2454 if (nextForUser.get(userId) == null) {
2455 nextForUser.put(userId, a.alarmClock);
Christopher Tate76389c02016-08-03 14:57:47 -07002456 } else if (a.alarmClock.equals(current)
2457 && current.getTriggerTime() <= nextForUser.get(userId).getTriggerTime()) {
2458 // same/earlier time and it's the one we cited before, so stick with it
2459 nextForUser.put(userId, current);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002460 }
2461 }
2462 }
2463 }
2464
2465 // Update mNextAlarmForUser with new values.
2466 final int NN = nextForUser.size();
2467 for (int i = 0; i < NN; i++) {
Jose Lima235510e2014-08-13 12:50:01 -07002468 AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002469 int userId = nextForUser.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07002470 AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002471 if (!newAlarm.equals(currentAlarm)) {
2472 updateNextAlarmInfoForUserLocked(userId, newAlarm);
2473 }
2474 }
2475
2476 // Remove users without any alarm clocks scheduled.
2477 final int NNN = mNextAlarmClockForUser.size();
2478 for (int i = NNN - 1; i >= 0; i--) {
2479 int userId = mNextAlarmClockForUser.keyAt(i);
2480 if (nextForUser.get(userId) == null) {
2481 updateNextAlarmInfoForUserLocked(userId, null);
2482 }
2483 }
2484 }
2485
Jose Lima235510e2014-08-13 12:50:01 -07002486 private void updateNextAlarmInfoForUserLocked(int userId,
2487 AlarmManager.AlarmClockInfo alarmClock) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02002488 if (alarmClock != null) {
2489 if (DEBUG_ALARM_CLOCK) {
2490 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01002491 formatNextAlarm(getContext(), alarmClock, userId));
Adrian Roosc42a1e12014-07-07 23:35:53 +02002492 }
2493 mNextAlarmClockForUser.put(userId, alarmClock);
2494 } else {
2495 if (DEBUG_ALARM_CLOCK) {
2496 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None");
2497 }
2498 mNextAlarmClockForUser.remove(userId);
2499 }
2500
2501 mPendingSendNextAlarmClockChangedForUser.put(userId, true);
2502 mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
2503 mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
2504 }
2505
2506 /**
2507 * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
2508 * for which alarm clocks have changed since the last call to this.
2509 *
2510 * Do not call with a lock held. Only call from mHandler's thread.
2511 *
2512 * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
2513 */
2514 private void sendNextAlarmClockChanged() {
Jose Lima235510e2014-08-13 12:50:01 -07002515 SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02002516 pendingUsers.clear();
2517
2518 synchronized (mLock) {
2519 final int N = mPendingSendNextAlarmClockChangedForUser.size();
2520 for (int i = 0; i < N; i++) {
2521 int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i);
2522 pendingUsers.append(userId, mNextAlarmClockForUser.get(userId));
2523 }
2524 mPendingSendNextAlarmClockChangedForUser.clear();
2525 }
2526
2527 final int N = pendingUsers.size();
2528 for (int i = 0; i < N; i++) {
2529 int userId = pendingUsers.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07002530 AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002531 Settings.System.putStringForUser(getContext().getContentResolver(),
2532 Settings.System.NEXT_ALARM_FORMATTED,
Selim Cinek9c4a7072014-11-21 17:44:34 +01002533 formatNextAlarm(getContext(), alarmClock, userId),
Adrian Roosc42a1e12014-07-07 23:35:53 +02002534 userId);
2535
2536 getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT,
2537 new UserHandle(userId));
2538 }
2539 }
2540
2541 /**
2542 * Formats an alarm like platform/packages/apps/DeskClock used to.
2543 */
Selim Cinek9c4a7072014-11-21 17:44:34 +01002544 private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info,
2545 int userId) {
2546 String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma";
Adrian Roosc42a1e12014-07-07 23:35:53 +02002547 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
2548 return (info == null) ? "" :
2549 DateFormat.format(pattern, info.getTriggerTime()).toString();
2550 }
2551
Adam Lesinski182f73f2013-12-05 16:48:06 -08002552 void rescheduleKernelAlarmsLocked() {
2553 // Schedule the next upcoming wakeup alarm. If there is a deliverable batch
2554 // prior to that which contains no wakeups, we schedule that as well.
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002555 long nextNonWakeup = 0;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002556 if (mAlarmBatches.size() > 0) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002557 final Batch firstWakeup = findFirstWakeupBatchLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002558 final Batch firstBatch = mAlarmBatches.get(0);
Prashant Malani753e9e02015-06-10 17:43:49 -07002559 if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002560 mNextWakeup = firstWakeup.start;
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07002561 mLastWakeupSet = SystemClock.elapsedRealtime();
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002562 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002563 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002564 if (firstBatch != firstWakeup) {
2565 nextNonWakeup = firstBatch.start;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002566 }
2567 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002568 if (mPendingNonWakeupAlarms.size() > 0) {
2569 if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
2570 nextNonWakeup = mNextNonWakeupDeliveryTime;
2571 }
2572 }
Prashant Malani753e9e02015-06-10 17:43:49 -07002573 if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002574 mNextNonWakeup = nextNonWakeup;
2575 setLocked(ELAPSED_REALTIME, nextNonWakeup);
2576 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002577 }
2578
Christopher Tate14a7bb02015-10-01 10:24:31 -07002579 private void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
Christopher Tate1d99c392017-12-07 16:54:04 -08002580 if (operation == null && directReceiver == null) {
2581 if (localLOGV) {
2582 Slog.w(TAG, "requested remove() of null operation",
2583 new RuntimeException("here"));
2584 }
2585 return;
2586 }
2587
Adam Lesinski182f73f2013-12-05 16:48:06 -08002588 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002589 final Predicate<Alarm> whichAlarms = (Alarm a) -> a.matches(operation, directReceiver);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002590 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2591 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002592 didRemove |= b.remove(whichAlarms);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002593 if (b.size() == 0) {
2594 mAlarmBatches.remove(i);
2595 }
2596 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002597 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002598 if (mPendingWhileIdleAlarms.get(i).matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002599 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2600 mPendingWhileIdleAlarms.remove(i);
2601 }
2602 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002603 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
2604 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
2605 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
2606 if (alarmsForUid.get(j).matches(operation, directReceiver)) {
2607 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2608 alarmsForUid.remove(j);
2609 }
2610 }
2611 if (alarmsForUid.size() == 0) {
2612 mPendingBackgroundAlarms.removeAt(i);
2613 }
2614 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002615 if (didRemove) {
2616 if (DEBUG_BATCH) {
2617 Slog.v(TAG, "remove(operation) changed bounds; rebatching");
2618 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002619 boolean restorePending = false;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002620 if (mPendingIdleUntil != null && mPendingIdleUntil.matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002621 mPendingIdleUntil = null;
2622 restorePending = true;
2623 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002624 if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002625 mNextWakeFromIdle = null;
2626 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002627 rebatchAllAlarmsLocked(true);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002628 if (restorePending) {
2629 restorePendingWhileIdleAlarmsLocked();
2630 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02002631 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002632 }
2633 }
2634
Christopher Tate1d99c392017-12-07 16:54:04 -08002635 void removeLocked(final int uid) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08002636 if (uid == Process.SYSTEM_UID) {
2637 Slog.wtf(TAG, "removeLocked: Shouldn't for UID=" + uid);
2638 return;
2639 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002640 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002641 final Predicate<Alarm> whichAlarms = (Alarm a) -> a.uid == uid;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002642 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2643 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002644 didRemove |= b.remove(whichAlarms);
2645 if (b.size() == 0) {
2646 mAlarmBatches.remove(i);
2647 }
2648 }
2649 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
2650 final Alarm a = mPendingWhileIdleAlarms.get(i);
2651 if (a.uid == uid) {
2652 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2653 mPendingWhileIdleAlarms.remove(i);
2654 }
2655 }
2656 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i --) {
2657 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
2658 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
2659 if (alarmsForUid.get(j).uid == uid) {
2660 alarmsForUid.remove(j);
2661 }
2662 }
2663 if (alarmsForUid.size() == 0) {
2664 mPendingBackgroundAlarms.removeAt(i);
2665 }
2666 }
2667 if (didRemove) {
2668 if (DEBUG_BATCH) {
2669 Slog.v(TAG, "remove(uid) changed bounds; rebatching");
2670 }
2671 rebatchAllAlarmsLocked(true);
2672 rescheduleKernelAlarmsLocked();
2673 updateNextAlarmClockLocked();
2674 }
2675 }
2676
2677 void removeLocked(final String packageName) {
2678 if (packageName == null) {
2679 if (localLOGV) {
2680 Slog.w(TAG, "requested remove() of null packageName",
2681 new RuntimeException("here"));
2682 }
2683 return;
2684 }
2685
2686 boolean didRemove = false;
2687 final Predicate<Alarm> whichAlarms = (Alarm a) -> a.matches(packageName);
Makoto Onuki5d93b832018-01-10 16:12:39 -08002688 final boolean oldHasTick = haveBatchesTimeTickAlarm(mAlarmBatches);
Christopher Tate1d99c392017-12-07 16:54:04 -08002689 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2690 Batch b = mAlarmBatches.get(i);
2691 didRemove |= b.remove(whichAlarms);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002692 if (b.size() == 0) {
2693 mAlarmBatches.remove(i);
2694 }
2695 }
Makoto Onuki5d93b832018-01-10 16:12:39 -08002696 final boolean newHasTick = haveBatchesTimeTickAlarm(mAlarmBatches);
2697 if (oldHasTick != newHasTick) {
2698 Slog.wtf(TAG, "removeLocked: hasTick changed from " + oldHasTick + " to " + newHasTick);
2699 }
2700
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002701 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002702 final Alarm a = mPendingWhileIdleAlarms.get(i);
2703 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002704 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2705 mPendingWhileIdleAlarms.remove(i);
2706 }
2707 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002708 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i --) {
2709 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
2710 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
2711 if (alarmsForUid.get(j).matches(packageName)) {
2712 alarmsForUid.remove(j);
2713 }
2714 }
2715 if (alarmsForUid.size() == 0) {
2716 mPendingBackgroundAlarms.removeAt(i);
2717 }
2718 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002719 if (didRemove) {
2720 if (DEBUG_BATCH) {
2721 Slog.v(TAG, "remove(package) changed bounds; rebatching");
2722 }
2723 rebatchAllAlarmsLocked(true);
2724 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02002725 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002726 }
2727 }
2728
Christopher Tate1d99c392017-12-07 16:54:04 -08002729 void removeForStoppedLocked(final int uid) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08002730 if (uid == Process.SYSTEM_UID) {
2731 Slog.wtf(TAG, "removeForStoppedLocked: Shouldn't for UID=" + uid);
2732 return;
2733 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002734 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002735 final Predicate<Alarm> whichAlarms = (Alarm a) -> {
2736 try {
2737 if (a.uid == uid && ActivityManager.getService().isAppStartModeDisabled(
2738 uid, a.packageName)) {
2739 return true;
2740 }
2741 } catch (RemoteException e) { /* fall through */}
2742 return false;
2743 };
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002744 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2745 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002746 didRemove |= b.remove(whichAlarms);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002747 if (b.size() == 0) {
2748 mAlarmBatches.remove(i);
2749 }
2750 }
2751 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
2752 final Alarm a = mPendingWhileIdleAlarms.get(i);
Dianne Hackborne07641d2016-11-09 15:07:23 -08002753 if (a.uid == uid) {
2754 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2755 mPendingWhileIdleAlarms.remove(i);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002756 }
2757 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002758 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
2759 if (mPendingBackgroundAlarms.keyAt(i) == uid) {
2760 mPendingBackgroundAlarms.removeAt(i);
2761 }
2762 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002763 if (didRemove) {
2764 if (DEBUG_BATCH) {
2765 Slog.v(TAG, "remove(package) changed bounds; rebatching");
2766 }
2767 rebatchAllAlarmsLocked(true);
2768 rescheduleKernelAlarmsLocked();
2769 updateNextAlarmClockLocked();
2770 }
2771 }
2772
Adam Lesinski182f73f2013-12-05 16:48:06 -08002773 void removeUserLocked(int userHandle) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08002774 if (userHandle == UserHandle.USER_SYSTEM) {
2775 Slog.wtf(TAG, "removeForStoppedLocked: Shouldn't for user=" + userHandle);
2776 return;
2777 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002778 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002779 final Predicate<Alarm> whichAlarms =
2780 (Alarm a) -> UserHandle.getUserId(a.creatorUid) == userHandle;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002781 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2782 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002783 didRemove |= b.remove(whichAlarms);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002784 if (b.size() == 0) {
2785 mAlarmBatches.remove(i);
2786 }
2787 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002788 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002789 if (UserHandle.getUserId(mPendingWhileIdleAlarms.get(i).creatorUid)
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002790 == userHandle) {
2791 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2792 mPendingWhileIdleAlarms.remove(i);
2793 }
2794 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002795 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
2796 if (UserHandle.getUserId(mPendingBackgroundAlarms.keyAt(i)) == userHandle) {
2797 mPendingBackgroundAlarms.removeAt(i);
2798 }
2799 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002800 for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
2801 if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
2802 mLastAllowWhileIdleDispatch.removeAt(i);
2803 }
2804 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002805
2806 if (didRemove) {
2807 if (DEBUG_BATCH) {
2808 Slog.v(TAG, "remove(user) changed bounds; rebatching");
2809 }
2810 rebatchAllAlarmsLocked(true);
2811 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02002812 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002813 }
2814 }
2815
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002816 void interactiveStateChangedLocked(boolean interactive) {
2817 if (mInteractive != interactive) {
2818 mInteractive = interactive;
2819 final long nowELAPSED = SystemClock.elapsedRealtime();
2820 if (interactive) {
2821 if (mPendingNonWakeupAlarms.size() > 0) {
2822 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
2823 mTotalDelayTime += thisDelayTime;
2824 if (mMaxDelayTime < thisDelayTime) {
2825 mMaxDelayTime = thisDelayTime;
2826 }
2827 deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
2828 mPendingNonWakeupAlarms.clear();
2829 }
2830 if (mNonInteractiveStartTime > 0) {
2831 long dur = nowELAPSED - mNonInteractiveStartTime;
2832 if (dur > mNonInteractiveTime) {
2833 mNonInteractiveTime = dur;
2834 }
2835 }
2836 } else {
2837 mNonInteractiveStartTime = nowELAPSED;
2838 }
2839 }
2840 }
2841
Adam Lesinski182f73f2013-12-05 16:48:06 -08002842 boolean lookForPackageLocked(String packageName) {
2843 for (int i = 0; i < mAlarmBatches.size(); i++) {
2844 Batch b = mAlarmBatches.get(i);
2845 if (b.hasPackage(packageName)) {
2846 return true;
2847 }
2848 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002849 for (int i = 0; i < mPendingWhileIdleAlarms.size(); i++) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002850 final Alarm a = mPendingWhileIdleAlarms.get(i);
2851 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002852 return true;
2853 }
2854 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002855 return false;
2856 }
2857
2858 private void setLocked(int type, long when) {
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -08002859 if (mNativeData != 0) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08002860 // The kernel never triggers alarms with negative wakeup times
2861 // so we ensure they are positive.
2862 long alarmSeconds, alarmNanoseconds;
2863 if (when < 0) {
2864 alarmSeconds = 0;
2865 alarmNanoseconds = 0;
2866 } else {
2867 alarmSeconds = when / 1000;
2868 alarmNanoseconds = (when % 1000) * 1000 * 1000;
2869 }
Kweku Adams61e03292017-10-19 14:27:12 -07002870
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -08002871 set(mNativeData, type, alarmSeconds, alarmNanoseconds);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002872 } else {
2873 Message msg = Message.obtain();
2874 msg.what = ALARM_EVENT;
Kweku Adams61e03292017-10-19 14:27:12 -07002875
Adam Lesinski182f73f2013-12-05 16:48:06 -08002876 mHandler.removeMessages(ALARM_EVENT);
2877 mHandler.sendMessageAtTime(msg, when);
2878 }
2879 }
2880
Dianne Hackborn043fcd92010-10-06 14:27:34 -07002881 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Kweku Adams61e03292017-10-19 14:27:12 -07002882 String prefix, String label, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 for (int i=list.size()-1; i>=0; i--) {
2884 Alarm a = list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002885 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
2886 pw.print(": "); pw.println(a);
Kweku Adams61e03292017-10-19 14:27:12 -07002887 a.dump(pw, prefix + " ", nowELAPSED, nowRTC, sdf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 }
2889 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002890
2891 private static final String labelForType(int type) {
2892 switch (type) {
2893 case RTC: return "RTC";
2894 case RTC_WAKEUP : return "RTC_WAKEUP";
2895 case ELAPSED_REALTIME : return "ELAPSED";
2896 case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP";
Christopher Tatee0a22b32013-07-11 14:43:13 -07002897 }
2898 return "--unknown--";
2899 }
2900
2901 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002902 String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07002903 for (int i=list.size()-1; i>=0; i--) {
2904 Alarm a = list.get(i);
2905 final String label = labelForType(a.type);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002906 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
2907 pw.print(": "); pw.println(a);
Kweku Adams61e03292017-10-19 14:27:12 -07002908 a.dump(pw, prefix + " ", nowELAPSED, nowRTC, sdf);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002909 }
2910 }
2911
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002912 private boolean isBackgroundRestricted(Alarm alarm) {
Suprabh Shuklac25447d2018-01-19 16:43:35 -08002913 final boolean allowWhileIdle = (alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002914 if (alarm.alarmClock != null) {
2915 // Don't block alarm clocks
2916 return false;
2917 }
2918 if (alarm.operation != null
2919 && (alarm.operation.isActivity() || alarm.operation.isForegroundService())) {
2920 // Don't block starting foreground components
2921 return false;
2922 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08002923 final String sourcePackage = alarm.sourcePackage;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002924 final int sourceUid = alarm.creatorUid;
Suprabh Shuklac25447d2018-01-19 16:43:35 -08002925 return mForceAppStandbyTracker.areAlarmsRestricted(sourceUid, sourcePackage,
2926 allowWhileIdle);
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002927 }
2928
Greg Hackmanna1d6f922013-12-09 16:56:53 -08002929 private native long init();
2930 private native void close(long nativeData);
2931 private native void set(long nativeData, int type, long seconds, long nanoseconds);
2932 private native int waitForAlarm(long nativeData);
Greg Hackmann38bf5142014-02-19 16:39:36 -08002933 private native int setKernelTime(long nativeData, long millis);
Greg Hackmanna1d6f922013-12-09 16:56:53 -08002934 private native int setKernelTimezone(long nativeData, int minuteswest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002936 boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002937 final long nowRTC) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002938 boolean hasWakeup = false;
Christopher Tatee0a22b32013-07-11 14:43:13 -07002939 // batches are temporally sorted, so we need only pull from the
2940 // start of the list until we either empty it or hit a batch
2941 // that is not yet deliverable
Christopher Tate6578ad12013-09-24 17:12:46 -07002942 while (mAlarmBatches.size() > 0) {
2943 Batch batch = mAlarmBatches.get(0);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002944 if (batch.start > nowELAPSED) {
2945 // Everything else is scheduled for the future
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002946 break;
2947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002948
Christopher Tatee0a22b32013-07-11 14:43:13 -07002949 // We will (re)schedule some alarms now; don't let that interfere
2950 // with delivery of this current batch
2951 mAlarmBatches.remove(0);
Dianne Hackborn390517b2013-05-30 15:03:32 -07002952
Christopher Tatee0a22b32013-07-11 14:43:13 -07002953 final int N = batch.size();
2954 for (int i = 0; i < N; i++) {
2955 Alarm alarm = batch.get(i);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002956
2957 if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
2958 // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
2959 // schedule such alarms.
Suprabh Shuklac25447d2018-01-19 16:43:35 -08002960 final long lastTime = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, 0);
2961 final boolean dozing = mPendingIdleUntil != null;
2962 final boolean ebs = mForceAppStandbyTracker.isForceAllAppsStandbyEnabled();
2963 final long minTime;
2964 if (!dozing && !ebs) {
2965 minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
2966 } else if (dozing) {
2967 minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
2968 } else if (mUseAllowWhileIdleShortTime.get(alarm.creatorUid)) {
2969 // if the last allow-while-idle went off while uid was fg, or the uid
2970 // recently came into fg, don't block the alarm for long.
2971 minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
2972 } else {
2973 minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
2974 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002975 if (nowELAPSED < minTime) {
2976 // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
2977 // alarm went off for this app. Reschedule the alarm to be in the
2978 // correct time period.
2979 alarm.whenElapsed = minTime;
2980 if (alarm.maxWhenElapsed < minTime) {
2981 alarm.maxWhenElapsed = minTime;
2982 }
Dianne Hackbornae78bf82015-10-26 13:33:20 -07002983 if (RECORD_DEVICE_IDLE_ALARMS) {
2984 IdleDispatchEntry ent = new IdleDispatchEntry();
2985 ent.uid = alarm.uid;
2986 ent.pkg = alarm.operation.getCreatorPackage();
2987 ent.tag = alarm.operation.getTag("");
2988 ent.op = "RESCHEDULE";
2989 ent.elapsedRealtime = nowELAPSED;
2990 ent.argRealtime = lastTime;
2991 mAllowWhileIdleDispatches.add(ent);
2992 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002993 setImplLocked(alarm, true, false);
2994 continue;
2995 }
2996 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002997 if (isBackgroundRestricted(alarm)) {
2998 // Alarms with FLAG_WAKE_FROM_IDLE or mPendingIdleUntil alarm are not deferred
2999 if (DEBUG_BG_LIMIT) {
3000 Slog.d(TAG, "Deferring alarm " + alarm + " due to user forced app standby");
3001 }
3002 ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(alarm.creatorUid);
3003 if (alarmsForUid == null) {
3004 alarmsForUid = new ArrayList<>();
3005 mPendingBackgroundAlarms.put(alarm.creatorUid, alarmsForUid);
3006 }
3007 alarmsForUid.add(alarm);
3008 continue;
3009 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003010
Christopher Tatee0a22b32013-07-11 14:43:13 -07003011 alarm.count = 1;
3012 triggerList.add(alarm);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003013 if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
3014 EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003015 alarm.statsTag);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003016 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003017 if (mPendingIdleUntil == alarm) {
3018 mPendingIdleUntil = null;
3019 rebatchAllAlarmsLocked(false);
3020 restorePendingWhileIdleAlarmsLocked();
3021 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003022 if (mNextWakeFromIdle == alarm) {
3023 mNextWakeFromIdle = null;
3024 rebatchAllAlarmsLocked(false);
3025 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003026
3027 // Recurring alarms may have passed several alarm intervals while the
3028 // phone was asleep or off, so pass a trigger count when sending them.
3029 if (alarm.repeatInterval > 0) {
3030 // this adjustment will be zero if we're late by
3031 // less than one full repeat interval
Suprabh Shukla75edab12018-01-29 14:09:06 -08003032 alarm.count += (nowELAPSED - alarm.requestedWhenElapsed) / alarm.repeatInterval;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003033
3034 // Also schedule its next recurrence
3035 final long delta = alarm.count * alarm.repeatInterval;
3036 final long nextElapsed = alarm.whenElapsed + delta;
Christopher Tate3e04b472013-10-21 17:51:31 -07003037 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
Christopher Tatee0a22b32013-07-11 14:43:13 -07003038 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
Christopher Tate14a7bb02015-10-01 10:24:31 -07003039 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
3040 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
Christopher Tate864d42e2014-12-02 11:48:53 -08003041 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003042
Christopher Tate864d42e2014-12-02 11:48:53 -08003043 if (alarm.wakeup) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003044 hasWakeup = true;
3045 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02003046
3047 // We removed an alarm clock. Let the caller recompute the next alarm clock.
3048 if (alarm.alarmClock != null) {
3049 mNextAlarmClockMayChange = true;
3050 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07003051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003053
Christopher Tate1590f1e2014-10-02 17:27:57 -07003054 // This is a new alarm delivery set; bump the sequence number to indicate that
3055 // all apps' alarm delivery classes should be recalculated.
3056 mCurrentSeq++;
3057 calculateDeliveryPriorities(triggerList);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003058 Collections.sort(triggerList, mAlarmDispatchComparator);
3059
3060 if (localLOGV) {
3061 for (int i=0; i<triggerList.size(); i++) {
3062 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
3063 }
3064 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003065
3066 return hasWakeup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003067 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 /**
3070 * This Comparator sorts Alarms into increasing time order.
3071 */
3072 public static class IncreasingTimeOrder implements Comparator<Alarm> {
3073 public int compare(Alarm a1, Alarm a2) {
jinho.park1acd32a2015-05-27 14:44:18 +09003074 long when1 = a1.whenElapsed;
3075 long when2 = a2.whenElapsed;
Charles Tsaicdaaeee2015-05-20 18:16:48 +08003076 if (when1 > when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 return 1;
3078 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +08003079 if (when1 < when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003080 return -1;
3081 }
3082 return 0;
3083 }
3084 }
Kweku Adams61e03292017-10-19 14:27:12 -07003085
Makoto Onuki2206af32017-11-21 16:25:35 -08003086 @VisibleForTesting
3087 static class Alarm {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003088 public final int type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003089 public final long origWhen;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003090 public final boolean wakeup;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003091 public final PendingIntent operation;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003092 public final IAlarmListener listener;
3093 public final String listenerTag;
3094 public final String statsTag;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003095 public final WorkSource workSource;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003096 public final int flags;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003097 public final AlarmManager.AlarmClockInfo alarmClock;
3098 public final int uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003099 public final int creatorUid;
3100 public final String packageName;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003101 public final String sourcePackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 public int count;
3103 public long when;
Christopher Tate3e04b472013-10-21 17:51:31 -07003104 public long windowLength;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003105 public long whenElapsed; // 'when' in the elapsed time base
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003106 public long maxWhenElapsed; // also in the elapsed time base
Suprabh Shukla75edab12018-01-29 14:09:06 -08003107 public final long requestedWhenElapsed; // original expiry time requested by the app
3108 public final long requestedMaxWhenElapsed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003109 public long repeatInterval;
Christopher Tate1590f1e2014-10-02 17:27:57 -07003110 public PriorityClass priorityClass;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003111
Christopher Tate3e04b472013-10-21 17:51:31 -07003112 public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003113 long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag,
3114 WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info,
3115 int _uid, String _pkgName) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07003116 type = _type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003117 origWhen = _when;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003118 wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
3119 || _type == AlarmManager.RTC_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003120 when = _when;
3121 whenElapsed = _whenElapsed;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003122 requestedWhenElapsed = _whenElapsed;
Christopher Tate3e04b472013-10-21 17:51:31 -07003123 windowLength = _windowLength;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003124 maxWhenElapsed = _maxWhen;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003125 requestedMaxWhenElapsed = _maxWhen;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003126 repeatInterval = _interval;
3127 operation = _op;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003128 listener = _rec;
3129 listenerTag = _listenerTag;
3130 statsTag = makeTag(_op, _listenerTag, _type);
David Christieebe51fc2013-07-26 13:23:29 -07003131 workSource = _ws;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003132 flags = _flags;
Adrian Roosc42a1e12014-07-07 23:35:53 +02003133 alarmClock = _info;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003134 uid = _uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003135 packageName = _pkgName;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003136 sourcePackage = (operation != null) ? operation.getCreatorPackage() : packageName;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003137 creatorUid = (operation != null) ? operation.getCreatorUid() : uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003139
Christopher Tate14a7bb02015-10-01 10:24:31 -07003140 public static String makeTag(PendingIntent pi, String tag, int type) {
3141 final String alarmString = type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
3142 ? "*walarm*:" : "*alarm*:";
3143 return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag);
3144 }
3145
3146 public WakeupEvent makeWakeupEvent(long nowRTC) {
3147 return new WakeupEvent(nowRTC, creatorUid,
3148 (operation != null)
3149 ? operation.getIntent().getAction()
3150 : ("<listener>:" + listenerTag));
3151 }
3152
3153 // Returns true if either matches
3154 public boolean matches(PendingIntent pi, IAlarmListener rec) {
3155 return (operation != null)
3156 ? operation.equals(pi)
Lorenzo Colitti9b43ce02015-11-22 22:00:08 +09003157 : rec != null && listener.asBinder().equals(rec.asBinder());
Christopher Tate14a7bb02015-10-01 10:24:31 -07003158 }
3159
3160 public boolean matches(String packageName) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08003161 return packageName.equals(sourcePackage);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003162 }
3163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003164 @Override
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003165 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003166 StringBuilder sb = new StringBuilder(128);
3167 sb.append("Alarm{");
3168 sb.append(Integer.toHexString(System.identityHashCode(this)));
3169 sb.append(" type ");
3170 sb.append(type);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003171 sb.append(" when ");
3172 sb.append(when);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003173 sb.append(" ");
Suprabh Shukla75edab12018-01-29 14:09:06 -08003174 sb.append(sourcePackage);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003175 sb.append('}');
3176 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003177 }
3178
Kweku Adams61e03292017-10-19 14:27:12 -07003179 public void dump(PrintWriter pw, String prefix, long nowELAPSED, long nowRTC,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003180 SimpleDateFormat sdf) {
3181 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003182 pw.print(prefix); pw.print("tag="); pw.println(statsTag);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003183 pw.print(prefix); pw.print("type="); pw.print(type);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003184 pw.print(" requestedWhenElapsed="); TimeUtils.formatDuration(
Suprabh Shukla75edab12018-01-29 14:09:06 -08003185 requestedWhenElapsed, nowELAPSED, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003186 pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
3187 nowELAPSED, pw);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003188 pw.print(" when=");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003189 if (isRtc) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003190 pw.print(sdf.format(new Date(when)));
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003191 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003192 TimeUtils.formatDuration(when, nowELAPSED, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003193 }
3194 pw.println();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003195 pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003196 pw.print(" repeatInterval="); pw.print(repeatInterval);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003197 pw.print(" count="); pw.print(count);
3198 pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003199 if (alarmClock != null) {
3200 pw.print(prefix); pw.println("Alarm clock:");
3201 pw.print(prefix); pw.print(" triggerTime=");
3202 pw.println(sdf.format(new Date(alarmClock.getTriggerTime())));
3203 pw.print(prefix); pw.print(" showIntent="); pw.println(alarmClock.getShowIntent());
3204 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003205 pw.print(prefix); pw.print("operation="); pw.println(operation);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003206 if (listener != null) {
3207 pw.print(prefix); pw.print("listener="); pw.println(listener.asBinder());
3208 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003209 }
Kweku Adams61e03292017-10-19 14:27:12 -07003210
3211 public void writeToProto(ProtoOutputStream proto, long fieldId, long nowElapsed,
3212 long nowRTC) {
3213 final long token = proto.start(fieldId);
3214
3215 proto.write(AlarmProto.TAG, statsTag);
3216 proto.write(AlarmProto.TYPE, type);
Kweku Adams923ec432017-12-11 18:05:38 -08003217 proto.write(AlarmProto.TIME_UNTIL_WHEN_ELAPSED_MS, whenElapsed - nowElapsed);
Kweku Adams61e03292017-10-19 14:27:12 -07003218 proto.write(AlarmProto.WINDOW_LENGTH_MS, windowLength);
3219 proto.write(AlarmProto.REPEAT_INTERVAL_MS, repeatInterval);
3220 proto.write(AlarmProto.COUNT, count);
3221 proto.write(AlarmProto.FLAGS, flags);
3222 if (alarmClock != null) {
3223 alarmClock.writeToProto(proto, AlarmProto.ALARM_CLOCK);
3224 }
3225 if (operation != null) {
3226 operation.writeToProto(proto, AlarmProto.OPERATION);
3227 }
3228 if (listener != null) {
3229 proto.write(AlarmProto.LISTENER, listener.asBinder().toString());
3230 }
3231
3232 proto.end(token);
3233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234 }
Christopher Tate18a75f12013-07-01 18:18:59 -07003235
Christopher Tatee0a22b32013-07-11 14:43:13 -07003236 void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) {
3237 final int numBatches = batches.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07003238 for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) {
3239 Batch b = batches.get(nextBatch);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003240 if (b.start > nowELAPSED) {
Christopher Tate18a75f12013-07-01 18:18:59 -07003241 break;
3242 }
3243
Christopher Tatee0a22b32013-07-11 14:43:13 -07003244 final int numAlarms = b.alarms.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07003245 for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) {
3246 Alarm a = b.alarms.get(nextAlarm);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003247 mRecentWakeups.add(a.makeWakeupEvent(nowRTC));
Christopher Tatee0a22b32013-07-11 14:43:13 -07003248 }
Christopher Tate18a75f12013-07-01 18:18:59 -07003249 }
3250 }
3251
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003252 long currentNonWakeupFuzzLocked(long nowELAPSED) {
3253 long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
3254 if (timeSinceOn < 5*60*1000) {
3255 // If the screen has been off for 5 minutes, only delay by at most two minutes.
3256 return 2*60*1000;
3257 } else if (timeSinceOn < 30*60*1000) {
3258 // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
3259 return 15*60*1000;
3260 } else {
3261 // Otherwise, we will delay by at most an hour.
3262 return 60*60*1000;
3263 }
3264 }
3265
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003266 static int fuzzForDuration(long duration) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003267 if (duration < 15*60*1000) {
3268 // If the duration until the time is less than 15 minutes, the maximum fuzz
3269 // is the duration.
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003270 return (int)duration;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003271 } else if (duration < 90*60*1000) {
3272 // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes,
3273 return 15*60*1000;
3274 } else {
3275 // Otherwise, we will fuzz by at most half an hour.
3276 return 30*60*1000;
3277 }
3278 }
3279
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003280 boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
3281 if (mInteractive) {
3282 return false;
3283 }
3284 if (mLastAlarmDeliveryTime <= 0) {
3285 return false;
3286 }
minho.choo649acab2014-12-12 16:13:55 +09003287 if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003288 // This is just a little paranoia, if somehow we have pending non-wakeup alarms
3289 // and the next delivery time is in the past, then just deliver them all. This
3290 // avoids bugs where we get stuck in a loop trying to poll for alarms.
3291 return false;
3292 }
3293 long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
3294 return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
3295 }
3296
3297 void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
3298 mLastAlarmDeliveryTime = nowELAPSED;
3299 for (int i=0; i<triggerList.size(); i++) {
3300 Alarm alarm = triggerList.get(i);
Dianne Hackborna750a632015-06-16 17:18:23 -07003301 final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
Tim Murray175c0f92017-11-28 15:01:04 -08003302 if (alarm.wakeup) {
3303 Trace.traceBegin(Trace.TRACE_TAG_POWER, "Dispatch wakeup alarm to " + alarm.packageName);
3304 } else {
3305 Trace.traceBegin(Trace.TRACE_TAG_POWER, "Dispatch non-wakeup alarm to " + alarm.packageName);
3306 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003307 try {
Christopher Tate2ff5a732014-09-18 13:47:57 -07003308 if (localLOGV) {
3309 Slog.v(TAG, "sending alarm " + alarm);
3310 }
Dianne Hackborn1e383822015-04-10 14:02:33 -07003311 if (RECORD_ALARMS_IN_HISTORY) {
Narayan Kamath695cf722017-12-21 18:32:47 +00003312 ActivityManager.noteAlarmStart(alarm.operation, alarm.workSource, alarm.uid,
3313 alarm.statsTag);
Dianne Hackborn1e383822015-04-10 14:02:33 -07003314 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003315 mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003316 } catch (RuntimeException e) {
3317 Slog.w(TAG, "Failure sending alarm.", e);
3318 }
Tim Murray175c0f92017-11-28 15:01:04 -08003319 Trace.traceEnd(Trace.TRACE_TAG_POWER);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003320 }
3321 }
3322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 private class AlarmThread extends Thread
3324 {
3325 public AlarmThread()
3326 {
3327 super("AlarmManager");
3328 }
Kweku Adams61e03292017-10-19 14:27:12 -07003329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003330 public void run()
3331 {
Dianne Hackborn390517b2013-05-30 15:03:32 -07003332 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
3333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003334 while (true)
3335 {
Greg Hackmanna1d6f922013-12-09 16:56:53 -08003336 int result = waitForAlarm(mNativeData);
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07003337 mLastWakeup = SystemClock.elapsedRealtime();
Dianne Hackborn390517b2013-05-30 15:03:32 -07003338
3339 triggerList.clear();
3340
Dianne Hackbornc3527222015-05-13 14:03:20 -07003341 final long nowRTC = System.currentTimeMillis();
3342 final long nowELAPSED = SystemClock.elapsedRealtime();
3343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 if ((result & TIME_CHANGED_MASK) != 0) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07003345 // The kernel can give us spurious time change notifications due to
3346 // small adjustments it makes internally; we want to filter those out.
3347 final long lastTimeChangeClockTime;
3348 final long expectedClockTime;
Dianne Hackborn998e6082014-09-11 19:13:23 -07003349 synchronized (mLock) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07003350 lastTimeChangeClockTime = mLastTimeChangeClockTime;
3351 expectedClockTime = lastTimeChangeClockTime
3352 + (nowELAPSED - mLastTimeChangeRealtime);
Dianne Hackborn998e6082014-09-11 19:13:23 -07003353 }
Christopher Tate2b6e459e2017-02-17 14:33:52 -08003354 if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-1000)
3355 || nowRTC > (expectedClockTime+1000)) {
3356 // The change is by at least +/- 1000 ms (or this is the first change),
Dianne Hackbornc3527222015-05-13 14:03:20 -07003357 // let's do it!
3358 if (DEBUG_BATCH) {
3359 Slog.v(TAG, "Time changed notification from kernel; rebatching");
3360 }
3361 removeImpl(mTimeTickSender);
Christopher Tatecf024712016-08-05 13:21:45 -07003362 removeImpl(mDateChangeSender);
Dianne Hackbornc3527222015-05-13 14:03:20 -07003363 rebatchAllAlarms();
3364 mClockReceiver.scheduleTimeTickEvent();
Christopher Tatecf024712016-08-05 13:21:45 -07003365 mClockReceiver.scheduleDateChangedEvent();
Dianne Hackbornc3527222015-05-13 14:03:20 -07003366 synchronized (mLock) {
3367 mNumTimeChanged++;
3368 mLastTimeChangeClockTime = nowRTC;
3369 mLastTimeChangeRealtime = nowELAPSED;
3370 }
3371 Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
3372 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
Christopher Tate2b6e459e2017-02-17 14:33:52 -08003373 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
Chad Brubaker291df4f2017-03-14 10:23:02 -07003374 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
3375 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Dianne Hackbornc3527222015-05-13 14:03:20 -07003376 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
3377
3378 // The world has changed on us, so we need to re-evaluate alarms
3379 // regardless of whether the kernel has told us one went off.
3380 result |= IS_WAKEUP_MASK;
3381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383
Dianne Hackbornc3527222015-05-13 14:03:20 -07003384 if (result != TIME_CHANGED_MASK) {
3385 // If this was anything besides just a time change, then figure what if
3386 // anything to do about alarms.
3387 synchronized (mLock) {
3388 if (localLOGV) Slog.v(
3389 TAG, "Checking for alarms... rtc=" + nowRTC
3390 + ", elapsed=" + nowELAPSED);
Christopher Tate18a75f12013-07-01 18:18:59 -07003391
Dianne Hackbornc3527222015-05-13 14:03:20 -07003392 if (WAKEUP_STATS) {
3393 if ((result & IS_WAKEUP_MASK) != 0) {
3394 long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
3395 int n = 0;
3396 for (WakeupEvent event : mRecentWakeups) {
3397 if (event.when > newEarliest) break;
3398 n++; // number of now-stale entries at the list head
3399 }
3400 for (int i = 0; i < n; i++) {
3401 mRecentWakeups.remove();
3402 }
Christopher Tate18a75f12013-07-01 18:18:59 -07003403
Dianne Hackbornc3527222015-05-13 14:03:20 -07003404 recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003405 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003406 }
Dianne Hackbornc3527222015-05-13 14:03:20 -07003407
3408 boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
3409 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
3410 // if there are no wakeup alarms and the screen is off, we can
3411 // delay what we have so far until the future.
3412 if (mPendingNonWakeupAlarms.size() == 0) {
3413 mStartCurrentDelayTime = nowELAPSED;
3414 mNextNonWakeupDeliveryTime = nowELAPSED
3415 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
3416 }
3417 mPendingNonWakeupAlarms.addAll(triggerList);
3418 mNumDelayedAlarms += triggerList.size();
3419 rescheduleKernelAlarmsLocked();
3420 updateNextAlarmClockLocked();
3421 } else {
3422 // now deliver the alarm intents; if there are pending non-wakeup
3423 // alarms, we need to merge them in to the list. note we don't
3424 // just deliver them first because we generally want non-wakeup
3425 // alarms delivered after wakeup alarms.
Dianne Hackbornc3527222015-05-13 14:03:20 -07003426 if (mPendingNonWakeupAlarms.size() > 0) {
3427 calculateDeliveryPriorities(mPendingNonWakeupAlarms);
3428 triggerList.addAll(mPendingNonWakeupAlarms);
3429 Collections.sort(triggerList, mAlarmDispatchComparator);
3430 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
3431 mTotalDelayTime += thisDelayTime;
3432 if (mMaxDelayTime < thisDelayTime) {
3433 mMaxDelayTime = thisDelayTime;
3434 }
3435 mPendingNonWakeupAlarms.clear();
3436 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003437 final ArraySet<Pair<String, Integer>> triggerPackages =
3438 new ArraySet<>();
3439 for (int i = 0; i < triggerList.size(); i++) {
3440 final Alarm a = triggerList.get(i);
3441 if (!UserHandle.isCore(a.creatorUid)) {
3442 triggerPackages.add(Pair.create(
3443 a.sourcePackage, UserHandle.getUserId(a.creatorUid)));
Suprabh Shukla75edab12018-01-29 14:09:06 -08003444 }
3445 }
Dianne Hackbornc3527222015-05-13 14:03:20 -07003446 deliverAlarmsLocked(triggerList, nowELAPSED);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003447 reorderAlarmsBasedOnStandbyBuckets(triggerPackages);
3448 rescheduleKernelAlarmsLocked();
3449 updateNextAlarmClockLocked();
Dianne Hackbornc3527222015-05-13 14:03:20 -07003450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451 }
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07003452
3453 } else {
3454 // Just in case -- even though no wakeup flag was set, make sure
3455 // we have updated the kernel to the next alarm time.
Christopher Tate7b5b7cb2016-07-07 14:41:36 -07003456 synchronized (mLock) {
3457 rescheduleKernelAlarmsLocked();
3458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003459 }
3460 }
3461 }
3462 }
Christopher Tatec4a07d12012-04-06 14:19:13 -07003463
David Christieebe51fc2013-07-26 13:23:29 -07003464 /**
3465 * Attribute blame for a WakeLock.
3466 * @param pi PendingIntent to attribute blame to if ws is null.
3467 * @param ws WorkSource to attribute blame.
Christopher Tate14a7bb02015-10-01 10:24:31 -07003468 * @param knownUid attribution uid; < 0 if we need to derive it from the PendingIntent sender
David Christieebe51fc2013-07-26 13:23:29 -07003469 */
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003470 void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003471 int knownUid, boolean first) {
Christopher Tatec4a07d12012-04-06 14:19:13 -07003472 try {
Dianne Hackborna1bd7922014-03-21 11:07:11 -07003473 final boolean unimportant = pi == mTimeTickSender;
3474 mWakeLock.setUnimportantForLogging(unimportant);
Dianne Hackborn4590e522014-03-24 13:36:46 -07003475 if (first || mLastWakeLockUnimportantForLogging) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003476 mWakeLock.setHistoryTag(tag);
Dianne Hackborn4590e522014-03-24 13:36:46 -07003477 } else {
3478 mWakeLock.setHistoryTag(null);
3479 }
3480 mLastWakeLockUnimportantForLogging = unimportant;
David Christieebe51fc2013-07-26 13:23:29 -07003481 if (ws != null) {
3482 mWakeLock.setWorkSource(ws);
3483 return;
3484 }
3485
Christopher Tate14a7bb02015-10-01 10:24:31 -07003486 final int uid = (knownUid >= 0)
3487 ? knownUid
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003488 : ActivityManager.getService().getUidForIntentSender(pi.getTarget());
Christopher Tatec4a07d12012-04-06 14:19:13 -07003489 if (uid >= 0) {
3490 mWakeLock.setWorkSource(new WorkSource(uid));
3491 return;
3492 }
3493 } catch (Exception e) {
3494 }
3495
3496 // Something went wrong; fall back to attributing the lock to the OS
3497 mWakeLock.setWorkSource(null);
3498 }
3499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003500 private class AlarmHandler extends Handler {
3501 public static final int ALARM_EVENT = 1;
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003502 public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2;
3503 public static final int LISTENER_TIMEOUT = 3;
3504 public static final int REPORT_ALARMS_ACTIVE = 4;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003505 public static final int APP_STANDBY_BUCKET_CHANGED = 5;
3506 public static final int APP_STANDBY_PAROLE_CHANGED = 6;
Kweku Adams61e03292017-10-19 14:27:12 -07003507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003508 public AlarmHandler() {
3509 }
Kweku Adams61e03292017-10-19 14:27:12 -07003510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003511 public void handleMessage(Message msg) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003512 switch (msg.what) {
3513 case ALARM_EVENT: {
3514 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
3515 synchronized (mLock) {
3516 final long nowRTC = System.currentTimeMillis();
3517 final long nowELAPSED = SystemClock.elapsedRealtime();
3518 triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
3519 updateNextAlarmClockLocked();
3520 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02003521
Christopher Tate14a7bb02015-10-01 10:24:31 -07003522 // now trigger the alarms without the lock held
3523 for (int i=0; i<triggerList.size(); i++) {
3524 Alarm alarm = triggerList.get(i);
3525 try {
3526 alarm.operation.send();
3527 } catch (PendingIntent.CanceledException e) {
3528 if (alarm.repeatInterval > 0) {
3529 // This IntentSender is no longer valid, but this
3530 // is a repeating alarm, so toss the hoser.
3531 removeImpl(alarm.operation);
3532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 }
3534 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003535 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003537
3538 case SEND_NEXT_ALARM_CLOCK_CHANGED:
3539 sendNextAlarmClockChanged();
3540 break;
3541
3542 case LISTENER_TIMEOUT:
3543 mDeliveryTracker.alarmTimedOut((IBinder) msg.obj);
3544 break;
3545
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003546 case REPORT_ALARMS_ACTIVE:
3547 if (mLocalDeviceIdleController != null) {
3548 mLocalDeviceIdleController.setAlarmsActive(msg.arg1 != 0);
3549 }
3550 break;
3551
Suprabh Shukla75edab12018-01-29 14:09:06 -08003552 case APP_STANDBY_PAROLE_CHANGED:
3553 synchronized (mLock) {
3554 mAppStandbyParole = (Boolean) msg.obj;
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003555 if (reorderAlarmsBasedOnStandbyBuckets(null)) {
3556 rescheduleKernelAlarmsLocked();
3557 updateNextAlarmClockLocked();
3558 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08003559 }
3560 break;
3561
3562 case APP_STANDBY_BUCKET_CHANGED:
3563 synchronized (mLock) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003564 final ArraySet<Pair<String, Integer>> filterPackages = new ArraySet<>();
3565 filterPackages.add(Pair.create((String) msg.obj, msg.arg1));
3566 if (reorderAlarmsBasedOnStandbyBuckets(filterPackages)) {
3567 rescheduleKernelAlarmsLocked();
3568 updateNextAlarmClockLocked();
3569 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08003570 }
3571 break;
3572
Christopher Tate14a7bb02015-10-01 10:24:31 -07003573 default:
3574 // nope, just ignore it
3575 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003576 }
3577 }
3578 }
Kweku Adams61e03292017-10-19 14:27:12 -07003579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 class ClockReceiver extends BroadcastReceiver {
3581 public ClockReceiver() {
3582 IntentFilter filter = new IntentFilter();
3583 filter.addAction(Intent.ACTION_TIME_TICK);
3584 filter.addAction(Intent.ACTION_DATE_CHANGED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003585 getContext().registerReceiver(this, filter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 }
Kweku Adams61e03292017-10-19 14:27:12 -07003587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003588 @Override
3589 public void onReceive(Context context, Intent intent) {
3590 if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
Christopher Tate385e4982013-07-23 18:22:29 -07003591 if (DEBUG_BATCH) {
3592 Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
3593 }
Christopher Tate12cf0b62018-01-05 18:40:14 -08003594 synchronized (mLock) {
3595 mLastTickReceived = System.currentTimeMillis();
3596 }
Christopher Tate385e4982013-07-23 18:22:29 -07003597 scheduleTimeTickEvent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003598 } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
3599 // Since the kernel does not keep track of DST, we need to
3600 // reset the TZ information at the beginning of each day
3601 // based off of the current Zone gmt offset + userspace tracked
3602 // daylight savings information.
3603 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
Lavettacn Xiaoc84cc4f2010-08-30 12:47:23 +02003604 int gmtOffset = zone.getOffset(System.currentTimeMillis());
Greg Hackmanna1d6f922013-12-09 16:56:53 -08003605 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
Christopher Tate385e4982013-07-23 18:22:29 -07003606 scheduleDateChangedEvent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 }
3608 }
Kweku Adams61e03292017-10-19 14:27:12 -07003609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 public void scheduleTimeTickEvent() {
Paul Westbrook51608a52011-08-25 13:18:54 -07003611 final long currentTime = System.currentTimeMillis();
Sungmin Choi563914a2013-01-10 17:28:40 +09003612 final long nextTime = 60000 * ((currentTime / 60000) + 1);
Paul Westbrook51608a52011-08-25 13:18:54 -07003613
3614 // Schedule this event for the amount of time that it would take to get to
3615 // the top of the next minute.
Sungmin Choi563914a2013-01-10 17:28:40 +09003616 final long tickEventDelay = nextTime - currentTime;
Paul Westbrook51608a52011-08-25 13:18:54 -07003617
David Christieebe51fc2013-07-26 13:23:29 -07003618 final WorkSource workSource = null; // Let system take blame for time tick events.
Adam Lesinski182f73f2013-12-05 16:48:06 -08003619 setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003620 0, mTimeTickSender, null, null, AlarmManager.FLAG_STANDALONE, workSource,
3621 null, Process.myUid(), "android");
Christopher Tate12cf0b62018-01-05 18:40:14 -08003622
3623 // Finally, remember when we set the tick alarm
3624 synchronized (mLock) {
3625 mLastTickSet = currentTime;
3626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 }
Christopher Tate385e4982013-07-23 18:22:29 -07003628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003629 public void scheduleDateChangedEvent() {
3630 Calendar calendar = Calendar.getInstance();
3631 calendar.setTimeInMillis(System.currentTimeMillis());
Christopher Tateafa8b982016-08-10 16:15:48 -07003632 calendar.set(Calendar.HOUR_OF_DAY, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003633 calendar.set(Calendar.MINUTE, 0);
3634 calendar.set(Calendar.SECOND, 0);
3635 calendar.set(Calendar.MILLISECOND, 0);
3636 calendar.add(Calendar.DAY_OF_MONTH, 1);
David Christieebe51fc2013-07-26 13:23:29 -07003637
3638 final WorkSource workSource = null; // Let system take blame for date change events.
Christopher Tate14a7bb02015-10-01 10:24:31 -07003639 setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
3640 AlarmManager.FLAG_STANDALONE, workSource, null,
3641 Process.myUid(), "android");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 }
3643 }
Kweku Adams61e03292017-10-19 14:27:12 -07003644
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003645 class InteractiveStateReceiver extends BroadcastReceiver {
3646 public InteractiveStateReceiver() {
3647 IntentFilter filter = new IntentFilter();
3648 filter.addAction(Intent.ACTION_SCREEN_OFF);
3649 filter.addAction(Intent.ACTION_SCREEN_ON);
3650 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
3651 getContext().registerReceiver(this, filter);
3652 }
3653
3654 @Override
3655 public void onReceive(Context context, Intent intent) {
3656 synchronized (mLock) {
3657 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
3658 }
3659 }
3660 }
3661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 class UninstallReceiver extends BroadcastReceiver {
3663 public UninstallReceiver() {
3664 IntentFilter filter = new IntentFilter();
3665 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
3666 filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003667 filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 filter.addDataScheme("package");
Adam Lesinski182f73f2013-12-05 16:48:06 -08003669 getContext().registerReceiver(this, filter);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003670 // Register for events related to sdcard installation.
3671 IntentFilter sdFilter = new IntentFilter();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08003672 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003673 sdFilter.addAction(Intent.ACTION_USER_STOPPED);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003674 sdFilter.addAction(Intent.ACTION_UID_REMOVED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003675 getContext().registerReceiver(this, sdFilter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 }
Kweku Adams61e03292017-10-19 14:27:12 -07003677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003678 @Override
3679 public void onReceive(Context context, Intent intent) {
Christopher Tate1d99c392017-12-07 16:54:04 -08003680 final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003681 synchronized (mLock) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003682 String action = intent.getAction();
3683 String pkgList[] = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003684 if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
3685 pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3686 for (String packageName : pkgList) {
3687 if (lookForPackageLocked(packageName)) {
3688 setResultCode(Activity.RESULT_OK);
3689 return;
3690 }
3691 }
3692 return;
3693 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003694 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003695 } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
3696 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
3697 if (userHandle >= 0) {
3698 removeUserLocked(userHandle);
Suprabh Shukla75edab12018-01-29 14:09:06 -08003699 for (int i = mLastAlarmDeliveredForPackage.size() - 1; i >= 0; i--) {
3700 final Pair<String, Integer> packageUser =
3701 mLastAlarmDeliveredForPackage.keyAt(i);
3702 if (packageUser.second == userHandle) {
3703 mLastAlarmDeliveredForPackage.removeAt(i);
3704 }
3705 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003706 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003707 } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003708 if (uid >= 0) {
3709 mLastAllowWhileIdleDispatch.delete(uid);
3710 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003711 } else {
Dianne Hackborn409578f2010-03-10 17:23:43 -08003712 if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
3713 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
3714 // This package is being updated; don't kill its alarms.
3715 return;
3716 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003717 Uri data = intent.getData();
3718 if (data != null) {
3719 String pkg = data.getSchemeSpecificPart();
3720 if (pkg != null) {
3721 pkgList = new String[]{pkg};
3722 }
3723 }
3724 }
3725 if (pkgList != null && (pkgList.length > 0)) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08003726 for (int i = mLastAlarmDeliveredForPackage.size() - 1; i >= 0; i--) {
3727 Pair<String, Integer> packageUser = mLastAlarmDeliveredForPackage.keyAt(i);
3728 if (ArrayUtils.contains(pkgList, packageUser.first)
3729 && packageUser.second == UserHandle.getUserId(uid)) {
3730 mLastAlarmDeliveredForPackage.removeAt(i);
3731 }
3732 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003733 for (String pkg : pkgList) {
Christopher Tate1d99c392017-12-07 16:54:04 -08003734 if (uid >= 0) {
3735 // package-removed case
3736 removeLocked(uid);
3737 } else {
3738 // external-applications-unavailable etc case
3739 removeLocked(pkg);
3740 }
Christopher Tate1590f1e2014-10-02 17:27:57 -07003741 mPriorities.remove(pkg);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003742 for (int i=mBroadcastStats.size()-1; i>=0; i--) {
3743 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
3744 if (uidStats.remove(pkg) != null) {
3745 if (uidStats.size() <= 0) {
3746 mBroadcastStats.removeAt(i);
3747 }
3748 }
3749 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751 }
3752 }
3753 }
3754 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003755
3756 final class UidObserver extends IUidObserver.Stub {
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003757 @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003758 }
3759
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003760 @Override public void onUidGone(int uid, boolean disabled) {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003761 synchronized (mLock) {
Suprabh Shuklac25447d2018-01-19 16:43:35 -08003762 mUseAllowWhileIdleShortTime.delete(uid);
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003763 if (disabled) {
Dianne Hackborne07641d2016-11-09 15:07:23 -08003764 removeForStoppedLocked(uid);
3765 }
3766 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003767 }
3768
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003769 @Override public void onUidActive(int uid) {
Suprabh Shuklac25447d2018-01-19 16:43:35 -08003770 synchronized (mLock) {
3771 mUseAllowWhileIdleShortTime.put(uid, true);
3772 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003773 }
3774
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003775 @Override public void onUidIdle(int uid, boolean disabled) {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003776 synchronized (mLock) {
3777 if (disabled) {
Dianne Hackborne07641d2016-11-09 15:07:23 -08003778 removeForStoppedLocked(uid);
3779 }
Dianne Hackbornde9c48b2015-11-20 14:49:59 -08003780 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003781 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003782
3783 @Override public void onUidCachedChanged(int uid, boolean cached) {
3784 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003785 };
3786
Suprabh Shukla75edab12018-01-29 14:09:06 -08003787 /**
3788 * Tracking of app assignments to standby buckets
3789 */
3790 final class AppStandbyTracker extends UsageStatsManagerInternal.AppIdleStateChangeListener {
3791 @Override
3792 public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
3793 boolean idle, int bucket) {
3794 if (DEBUG_STANDBY) {
3795 Slog.d(TAG, "Package " + packageName + " for user " + userId + " now in bucket " +
3796 bucket);
3797 }
3798 mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003799 mHandler.obtainMessage(AlarmHandler.APP_STANDBY_BUCKET_CHANGED, userId, -1, packageName)
3800 .sendToTarget();
Suprabh Shukla75edab12018-01-29 14:09:06 -08003801 }
3802
3803 @Override
3804 public void onParoleStateChanged(boolean isParoleOn) {
3805 if (DEBUG_STANDBY) {
3806 Slog.d(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
3807 }
3808 mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
3809 mHandler.removeMessages(AlarmHandler.APP_STANDBY_PAROLE_CHANGED);
3810 mHandler.obtainMessage(AlarmHandler.APP_STANDBY_PAROLE_CHANGED,
3811 Boolean.valueOf(isParoleOn)).sendToTarget();
3812 }
3813 };
3814
Makoto Onuki2206af32017-11-21 16:25:35 -08003815 private final Listener mForceAppStandbyListener = new Listener() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003816 @Override
Makoto Onuki2206af32017-11-21 16:25:35 -08003817 public void unblockAllUnrestrictedAlarms() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003818 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -08003819 sendAllUnrestrictedPendingBackgroundAlarmsLocked();
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003820 }
3821 }
Makoto Onuki2206af32017-11-21 16:25:35 -08003822
3823 @Override
3824 public void unblockAlarmsForUid(int uid) {
3825 synchronized (mLock) {
3826 sendPendingBackgroundAlarmsLocked(uid, null);
3827 }
3828 }
3829
3830 @Override
3831 public void unblockAlarmsForUidPackage(int uid, String packageName) {
3832 synchronized (mLock) {
3833 sendPendingBackgroundAlarmsLocked(uid, packageName);
3834 }
3835 }
3836 };
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 private final BroadcastStats getStatsLocked(PendingIntent pi) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003839 String pkg = pi.getCreatorPackage();
3840 int uid = pi.getCreatorUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07003841 return getStatsLocked(uid, pkg);
3842 }
3843
3844 private final BroadcastStats getStatsLocked(int uid, String pkgName) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003845 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
3846 if (uidStats == null) {
3847 uidStats = new ArrayMap<String, BroadcastStats>();
3848 mBroadcastStats.put(uid, uidStats);
3849 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003850 BroadcastStats bs = uidStats.get(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003851 if (bs == null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003852 bs = new BroadcastStats(uid, pkgName);
3853 uidStats.put(pkgName, bs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 }
3855 return bs;
3856 }
Dianne Hackborn81038902012-11-26 17:04:09 -08003857
Christopher Tate21e9f192017-08-08 13:49:11 -07003858 /**
3859 * Canonical count of (operation.send() - onSendFinished()) and
3860 * listener send/complete/timeout invocations.
3861 * Guarded by the usual lock.
3862 */
3863 @GuardedBy("mLock")
3864 private int mSendCount = 0;
3865 @GuardedBy("mLock")
Christopher Tateeabba732017-08-17 17:12:52 -07003866 private int mSendFinishCount = 0;
3867 @GuardedBy("mLock")
Christopher Tate21e9f192017-08-08 13:49:11 -07003868 private int mListenerCount = 0;
Christopher Tateeabba732017-08-17 17:12:52 -07003869 @GuardedBy("mLock")
3870 private int mListenerFinishCount = 0;
Christopher Tate21e9f192017-08-08 13:49:11 -07003871
Christopher Tate14a7bb02015-10-01 10:24:31 -07003872 class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished {
Christopher Tate21e9f192017-08-08 13:49:11 -07003873
Christopher Tate14a7bb02015-10-01 10:24:31 -07003874 private InFlight removeLocked(PendingIntent pi, Intent intent) {
3875 for (int i = 0; i < mInFlight.size(); i++) {
Christopher Tatedb9ae422017-08-21 11:24:30 -07003876 if (mInFlight.get(i).mPendingIntent == pi) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003877 return mInFlight.remove(i);
3878 }
3879 }
3880 mLog.w("No in-flight alarm for " + pi + " " + intent);
3881 return null;
3882 }
3883
3884 private InFlight removeLocked(IBinder listener) {
3885 for (int i = 0; i < mInFlight.size(); i++) {
3886 if (mInFlight.get(i).mListener == listener) {
3887 return mInFlight.remove(i);
3888 }
3889 }
3890 mLog.w("No in-flight alarm for listener " + listener);
3891 return null;
3892 }
3893
3894 private void updateStatsLocked(InFlight inflight) {
3895 final long nowELAPSED = SystemClock.elapsedRealtime();
3896 BroadcastStats bs = inflight.mBroadcastStats;
3897 bs.nesting--;
3898 if (bs.nesting <= 0) {
3899 bs.nesting = 0;
3900 bs.aggregateTime += nowELAPSED - bs.startTime;
3901 }
3902 FilterStats fs = inflight.mFilterStats;
3903 fs.nesting--;
3904 if (fs.nesting <= 0) {
3905 fs.nesting = 0;
3906 fs.aggregateTime += nowELAPSED - fs.startTime;
3907 }
3908 if (RECORD_ALARMS_IN_HISTORY) {
Narayan Kamath695cf722017-12-21 18:32:47 +00003909 ActivityManager.noteAlarmFinish(inflight.mPendingIntent, inflight.mWorkSource,
3910 inflight.mUid, inflight.mTag);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003911 }
3912 }
3913
3914 private void updateTrackingLocked(InFlight inflight) {
3915 if (inflight != null) {
3916 updateStatsLocked(inflight);
3917 }
3918 mBroadcastRefCount--;
Makoto Onuki3e7d8452017-03-02 15:33:17 -08003919 if (DEBUG_WAKELOCK) {
3920 Slog.d(TAG, "mBroadcastRefCount -> " + mBroadcastRefCount);
3921 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003922 if (mBroadcastRefCount == 0) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003923 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07003924 mWakeLock.release();
3925 if (mInFlight.size() > 0) {
3926 mLog.w("Finished all dispatches with " + mInFlight.size()
3927 + " remaining inflights");
3928 for (int i=0; i<mInFlight.size(); i++) {
3929 mLog.w(" Remaining #" + i + ": " + mInFlight.get(i));
3930 }
3931 mInFlight.clear();
3932 }
3933 } else {
3934 // the next of our alarms is now in flight. reattribute the wakelock.
3935 if (mInFlight.size() > 0) {
3936 InFlight inFlight = mInFlight.get(0);
3937 setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
3938 inFlight.mAlarmType, inFlight.mTag, -1, false);
3939 } else {
3940 // should never happen
3941 mLog.w("Alarm wakelock still held but sent queue empty");
3942 mWakeLock.setWorkSource(null);
3943 }
3944 }
3945 }
3946
3947 /**
3948 * Callback that arrives when a direct-call alarm reports that delivery has finished
3949 */
3950 @Override
3951 public void alarmComplete(IBinder who) {
3952 if (who == null) {
Christopher Tate21e9f192017-08-08 13:49:11 -07003953 mLog.w("Invalid alarmComplete: uid=" + Binder.getCallingUid()
Christopher Tate14a7bb02015-10-01 10:24:31 -07003954 + " pid=" + Binder.getCallingPid());
3955 return;
3956 }
3957
3958 final long ident = Binder.clearCallingIdentity();
3959 try {
3960 synchronized (mLock) {
3961 mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who);
3962 InFlight inflight = removeLocked(who);
3963 if (inflight != null) {
3964 if (DEBUG_LISTENER_CALLBACK) {
3965 Slog.i(TAG, "alarmComplete() from " + who);
3966 }
3967 updateTrackingLocked(inflight);
Christopher Tateeabba732017-08-17 17:12:52 -07003968 mListenerFinishCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003969 } else {
3970 // Delivery timed out, and the timeout handling already took care of
3971 // updating our tracking here, so we needn't do anything further.
3972 if (DEBUG_LISTENER_CALLBACK) {
3973 Slog.i(TAG, "Late alarmComplete() from " + who);
3974 }
3975 }
3976 }
3977 } finally {
3978 Binder.restoreCallingIdentity(ident);
3979 }
3980 }
3981
3982 /**
3983 * Callback that arrives when a PendingIntent alarm has finished delivery
3984 */
3985 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003986 public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
3987 String resultData, Bundle resultExtras) {
3988 synchronized (mLock) {
Christopher Tateeabba732017-08-17 17:12:52 -07003989 mSendFinishCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003990 updateTrackingLocked(removeLocked(pi, intent));
3991 }
3992 }
3993
3994 /**
3995 * Timeout of a direct-call alarm delivery
3996 */
3997 public void alarmTimedOut(IBinder who) {
3998 synchronized (mLock) {
3999 InFlight inflight = removeLocked(who);
Dianne Hackborn81038902012-11-26 17:04:09 -08004000 if (inflight != null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004001 // TODO: implement ANR policy for the target
4002 if (DEBUG_LISTENER_CALLBACK) {
4003 Slog.i(TAG, "Alarm listener " + who + " timed out in delivery");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004005 updateTrackingLocked(inflight);
Christopher Tateeabba732017-08-17 17:12:52 -07004006 mListenerFinishCount++;
Dianne Hackborn81038902012-11-26 17:04:09 -08004007 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004008 if (DEBUG_LISTENER_CALLBACK) {
4009 Slog.i(TAG, "Spurious timeout of listener " + who);
4010 }
Christopher Tate21e9f192017-08-08 13:49:11 -07004011 mLog.w("Spurious timeout of listener " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004012 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004013 }
4014 }
4015
4016 /**
4017 * Deliver an alarm and set up the post-delivery handling appropriately
4018 */
4019 public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
4020 if (alarm.operation != null) {
4021 // PendingIntent alarm
Christopher Tate21e9f192017-08-08 13:49:11 -07004022 mSendCount++;
Christopher Tate12cf0b62018-01-05 18:40:14 -08004023
4024 if (alarm.priorityClass.priority == PRIO_TICK) {
4025 mLastTickIssued = nowELAPSED;
4026 }
4027
Christopher Tate14a7bb02015-10-01 10:24:31 -07004028 try {
4029 alarm.operation.send(getContext(), 0,
4030 mBackgroundIntent.putExtra(
4031 Intent.EXTRA_ALARM_COUNT, alarm.count),
4032 mDeliveryTracker, mHandler, null,
4033 allowWhileIdle ? mIdleOptions : null);
4034 } catch (PendingIntent.CanceledException e) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08004035 if (alarm.operation == mTimeTickSender) {
4036 Slog.wtf(TAG, "mTimeTickSender canceled");
4037 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004038 if (alarm.repeatInterval > 0) {
4039 // This IntentSender is no longer valid, but this
4040 // is a repeating alarm, so toss it
4041 removeImpl(alarm.operation);
4042 }
Christopher Tate7f2a0352015-12-08 10:24:33 -08004043 // No actual delivery was possible, so the delivery tracker's
4044 // 'finished' callback won't be invoked. We also don't need
4045 // to do any wakelock or stats tracking, so we have nothing
4046 // left to do here but go on to the next thing.
Christopher Tateeabba732017-08-17 17:12:52 -07004047 mSendFinishCount++;
Christopher Tate7f2a0352015-12-08 10:24:33 -08004048 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004049 }
4050 } else {
4051 // Direct listener callback alarm
Christopher Tate21e9f192017-08-08 13:49:11 -07004052 mListenerCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004053 try {
4054 if (DEBUG_LISTENER_CALLBACK) {
4055 Slog.v(TAG, "Alarm to uid=" + alarm.uid
4056 + " listener=" + alarm.listener.asBinder());
4057 }
4058 alarm.listener.doAlarm(this);
4059 mHandler.sendMessageDelayed(
4060 mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
4061 alarm.listener.asBinder()),
4062 mConstants.LISTENER_TIMEOUT);
4063 } catch (Exception e) {
4064 if (DEBUG_LISTENER_CALLBACK) {
4065 Slog.i(TAG, "Alarm undeliverable to listener "
4066 + alarm.listener.asBinder(), e);
4067 }
Christopher Tate7f2a0352015-12-08 10:24:33 -08004068 // As in the PendingIntent.CanceledException case, delivery of the
4069 // alarm was not possible, so we have no wakelock or timeout or
4070 // stats management to do. It threw before we posted the delayed
4071 // timeout message, so we're done here.
Christopher Tateeabba732017-08-17 17:12:52 -07004072 mListenerFinishCount++;
Christopher Tate7f2a0352015-12-08 10:24:33 -08004073 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004074 }
4075 }
4076
4077 // The alarm is now in flight; now arrange wakelock and stats tracking
Makoto Onuki3e7d8452017-03-02 15:33:17 -08004078 if (DEBUG_WAKELOCK) {
4079 Slog.d(TAG, "mBroadcastRefCount -> " + (mBroadcastRefCount + 1));
4080 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004081 if (mBroadcastRefCount == 0) {
4082 setWakelockWorkSource(alarm.operation, alarm.workSource,
4083 alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1,
4084 true);
4085 mWakeLock.acquire();
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004086 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07004087 }
4088 final InFlight inflight = new InFlight(AlarmManagerService.this,
4089 alarm.operation, alarm.listener, alarm.workSource, alarm.uid,
4090 alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
4091 mInFlight.add(inflight);
4092 mBroadcastRefCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004093 if (allowWhileIdle) {
4094 // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
Suprabh Shuklac25447d2018-01-19 16:43:35 -08004095 mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED);
4096 if (mForceAppStandbyTracker.isInForeground(alarm.creatorUid)) {
4097 mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true);
4098 } else {
4099 mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false);
4100 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004101 if (RECORD_DEVICE_IDLE_ALARMS) {
4102 IdleDispatchEntry ent = new IdleDispatchEntry();
4103 ent.uid = alarm.uid;
4104 ent.pkg = alarm.packageName;
4105 ent.tag = alarm.statsTag;
4106 ent.op = "DELIVER";
4107 ent.elapsedRealtime = nowELAPSED;
4108 mAllowWhileIdleDispatches.add(ent);
4109 }
4110 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08004111 if (!UserHandle.isCore(alarm.creatorUid)) {
4112 final Pair<String, Integer> packageUser = Pair.create(alarm.sourcePackage,
4113 UserHandle.getUserId(alarm.creatorUid));
4114 mLastAlarmDeliveredForPackage.put(packageUser, nowELAPSED);
4115 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004116
4117 final BroadcastStats bs = inflight.mBroadcastStats;
4118 bs.count++;
4119 if (bs.nesting == 0) {
4120 bs.nesting = 1;
4121 bs.startTime = nowELAPSED;
4122 } else {
4123 bs.nesting++;
4124 }
4125 final FilterStats fs = inflight.mFilterStats;
4126 fs.count++;
4127 if (fs.nesting == 0) {
4128 fs.nesting = 1;
4129 fs.startTime = nowELAPSED;
4130 } else {
4131 fs.nesting++;
4132 }
4133 if (alarm.type == ELAPSED_REALTIME_WAKEUP
4134 || alarm.type == RTC_WAKEUP) {
4135 bs.numWakeup++;
4136 fs.numWakeup++;
Narayan Kamath695cf722017-12-21 18:32:47 +00004137 ActivityManager.noteWakeupAlarm(
4138 alarm.operation, alarm.workSource, alarm.uid, alarm.packageName,
4139 alarm.statsTag);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004140 }
4141 }
4142 }
4143}