blob: 85eeba0565066687be67fe7e25b26ead24e227f5 [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
Jeff Sharkey9911a282018-02-14 22:29:11 -070019import static android.app.AlarmManager.ELAPSED_REALTIME;
20import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
21import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE;
22import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
23import static android.app.AlarmManager.RTC;
24import static android.app.AlarmManager.RTC_WAKEUP;
25
Suprabh Shukla75edab12018-01-29 14:09:06 -080026import android.annotation.UserIdInt;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080027import android.app.Activity;
Adrian Roosc42a1e12014-07-07 23:35:53 +020028import android.app.ActivityManager;
Christopher Tate57ceaaa2013-07-19 16:30:43 -070029import android.app.AlarmManager;
Christopher Tate14a7bb02015-10-01 10:24:31 -070030import android.app.AppOpsManager;
Dianne Hackborna750a632015-06-16 17:18:23 -070031import android.app.BroadcastOptions;
Christopher Tate14a7bb02015-10-01 10:24:31 -070032import android.app.IAlarmCompleteListener;
33import android.app.IAlarmListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.app.IAlarmManager;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070035import android.app.IUidObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.app.PendingIntent;
Suprabh Shukla75edab12018-01-29 14:09:06 -080037import android.app.usage.UsageStatsManager;
38import android.app.usage.UsageStatsManagerInternal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.content.BroadcastReceiver;
Dianne Hackborna750a632015-06-16 17:18:23 -070040import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.content.Context;
42import android.content.Intent;
43import android.content.IntentFilter;
Christopher Tatebb9cce52017-04-18 14:19:43 -070044import android.content.pm.ApplicationInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.content.pm.PackageManager;
Christopher Tatebb9cce52017-04-18 14:19:43 -070046import android.content.pm.PackageManager.NameNotFoundException;
47import android.content.pm.PermissionInfo;
Dianne Hackborna750a632015-06-16 17:18:23 -070048import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.net.Uri;
50import android.os.Binder;
51import android.os.Bundle;
Christopher Tate247571462017-04-10 11:45:05 -070052import android.os.Environment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import android.os.Handler;
Adam Lesinski182f73f2013-12-05 16:48:06 -080054import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.os.Message;
Jeff Sharkey9911a282018-02-14 22:29:11 -070056import android.os.ParcelableException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.os.PowerManager;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -070058import android.os.Process;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070059import android.os.RemoteException;
mswest463f4c99d2018-02-01 10:13:10 -080060import android.os.ResultReceiver;
61import android.os.ShellCallback;
62import android.os.ShellCommand;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.os.SystemClock;
64import android.os.SystemProperties;
Tim Murray175c0f92017-11-28 15:01:04 -080065import android.os.Trace;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070066import android.os.UserHandle;
Christopher Tatec4a07d12012-04-06 14:19:13 -070067import android.os.WorkSource;
Adrian Roosc42a1e12014-07-07 23:35:53 +020068import android.provider.Settings;
Christopher Tate8b98ade2018-02-09 11:13:19 -080069import android.system.Os;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.text.TextUtils;
Adrian Roosc42a1e12014-07-07 23:35:53 +020071import android.text.format.DateFormat;
Christopher Tate22e919d2018-02-16 16:16:50 -080072import android.text.format.DateUtils;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080073import android.util.ArrayMap;
Suprabh Shukla92994ab2018-01-31 17:39:30 -080074import android.util.ArraySet;
Dianne Hackborna750a632015-06-16 17:18:23 -070075import android.util.KeyValueListParser;
Adrian Roosc42a1e12014-07-07 23:35:53 +020076import android.util.Log;
Jeff Sharkey9911a282018-02-14 22:29:11 -070077import android.util.NtpTrustedTime;
Suprabh Shukla75edab12018-01-29 14:09:06 -080078import android.util.Pair;
Joe Onorato8a9b2202010-02-26 18:56:32 -080079import android.util.Slog;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080080import android.util.SparseArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +020081import android.util.SparseBooleanArray;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -070082import android.util.SparseLongArray;
Dianne Hackborn043fcd92010-10-06 14:27:34 -070083import android.util.TimeUtils;
Kweku Adams61e03292017-10-19 14:27:12 -070084import android.util.proto.ProtoOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085
Jeff Sharkey9911a282018-02-14 22:29:11 -070086import com.android.internal.annotations.GuardedBy;
87import com.android.internal.annotations.VisibleForTesting;
88import com.android.internal.util.ArrayUtils;
89import com.android.internal.util.DumpUtils;
90import com.android.internal.util.LocalLog;
Makoto Onuki49392d32018-04-11 13:51:02 -070091import com.android.internal.util.StatLogger;
Jeff Sharkey9911a282018-02-14 22:29:11 -070092import com.android.server.AppStateTracker.Listener;
93
Christopher Tate4cb338d2013-07-26 13:11:31 -070094import java.io.ByteArrayOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import java.io.FileDescriptor;
96import java.io.PrintWriter;
Dianne Hackborn043fcd92010-10-06 14:27:34 -070097import java.text.SimpleDateFormat;
Jeff Sharkey9911a282018-02-14 22:29:11 -070098import java.time.DateTimeException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import java.util.ArrayList;
Dianne Hackborn81038902012-11-26 17:04:09 -0800100import java.util.Arrays;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import java.util.Calendar;
102import java.util.Collections;
103import java.util.Comparator;
Mike Lockwood1f7b4132009-11-20 15:12:51 -0500104import java.util.Date;
Christopher Tate1590f1e2014-10-02 17:27:57 -0700105import java.util.HashMap;
Christopher Tate18a75f12013-07-01 18:18:59 -0700106import java.util.LinkedList;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200107import java.util.Locale;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700108import java.util.Random;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import java.util.TimeZone;
John Spurlock604a5ee2015-06-01 12:27:22 -0400110import java.util.TreeSet;
Makoto Onuki2206af32017-11-21 16:25:35 -0800111import java.util.function.Predicate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112
Makoto Onuki2206af32017-11-21 16:25:35 -0800113/**
114 * Alarm manager implementaion.
115 *
116 * Unit test:
117 atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java
118 */
Adam Lesinski182f73f2013-12-05 16:48:06 -0800119class AlarmManagerService extends SystemService {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700120 private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
121 private static final int RTC_MASK = 1 << RTC;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800122 private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700123 private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800124 static final int TIME_CHANGED_MASK = 1 << 16;
125 static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
Christopher Tateb8849c12011-02-08 13:39:01 -0800126
Christopher Tatee0a22b32013-07-11 14:43:13 -0700127 // Mask for testing whether a given alarm type is wakeup vs non-wakeup
Adam Lesinski182f73f2013-12-05 16:48:06 -0800128 static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
Christopher Tateb8849c12011-02-08 13:39:01 -0800129
Adam Lesinski182f73f2013-12-05 16:48:06 -0800130 static final String TAG = "AlarmManager";
Adam Lesinski182f73f2013-12-05 16:48:06 -0800131 static final boolean localLOGV = false;
132 static final boolean DEBUG_BATCH = localLOGV || false;
133 static final boolean DEBUG_VALIDATE = localLOGV || false;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200134 static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700135 static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
Makoto Onuki3e7d8452017-03-02 15:33:17 -0800136 static final boolean DEBUG_WAKELOCK = localLOGV || false;
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700137 static final boolean DEBUG_BG_LIMIT = localLOGV || false;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800138 static final boolean DEBUG_STANDBY = localLOGV || false;
Dianne Hackborn1e383822015-04-10 14:02:33 -0700139 static final boolean RECORD_ALARMS_IN_HISTORY = true;
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700140 static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800141 static final int ALARM_EVENT = 1;
142 static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
Adrian Roosc42a1e12014-07-07 23:35:53 +0200143
Christopher Tate14a7bb02015-10-01 10:24:31 -0700144 private final Intent mBackgroundIntent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800146 static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700147
Adam Lesinski182f73f2013-12-05 16:48:06 -0800148 static final boolean WAKEUP_STATS = false;
Christopher Tate18a75f12013-07-01 18:18:59 -0700149
Christopher Tate24cd46f2016-02-02 14:28:01 -0800150 private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT =
151 new Intent(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)
Christopher Tate50191db2017-05-09 16:02:25 -0700152 .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
153 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Adrian Roosc42a1e12014-07-07 23:35:53 +0200154
Adam Lesinski182f73f2013-12-05 16:48:06 -0800155 final LocalLog mLog = new LocalLog(TAG);
Dianne Hackborn81038902012-11-26 17:04:09 -0800156
Christopher Tate14a7bb02015-10-01 10:24:31 -0700157 AppOpsManager mAppOps;
Dianne Hackborn627dfa12015-11-11 18:10:30 -0800158 DeviceIdleController.LocalService mLocalDeviceIdleController;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800159 private UsageStatsManagerInternal mUsageStatsManagerInternal;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700160
Adam Lesinski182f73f2013-12-05 16:48:06 -0800161 final Object mLock = new Object();
Dianne Hackborn81038902012-11-26 17:04:09 -0800162
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700163 // List of alarms per uid deferred due to user applied background restrictions on the source app
164 SparseArray<ArrayList<Alarm>> mPendingBackgroundAlarms = new SparseArray<>();
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -0800165 long mNativeData;
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800166 private long mNextWakeup;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700167 private long mNextNonWakeup;
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -0700168 private long mLastWakeupSet;
169 private long mLastWakeup;
Christopher Tate8b98ade2018-02-09 11:13:19 -0800170 private long mLastTrigger;
Christopher Tate12cf0b62018-01-05 18:40:14 -0800171 private long mLastTickSet;
172 private long mLastTickIssued; // elapsed
173 private long mLastTickReceived;
Makoto Onuki5d93b832018-01-10 16:12:39 -0800174 private long mLastTickAdded;
175 private long mLastTickRemoved;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800176 int mBroadcastRefCount = 0;
177 PowerManager.WakeLock mWakeLock;
Dianne Hackborna1bd7922014-03-21 11:07:11 -0700178 boolean mLastWakeLockUnimportantForLogging;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700179 ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
180 ArrayList<InFlight> mInFlight = new ArrayList<>();
Adam Lesinski182f73f2013-12-05 16:48:06 -0800181 final AlarmHandler mHandler = new AlarmHandler();
182 ClockReceiver mClockReceiver;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700183 InteractiveStateReceiver mInteractiveStateReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 private UninstallReceiver mUninstallReceiver;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700185 final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
Adam Lesinski182f73f2013-12-05 16:48:06 -0800186 PendingIntent mTimeTickSender;
187 PendingIntent mDateChangeSender;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700188 Random mRandom;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700189 boolean mInteractive = true;
190 long mNonInteractiveStartTime;
191 long mNonInteractiveTime;
192 long mLastAlarmDeliveryTime;
193 long mStartCurrentDelayTime;
194 long mNextNonWakeupDeliveryTime;
Dianne Hackbornc3527222015-05-13 14:03:20 -0700195 long mLastTimeChangeClockTime;
196 long mLastTimeChangeRealtime;
Dianne Hackborn998e6082014-09-11 19:13:23 -0700197 int mNumTimeChanged;
Dianne Hackborn81038902012-11-26 17:04:09 -0800198
Christopher Tatebb9cce52017-04-18 14:19:43 -0700199 // Bookkeeping about the identity of the "System UI" package, determined at runtime.
200
201 /**
202 * This permission must be defined by the canonical System UI package,
203 * with protection level "signature".
204 */
205 private static final String SYSTEM_UI_SELF_PERMISSION =
206 "android.permission.systemui.IDENTITY";
207
208 /**
209 * At boot we use SYSTEM_UI_SELF_PERMISSION to look up the definer's uid.
210 */
211 int mSystemUiUid;
212
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700213 /**
214 * For each uid, this is the last time we dispatched an "allow while idle" alarm,
Kweku Adams61e03292017-10-19 14:27:12 -0700215 * used to determine the earliest we can dispatch the next such alarm. Times are in the
216 * 'elapsed' timebase.
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700217 */
218 final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
219
Suprabh Shuklac25447d2018-01-19 16:43:35 -0800220 /**
221 * For each uid, we store whether the last allow-while-idle alarm was dispatched while
222 * the uid was in foreground or not. We will use the allow_while_idle_short_time in such cases.
223 */
224 final SparseBooleanArray mUseAllowWhileIdleShortTime = new SparseBooleanArray();
225
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700226 final static class IdleDispatchEntry {
227 int uid;
228 String pkg;
229 String tag;
230 String op;
231 long elapsedRealtime;
232 long argRealtime;
233 }
234 final ArrayList<IdleDispatchEntry> mAllowWhileIdleDispatches = new ArrayList();
235
Suprabh Shukla75edab12018-01-29 14:09:06 -0800236 interface Stats {
237 int REBATCH_ALL_ALARMS = 0;
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800238 int REORDER_ALARMS_FOR_STANDBY = 1;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800239 }
240
241 private final StatLogger mStatLogger = new StatLogger(new String[] {
242 "REBATCH_ALL_ALARMS",
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800243 "REORDER_ALARMS_FOR_STANDBY",
Suprabh Shukla75edab12018-01-29 14:09:06 -0800244 });
245
Dianne Hackborna750a632015-06-16 17:18:23 -0700246 /**
247 * Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
248 */
249 Bundle mIdleOptions;
250
Jose Lima235510e2014-08-13 12:50:01 -0700251 private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
252 new SparseArray<>();
253 private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
254 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200255 private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
256 new SparseBooleanArray();
257 private boolean mNextAlarmClockMayChange;
258
259 // May only use on mHandler's thread, locking not required.
Jose Lima235510e2014-08-13 12:50:01 -0700260 private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
261 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200262
Makoto Onukie4918212018-02-06 11:30:15 -0800263 private AppStateTracker mAppStateTracker;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800264 private boolean mAppStandbyParole;
265 private ArrayMap<Pair<String, Integer>, Long> mLastAlarmDeliveredForPackage = new ArrayMap<>();
Makoto Onuki2206af32017-11-21 16:25:35 -0800266
Dianne Hackborna750a632015-06-16 17:18:23 -0700267 /**
268 * All times are in milliseconds. These constants are kept synchronized with the system
269 * global Settings. Any access to this class or its fields should be done while
270 * holding the AlarmManagerService.mLock lock.
271 */
272 private final class Constants extends ContentObserver {
273 // Key names stored in the settings value.
274 private static final String KEY_MIN_FUTURITY = "min_futurity";
275 private static final String KEY_MIN_INTERVAL = "min_interval";
Christopher Tate22e919d2018-02-16 16:16:50 -0800276 private static final String KEY_MAX_INTERVAL = "max_interval";
Dianne Hackborna750a632015-06-16 17:18:23 -0700277 private static final String KEY_ALLOW_WHILE_IDLE_SHORT_TIME = "allow_while_idle_short_time";
278 private static final String KEY_ALLOW_WHILE_IDLE_LONG_TIME = "allow_while_idle_long_time";
279 private static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
280 = "allow_while_idle_whitelist_duration";
Christopher Tate14a7bb02015-10-01 10:24:31 -0700281 private static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
Dianne Hackborna750a632015-06-16 17:18:23 -0700282
Suprabh Shukla75edab12018-01-29 14:09:06 -0800283 // Keys for specifying throttling delay based on app standby bucketing
284 private final String[] KEYS_APP_STANDBY_DELAY = {
285 "standby_active_delay",
286 "standby_working_delay",
287 "standby_frequent_delay",
288 "standby_rare_delay",
289 "standby_never_delay",
290 };
291
Dianne Hackborna750a632015-06-16 17:18:23 -0700292 private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
293 private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
Christopher Tate22e919d2018-02-16 16:16:50 -0800294 private static final long DEFAULT_MAX_INTERVAL = 365 * DateUtils.DAY_IN_MILLIS;
Christopher Tateaa244da2015-08-27 15:57:57 -0700295 private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
Dianne Hackborn7682b262015-10-26 17:51:57 -0700296 private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000;
Dianne Hackborna750a632015-06-16 17:18:23 -0700297 private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700298 private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800299 private final long[] DEFAULT_APP_STANDBY_DELAYS = {
300 0, // Active
301 6 * 60_000, // Working
302 30 * 60_000, // Frequent
303 2 * 60 * 60_000, // Rare
304 10 * 24 * 60 * 60_000 // Never
305 };
Christopher Tate14a7bb02015-10-01 10:24:31 -0700306
Dianne Hackborna750a632015-06-16 17:18:23 -0700307 // Minimum futurity of a new alarm
308 public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
309
310 // Minimum alarm recurrence interval
311 public long MIN_INTERVAL = DEFAULT_MIN_INTERVAL;
312
Christopher Tate22e919d2018-02-16 16:16:50 -0800313 // Maximum alarm recurrence interval
314 public long MAX_INTERVAL = DEFAULT_MAX_INTERVAL;
315
Dianne Hackborna750a632015-06-16 17:18:23 -0700316 // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
317 public long ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME;
318
319 // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
320 public long ALLOW_WHILE_IDLE_LONG_TIME = DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME;
321
322 // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
323 public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
324 = DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
325
Christopher Tate14a7bb02015-10-01 10:24:31 -0700326 // Direct alarm listener callback timeout
327 public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
328
Suprabh Shukla75edab12018-01-29 14:09:06 -0800329 public long[] APP_STANDBY_MIN_DELAYS = new long[DEFAULT_APP_STANDBY_DELAYS.length];
330
Dianne Hackborna750a632015-06-16 17:18:23 -0700331 private ContentResolver mResolver;
332 private final KeyValueListParser mParser = new KeyValueListParser(',');
333 private long mLastAllowWhileIdleWhitelistDuration = -1;
334
335 public Constants(Handler handler) {
336 super(handler);
Dianne Hackborna750a632015-06-16 17:18:23 -0700337 updateAllowWhileIdleWhitelistDurationLocked();
338 }
339
340 public void start(ContentResolver resolver) {
341 mResolver = resolver;
342 mResolver.registerContentObserver(Settings.Global.getUriFor(
343 Settings.Global.ALARM_MANAGER_CONSTANTS), false, this);
344 updateConstants();
345 }
346
Dianne Hackborna750a632015-06-16 17:18:23 -0700347 public void updateAllowWhileIdleWhitelistDurationLocked() {
348 if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
349 mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
350 BroadcastOptions opts = BroadcastOptions.makeBasic();
351 opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
352 mIdleOptions = opts.toBundle();
353 }
354 }
355
356 @Override
357 public void onChange(boolean selfChange, Uri uri) {
358 updateConstants();
359 }
360
361 private void updateConstants() {
362 synchronized (mLock) {
363 try {
364 mParser.setString(Settings.Global.getString(mResolver,
365 Settings.Global.ALARM_MANAGER_CONSTANTS));
366 } catch (IllegalArgumentException e) {
367 // Failed to parse the settings string, log this and move on
368 // with defaults.
Dianne Hackborn0ef403e2017-01-24 18:22:15 -0800369 Slog.e(TAG, "Bad alarm manager settings", e);
Dianne Hackborna750a632015-06-16 17:18:23 -0700370 }
371
372 MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
373 MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
Christopher Tate22e919d2018-02-16 16:16:50 -0800374 MAX_INTERVAL = mParser.getLong(KEY_MAX_INTERVAL, DEFAULT_MAX_INTERVAL);
Dianne Hackborna750a632015-06-16 17:18:23 -0700375 ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
376 DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
377 ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME,
378 DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
379 ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong(
380 KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
381 DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700382 LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
383 DEFAULT_LISTENER_TIMEOUT);
Suprabh Shukla75edab12018-01-29 14:09:06 -0800384 APP_STANDBY_MIN_DELAYS[0] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[0],
385 DEFAULT_APP_STANDBY_DELAYS[0]);
386 for (int i = 1; i < KEYS_APP_STANDBY_DELAY.length; i++) {
387 APP_STANDBY_MIN_DELAYS[i] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[i],
388 Math.max(APP_STANDBY_MIN_DELAYS[i-1], DEFAULT_APP_STANDBY_DELAYS[i]));
389 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700390 updateAllowWhileIdleWhitelistDurationLocked();
391 }
392 }
393
394 void dump(PrintWriter pw) {
395 pw.println(" Settings:");
396
397 pw.print(" "); pw.print(KEY_MIN_FUTURITY); pw.print("=");
398 TimeUtils.formatDuration(MIN_FUTURITY, pw);
399 pw.println();
400
401 pw.print(" "); pw.print(KEY_MIN_INTERVAL); pw.print("=");
402 TimeUtils.formatDuration(MIN_INTERVAL, pw);
403 pw.println();
404
Christopher Tate22e919d2018-02-16 16:16:50 -0800405 pw.print(" "); pw.print(KEY_MAX_INTERVAL); pw.print("=");
406 TimeUtils.formatDuration(MAX_INTERVAL, pw);
407 pw.println();
408
Christopher Tate14a7bb02015-10-01 10:24:31 -0700409 pw.print(" "); pw.print(KEY_LISTENER_TIMEOUT); pw.print("=");
410 TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
411 pw.println();
412
Dianne Hackborna750a632015-06-16 17:18:23 -0700413 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME); pw.print("=");
414 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw);
415 pw.println();
416
417 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME); pw.print("=");
418 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw);
419 pw.println();
420
421 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); pw.print("=");
422 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
423 pw.println();
Suprabh Shukla75edab12018-01-29 14:09:06 -0800424
425 for (int i = 0; i < KEYS_APP_STANDBY_DELAY.length; i++) {
426 pw.print(" "); pw.print(KEYS_APP_STANDBY_DELAY[i]); pw.print("=");
427 TimeUtils.formatDuration(APP_STANDBY_MIN_DELAYS[i], pw);
428 pw.println();
429 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700430 }
Kweku Adams61e03292017-10-19 14:27:12 -0700431
432 void dumpProto(ProtoOutputStream proto, long fieldId) {
433 final long token = proto.start(fieldId);
434
435 proto.write(ConstantsProto.MIN_FUTURITY_DURATION_MS, MIN_FUTURITY);
436 proto.write(ConstantsProto.MIN_INTERVAL_DURATION_MS, MIN_INTERVAL);
Christopher Tate22e919d2018-02-16 16:16:50 -0800437 proto.write(ConstantsProto.MAX_INTERVAL_DURATION_MS, MAX_INTERVAL);
Kweku Adams61e03292017-10-19 14:27:12 -0700438 proto.write(ConstantsProto.LISTENER_TIMEOUT_DURATION_MS, LISTENER_TIMEOUT);
439 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_SHORT_DURATION_MS,
440 ALLOW_WHILE_IDLE_SHORT_TIME);
441 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_LONG_DURATION_MS,
442 ALLOW_WHILE_IDLE_LONG_TIME);
443 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_WHITELIST_DURATION_MS,
444 ALLOW_WHILE_IDLE_WHITELIST_DURATION);
445
446 proto.end(token);
447 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700448 }
449
450 final Constants mConstants;
451
Christopher Tate1590f1e2014-10-02 17:27:57 -0700452 // Alarm delivery ordering bookkeeping
453 static final int PRIO_TICK = 0;
454 static final int PRIO_WAKEUP = 1;
455 static final int PRIO_NORMAL = 2;
456
Dianne Hackborna750a632015-06-16 17:18:23 -0700457 final class PriorityClass {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700458 int seq;
459 int priority;
460
461 PriorityClass() {
462 seq = mCurrentSeq - 1;
463 priority = PRIO_NORMAL;
464 }
465 }
466
Dianne Hackborna750a632015-06-16 17:18:23 -0700467 final HashMap<String, PriorityClass> mPriorities = new HashMap<>();
Christopher Tate1590f1e2014-10-02 17:27:57 -0700468 int mCurrentSeq = 0;
469
Dianne Hackborna750a632015-06-16 17:18:23 -0700470 static final class WakeupEvent {
Christopher Tate18a75f12013-07-01 18:18:59 -0700471 public long when;
472 public int uid;
473 public String action;
474
475 public WakeupEvent(long theTime, int theUid, String theAction) {
476 when = theTime;
477 uid = theUid;
478 action = theAction;
479 }
480 }
481
Adam Lesinski182f73f2013-12-05 16:48:06 -0800482 final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
483 final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
Christopher Tate18a75f12013-07-01 18:18:59 -0700484
Adrian Roosc42a1e12014-07-07 23:35:53 +0200485 final class Batch {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700486 long start; // These endpoints are always in ELAPSED
487 long end;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700488 int flags; // Flags for alarms, such as FLAG_STANDALONE.
Christopher Tatee0a22b32013-07-11 14:43:13 -0700489
490 final ArrayList<Alarm> alarms = new ArrayList<Alarm>();
491
492 Batch() {
493 start = 0;
494 end = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700495 flags = 0;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700496 }
497
498 Batch(Alarm seed) {
499 start = seed.whenElapsed;
Christopher Tate22e919d2018-02-16 16:16:50 -0800500 end = clampPositive(seed.maxWhenElapsed);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700501 flags = seed.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700502 alarms.add(seed);
Makoto Onuki5d93b832018-01-10 16:12:39 -0800503 if (seed.operation == mTimeTickSender) {
504 mLastTickAdded = System.currentTimeMillis();
505 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700506 }
507
508 int size() {
509 return alarms.size();
510 }
511
512 Alarm get(int index) {
513 return alarms.get(index);
514 }
515
516 boolean canHold(long whenElapsed, long maxWhen) {
517 return (end >= whenElapsed) && (start <= maxWhen);
518 }
519
520 boolean add(Alarm alarm) {
521 boolean newStart = false;
522 // narrows the batch if necessary; presumes that canHold(alarm) is true
523 int index = Collections.binarySearch(alarms, alarm, sIncreasingTimeOrder);
524 if (index < 0) {
525 index = 0 - index - 1;
526 }
527 alarms.add(index, alarm);
Makoto Onuki5d93b832018-01-10 16:12:39 -0800528 if (alarm.operation == mTimeTickSender) {
529 mLastTickAdded = System.currentTimeMillis();
530 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700531 if (DEBUG_BATCH) {
532 Slog.v(TAG, "Adding " + alarm + " to " + this);
533 }
534 if (alarm.whenElapsed > start) {
535 start = alarm.whenElapsed;
536 newStart = true;
537 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700538 if (alarm.maxWhenElapsed < end) {
539 end = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700540 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700541 flags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700542
543 if (DEBUG_BATCH) {
544 Slog.v(TAG, " => now " + this);
545 }
546 return newStart;
547 }
548
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800549 boolean remove(Alarm alarm) {
550 return remove(a -> (a == alarm));
551 }
552
Christopher Tate1d99c392017-12-07 16:54:04 -0800553 boolean remove(Predicate<Alarm> predicate) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700554 boolean didRemove = false;
555 long newStart = 0; // recalculate endpoints as we go
556 long newEnd = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700557 int newFlags = 0;
Christopher Tateae269d52013-09-26 13:11:55 -0700558 for (int i = 0; i < alarms.size(); ) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700559 Alarm alarm = alarms.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -0800560 if (predicate.test(alarm)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700561 alarms.remove(i);
562 didRemove = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200563 if (alarm.alarmClock != null) {
564 mNextAlarmClockMayChange = true;
565 }
Makoto Onuki5d93b832018-01-10 16:12:39 -0800566 if (alarm.operation == mTimeTickSender) {
567 mLastTickRemoved = System.currentTimeMillis();
568 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700569 } else {
570 if (alarm.whenElapsed > newStart) {
571 newStart = alarm.whenElapsed;
572 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700573 if (alarm.maxWhenElapsed < newEnd) {
574 newEnd = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700575 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700576 newFlags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700577 i++;
578 }
579 }
580 if (didRemove) {
581 // commit the new batch bounds
582 start = newStart;
583 end = newEnd;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700584 flags = newFlags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700585 }
586 return didRemove;
587 }
588
Christopher Tatee0a22b32013-07-11 14:43:13 -0700589 boolean hasPackage(final String packageName) {
590 final int N = alarms.size();
591 for (int i = 0; i < N; i++) {
592 Alarm a = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700593 if (a.matches(packageName)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700594 return true;
595 }
596 }
597 return false;
598 }
599
600 boolean hasWakeups() {
601 final int N = alarms.size();
602 for (int i = 0; i < N; i++) {
603 Alarm a = alarms.get(i);
604 // non-wakeup alarms are types 1 and 3, i.e. have the low bit set
605 if ((a.type & TYPE_NONWAKEUP_MASK) == 0) {
606 return true;
607 }
608 }
609 return false;
610 }
611
612 @Override
613 public String toString() {
614 StringBuilder b = new StringBuilder(40);
615 b.append("Batch{"); b.append(Integer.toHexString(this.hashCode()));
616 b.append(" num="); b.append(size());
617 b.append(" start="); b.append(start);
618 b.append(" end="); b.append(end);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700619 if (flags != 0) {
620 b.append(" flgs=0x");
621 b.append(Integer.toHexString(flags));
Christopher Tatee0a22b32013-07-11 14:43:13 -0700622 }
623 b.append('}');
624 return b.toString();
625 }
Kweku Adams61e03292017-10-19 14:27:12 -0700626
627 public void writeToProto(ProtoOutputStream proto, long fieldId, long nowElapsed,
628 long nowRTC) {
629 final long token = proto.start(fieldId);
630
631 proto.write(BatchProto.START_REALTIME, start);
632 proto.write(BatchProto.END_REALTIME, end);
633 proto.write(BatchProto.FLAGS, flags);
634 for (Alarm a : alarms) {
635 a.writeToProto(proto, BatchProto.ALARMS, nowElapsed, nowRTC);
636 }
637
638 proto.end(token);
639 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700640 }
641
642 static class BatchTimeOrder implements Comparator<Batch> {
643 public int compare(Batch b1, Batch b2) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800644 long when1 = b1.start;
645 long when2 = b2.start;
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800646 if (when1 > when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700647 return 1;
648 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800649 if (when1 < when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700650 return -1;
651 }
652 return 0;
653 }
654 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800655
656 final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
657 @Override
658 public int compare(Alarm lhs, Alarm rhs) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700659 // priority class trumps everything. TICK < WAKEUP < NORMAL
660 if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
661 return -1;
662 } else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
663 return 1;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800664 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700665
666 // within each class, sort by nominal delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800667 if (lhs.whenElapsed < rhs.whenElapsed) {
668 return -1;
669 } else if (lhs.whenElapsed > rhs.whenElapsed) {
670 return 1;
671 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700672
673 // same priority class + same target delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800674 return 0;
675 }
676 };
677
Christopher Tate1590f1e2014-10-02 17:27:57 -0700678 void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
679 final int N = alarms.size();
680 for (int i = 0; i < N; i++) {
681 Alarm a = alarms.get(i);
682
683 final int alarmPrio;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700684 if (a.operation != null
685 && Intent.ACTION_TIME_TICK.equals(a.operation.getIntent().getAction())) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700686 alarmPrio = PRIO_TICK;
687 } else if (a.wakeup) {
688 alarmPrio = PRIO_WAKEUP;
689 } else {
690 alarmPrio = PRIO_NORMAL;
691 }
692
693 PriorityClass packagePrio = a.priorityClass;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800694 String alarmPackage = a.sourcePackage;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700695 if (packagePrio == null) packagePrio = mPriorities.get(alarmPackage);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700696 if (packagePrio == null) {
697 packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
Christopher Tate14a7bb02015-10-01 10:24:31 -0700698 mPriorities.put(alarmPackage, packagePrio);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700699 }
700 a.priorityClass = packagePrio;
701
702 if (packagePrio.seq != mCurrentSeq) {
703 // first alarm we've seen in the current delivery generation from this package
704 packagePrio.priority = alarmPrio;
705 packagePrio.seq = mCurrentSeq;
706 } else {
707 // Multiple alarms from this package being delivered in this generation;
708 // bump the package's delivery class if it's warranted.
709 // TICK < WAKEUP < NORMAL
710 if (alarmPrio < packagePrio.priority) {
711 packagePrio.priority = alarmPrio;
712 }
713 }
714 }
715 }
716
Christopher Tatee0a22b32013-07-11 14:43:13 -0700717 // minimum recurrence period or alarm futurity for us to be able to fuzz it
Adam Lesinski182f73f2013-12-05 16:48:06 -0800718 static final long MIN_FUZZABLE_INTERVAL = 10000;
719 static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700720 final ArrayList<Batch> mAlarmBatches = new ArrayList<>();
721
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700722 // 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 -0700723 // to run during this time are placed in mPendingWhileIdleAlarms
724 Alarm mPendingIdleUntil = null;
Dianne Hackbornf70faed2015-04-21 14:11:38 -0700725 Alarm mNextWakeFromIdle = null;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700726 ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
Christopher Tatee0a22b32013-07-11 14:43:13 -0700727
Jeff Brownb880d882014-02-10 19:47:07 -0800728 public AlarmManagerService(Context context) {
729 super(context);
Dianne Hackborna750a632015-06-16 17:18:23 -0700730 mConstants = new Constants(mHandler);
Makoto Onuki2206af32017-11-21 16:25:35 -0800731
Christopher Tate1d99c392017-12-07 16:54:04 -0800732 publishLocalService(AlarmManagerInternal.class, new LocalService());
Jeff Brownb880d882014-02-10 19:47:07 -0800733 }
734
Christopher Tatee0a22b32013-07-11 14:43:13 -0700735 static long convertToElapsed(long when, int type) {
736 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
737 if (isRtc) {
738 when -= System.currentTimeMillis() - SystemClock.elapsedRealtime();
739 }
740 return when;
741 }
742
743 // Apply a heuristic to { recurrence interval, futurity of the trigger time } to
744 // calculate the end of our nominal delivery window for the alarm.
745 static long maxTriggerTime(long now, long triggerAtTime, long interval) {
746 // Current heuristic: batchable window is 75% of either the recurrence interval
747 // [for a periodic alarm] or of the time from now to the desired delivery time,
748 // with a minimum delay/interval of 10 seconds, under which we will simply not
749 // defer the alarm.
750 long futurity = (interval == 0)
751 ? (triggerAtTime - now)
752 : interval;
Christopher Tate57ceaaa2013-07-19 16:30:43 -0700753 if (futurity < MIN_FUZZABLE_INTERVAL) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700754 futurity = 0;
755 }
Christopher Tate22e919d2018-02-16 16:16:50 -0800756 return clampPositive(triggerAtTime + (long)(.75 * futurity));
Christopher Tatee0a22b32013-07-11 14:43:13 -0700757 }
758
759 // returns true if the batch was added at the head
760 static boolean addBatchLocked(ArrayList<Batch> list, Batch newBatch) {
761 int index = Collections.binarySearch(list, newBatch, sBatchOrder);
762 if (index < 0) {
763 index = 0 - index - 1;
764 }
765 list.add(index, newBatch);
766 return (index == 0);
767 }
768
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800769 private void insertAndBatchAlarmLocked(Alarm alarm) {
770 final int whichBatch = ((alarm.flags & AlarmManager.FLAG_STANDALONE) != 0) ? -1
771 : attemptCoalesceLocked(alarm.whenElapsed, alarm.maxWhenElapsed);
772
773 if (whichBatch < 0) {
774 addBatchLocked(mAlarmBatches, new Batch(alarm));
775 } else {
776 final Batch batch = mAlarmBatches.get(whichBatch);
777 if (batch.add(alarm)) {
778 // The start time of this batch advanced, so batch ordering may
779 // have just been broken. Move it to where it now belongs.
780 mAlarmBatches.remove(whichBatch);
781 addBatchLocked(mAlarmBatches, batch);
782 }
783 }
784 }
785
Christopher Tate385e4982013-07-23 18:22:29 -0700786 // Return the index of the matching batch, or -1 if none found.
787 int attemptCoalesceLocked(long whenElapsed, long maxWhen) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700788 final int N = mAlarmBatches.size();
789 for (int i = 0; i < N; i++) {
790 Batch b = mAlarmBatches.get(i);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700791 if ((b.flags&AlarmManager.FLAG_STANDALONE) == 0 && b.canHold(whenElapsed, maxWhen)) {
Christopher Tate385e4982013-07-23 18:22:29 -0700792 return i;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700793 }
794 }
Christopher Tate385e4982013-07-23 18:22:29 -0700795 return -1;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700796 }
Makoto Onuki5d93b832018-01-10 16:12:39 -0800797 /** @return total count of the alarms in a set of alarm batches. */
798 static int getAlarmCount(ArrayList<Batch> batches) {
799 int ret = 0;
800
801 final int size = batches.size();
802 for (int i = 0; i < size; i++) {
803 ret += batches.get(i).size();
804 }
805 return ret;
806 }
807
808 boolean haveAlarmsTimeTickAlarm(ArrayList<Alarm> alarms) {
809 if (alarms.size() == 0) {
810 return false;
811 }
812 final int batchSize = alarms.size();
813 for (int j = 0; j < batchSize; j++) {
814 if (alarms.get(j).operation == mTimeTickSender) {
815 return true;
816 }
817 }
818 return false;
819 }
820
821 boolean haveBatchesTimeTickAlarm(ArrayList<Batch> batches) {
822 final int numBatches = batches.size();
823 for (int i = 0; i < numBatches; i++) {
824 if (haveAlarmsTimeTickAlarm(batches.get(i).alarms)) {
825 return true;
826 }
827 }
828 return false;
829 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700830
831 // The RTC clock has moved arbitrarily, so we need to recalculate all the batching
832 void rebatchAllAlarms() {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700833 synchronized (mLock) {
Christopher Tate4cb338d2013-07-26 13:11:31 -0700834 rebatchAllAlarmsLocked(true);
835 }
836 }
837
838 void rebatchAllAlarmsLocked(boolean doValidate) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800839 final long start = mStatLogger.getTime();
Makoto Onuki5d93b832018-01-10 16:12:39 -0800840 final int oldCount =
841 getAlarmCount(mAlarmBatches) + ArrayUtils.size(mPendingWhileIdleAlarms);
842 final boolean oldHasTick = haveBatchesTimeTickAlarm(mAlarmBatches)
843 || haveAlarmsTimeTickAlarm(mPendingWhileIdleAlarms);
844
Christopher Tate4cb338d2013-07-26 13:11:31 -0700845 ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone();
846 mAlarmBatches.clear();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700847 Alarm oldPendingIdleUntil = mPendingIdleUntil;
Christopher Tate4cb338d2013-07-26 13:11:31 -0700848 final long nowElapsed = SystemClock.elapsedRealtime();
849 final int oldBatches = oldSet.size();
850 for (int batchNum = 0; batchNum < oldBatches; batchNum++) {
851 Batch batch = oldSet.get(batchNum);
852 final int N = batch.size();
853 for (int i = 0; i < N; i++) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700854 reAddAlarmLocked(batch.get(i), nowElapsed, doValidate);
Christopher Tatee0a22b32013-07-11 14:43:13 -0700855 }
856 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700857 if (oldPendingIdleUntil != null && oldPendingIdleUntil != mPendingIdleUntil) {
858 Slog.wtf(TAG, "Rebatching: idle until changed from " + oldPendingIdleUntil
859 + " to " + mPendingIdleUntil);
860 if (mPendingIdleUntil == null) {
861 // Somehow we lost this... we need to restore all of the pending alarms.
862 restorePendingWhileIdleAlarmsLocked();
863 }
864 }
Makoto Onuki5d93b832018-01-10 16:12:39 -0800865 final int newCount =
866 getAlarmCount(mAlarmBatches) + ArrayUtils.size(mPendingWhileIdleAlarms);
867 final boolean newHasTick = haveBatchesTimeTickAlarm(mAlarmBatches)
868 || haveAlarmsTimeTickAlarm(mPendingWhileIdleAlarms);
869
870 if (oldCount != newCount) {
871 Slog.wtf(TAG, "Rebatching: total count changed from " + oldCount + " to " + newCount);
872 }
873 if (oldHasTick != newHasTick) {
874 Slog.wtf(TAG, "Rebatching: hasTick changed from " + oldHasTick + " to " + newHasTick);
875 }
876
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700877 rescheduleKernelAlarmsLocked();
878 updateNextAlarmClockLocked();
Suprabh Shukla75edab12018-01-29 14:09:06 -0800879 mStatLogger.logDurationStat(Stats.REBATCH_ALL_ALARMS, start);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700880 }
881
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800882 /**
883 * Re-orders the alarm batches based on newly evaluated send times based on the current
884 * app-standby buckets
885 * @param targetPackages [Package, User] pairs for which alarms need to be re-evaluated,
886 * null indicates all
887 * @return True if there was any reordering done to the current list.
888 */
889 boolean reorderAlarmsBasedOnStandbyBuckets(ArraySet<Pair<String, Integer>> targetPackages) {
890 final long start = mStatLogger.getTime();
891 final ArrayList<Alarm> rescheduledAlarms = new ArrayList<>();
892
893 for (int batchIndex = mAlarmBatches.size() - 1; batchIndex >= 0; batchIndex--) {
894 final Batch batch = mAlarmBatches.get(batchIndex);
895 for (int alarmIndex = batch.size() - 1; alarmIndex >= 0; alarmIndex--) {
896 final Alarm alarm = batch.get(alarmIndex);
897 final Pair<String, Integer> packageUser =
898 Pair.create(alarm.sourcePackage, UserHandle.getUserId(alarm.creatorUid));
899 if (targetPackages != null && !targetPackages.contains(packageUser)) {
900 continue;
901 }
902 if (adjustDeliveryTimeBasedOnStandbyBucketLocked(alarm)) {
903 batch.remove(alarm);
904 rescheduledAlarms.add(alarm);
905 }
906 }
907 if (batch.size() == 0) {
908 mAlarmBatches.remove(batchIndex);
909 }
910 }
911 for (int i = 0; i < rescheduledAlarms.size(); i++) {
912 final Alarm a = rescheduledAlarms.get(i);
913 insertAndBatchAlarmLocked(a);
914 }
915
916 mStatLogger.logDurationStat(Stats.REORDER_ALARMS_FOR_STANDBY, start);
917 return rescheduledAlarms.size() > 0;
918 }
919
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700920 void reAddAlarmLocked(Alarm a, long nowElapsed, boolean doValidate) {
921 a.when = a.origWhen;
922 long whenElapsed = convertToElapsed(a.when, a.type);
923 final long maxElapsed;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700924 if (a.windowLength == AlarmManager.WINDOW_EXACT) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700925 // Exact
926 maxElapsed = whenElapsed;
927 } else {
928 // Not exact. Preserve any explicit window, otherwise recalculate
929 // the window based on the alarm's new futurity. Note that this
930 // reflects a policy of preferring timely to deferred delivery.
931 maxElapsed = (a.windowLength > 0)
Christopher Tate22e919d2018-02-16 16:16:50 -0800932 ? clampPositive(whenElapsed + a.windowLength)
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700933 : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
934 }
935 a.whenElapsed = whenElapsed;
936 a.maxWhenElapsed = maxElapsed;
937 setImplLocked(a, true, doValidate);
938 }
939
Christopher Tate22e919d2018-02-16 16:16:50 -0800940 static long clampPositive(long val) {
941 return (val >= 0) ? val : Long.MAX_VALUE;
942 }
943
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700944 /**
945 * Sends alarms that were blocked due to user applied background restrictions - either because
946 * the user lifted those or the uid came to foreground.
947 *
948 * @param uid uid to filter on
949 * @param packageName package to filter on, or null for all packages in uid
950 */
951 void sendPendingBackgroundAlarmsLocked(int uid, String packageName) {
952 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(uid);
953 if (alarmsForUid == null || alarmsForUid.size() == 0) {
954 return;
955 }
956 final ArrayList<Alarm> alarmsToDeliver;
957 if (packageName != null) {
958 if (DEBUG_BG_LIMIT) {
959 Slog.d(TAG, "Sending blocked alarms for uid " + uid + ", package " + packageName);
960 }
961 alarmsToDeliver = new ArrayList<>();
962 for (int i = alarmsForUid.size() - 1; i >= 0; i--) {
963 final Alarm a = alarmsForUid.get(i);
964 if (a.matches(packageName)) {
965 alarmsToDeliver.add(alarmsForUid.remove(i));
966 }
967 }
968 if (alarmsForUid.size() == 0) {
969 mPendingBackgroundAlarms.remove(uid);
970 }
971 } else {
972 if (DEBUG_BG_LIMIT) {
973 Slog.d(TAG, "Sending blocked alarms for uid " + uid);
974 }
975 alarmsToDeliver = alarmsForUid;
976 mPendingBackgroundAlarms.remove(uid);
977 }
978 deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, SystemClock.elapsedRealtime());
979 }
980
Makoto Onuki2206af32017-11-21 16:25:35 -0800981 /**
982 * Check all alarms in {@link #mPendingBackgroundAlarms} and send the ones that are not
983 * restricted.
984 *
985 * This is only called when the global "force all apps-standby" flag changes or when the
986 * power save whitelist changes, so it's okay to be slow.
987 */
988 void sendAllUnrestrictedPendingBackgroundAlarmsLocked() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700989 final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
Makoto Onuki2206af32017-11-21 16:25:35 -0800990
991 findAllUnrestrictedPendingBackgroundAlarmsLockedInner(
992 mPendingBackgroundAlarms, alarmsToDeliver, this::isBackgroundRestricted);
993
994 if (alarmsToDeliver.size() > 0) {
995 deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, SystemClock.elapsedRealtime());
996 }
997 }
998
999 @VisibleForTesting
1000 static void findAllUnrestrictedPendingBackgroundAlarmsLockedInner(
1001 SparseArray<ArrayList<Alarm>> pendingAlarms, ArrayList<Alarm> unrestrictedAlarms,
1002 Predicate<Alarm> isBackgroundRestricted) {
1003
1004 for (int uidIndex = pendingAlarms.size() - 1; uidIndex >= 0; uidIndex--) {
1005 final int uid = pendingAlarms.keyAt(uidIndex);
1006 final ArrayList<Alarm> alarmsForUid = pendingAlarms.valueAt(uidIndex);
1007
1008 for (int alarmIndex = alarmsForUid.size() - 1; alarmIndex >= 0; alarmIndex--) {
1009 final Alarm alarm = alarmsForUid.get(alarmIndex);
1010
1011 if (isBackgroundRestricted.test(alarm)) {
1012 continue;
1013 }
1014
1015 unrestrictedAlarms.add(alarm);
1016 alarmsForUid.remove(alarmIndex);
1017 }
1018
1019 if (alarmsForUid.size() == 0) {
1020 pendingAlarms.removeAt(uidIndex);
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001021 }
1022 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001023 }
1024
1025 private void deliverPendingBackgroundAlarmsLocked(ArrayList<Alarm> alarms, long nowELAPSED) {
1026 final int N = alarms.size();
1027 boolean hasWakeup = false;
1028 for (int i = 0; i < N; i++) {
1029 final Alarm alarm = alarms.get(i);
1030 if (alarm.wakeup) {
1031 hasWakeup = true;
1032 }
1033 alarm.count = 1;
1034 // Recurring alarms may have passed several alarm intervals while the
1035 // alarm was kept pending. Send the appropriate trigger count.
1036 if (alarm.repeatInterval > 0) {
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001037 alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001038 // Also schedule its next recurrence
1039 final long delta = alarm.count * alarm.repeatInterval;
1040 final long nextElapsed = alarm.whenElapsed + delta;
1041 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
1042 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
1043 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
1044 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
1045 // Kernel alarms will be rescheduled as needed in setImplLocked
1046 }
1047 }
1048 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
1049 // No need to wakeup for non wakeup alarms
1050 if (mPendingNonWakeupAlarms.size() == 0) {
1051 mStartCurrentDelayTime = nowELAPSED;
1052 mNextNonWakeupDeliveryTime = nowELAPSED
1053 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
1054 }
1055 mPendingNonWakeupAlarms.addAll(alarms);
1056 mNumDelayedAlarms += alarms.size();
1057 } else {
1058 if (DEBUG_BG_LIMIT) {
1059 Slog.d(TAG, "Waking up to deliver pending blocked alarms");
1060 }
1061 // Since we are waking up, also deliver any pending non wakeup alarms we have.
1062 if (mPendingNonWakeupAlarms.size() > 0) {
1063 alarms.addAll(mPendingNonWakeupAlarms);
1064 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
1065 mTotalDelayTime += thisDelayTime;
1066 if (mMaxDelayTime < thisDelayTime) {
1067 mMaxDelayTime = thisDelayTime;
1068 }
1069 mPendingNonWakeupAlarms.clear();
1070 }
1071 calculateDeliveryPriorities(alarms);
1072 Collections.sort(alarms, mAlarmDispatchComparator);
1073 deliverAlarmsLocked(alarms, nowELAPSED);
1074 }
1075 }
1076
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001077 void restorePendingWhileIdleAlarmsLocked() {
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001078 if (RECORD_DEVICE_IDLE_ALARMS) {
1079 IdleDispatchEntry ent = new IdleDispatchEntry();
1080 ent.uid = 0;
1081 ent.pkg = "FINISH IDLE";
1082 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1083 mAllowWhileIdleDispatches.add(ent);
1084 }
1085
Dianne Hackborn35d54032015-04-23 10:30:43 -07001086 // Bring pending alarms back into the main list.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001087 if (mPendingWhileIdleAlarms.size() > 0) {
1088 ArrayList<Alarm> alarms = mPendingWhileIdleAlarms;
1089 mPendingWhileIdleAlarms = new ArrayList<>();
1090 final long nowElapsed = SystemClock.elapsedRealtime();
1091 for (int i=alarms.size() - 1; i >= 0; i--) {
1092 Alarm a = alarms.get(i);
1093 reAddAlarmLocked(a, nowElapsed, false);
1094 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001095 }
Dianne Hackborn35d54032015-04-23 10:30:43 -07001096
1097 // Reschedule everything.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001098 rescheduleKernelAlarmsLocked();
1099 updateNextAlarmClockLocked();
Dianne Hackborn35d54032015-04-23 10:30:43 -07001100
1101 // And send a TIME_TICK right now, since it is important to get the UI updated.
1102 try {
1103 mTimeTickSender.send();
1104 } catch (PendingIntent.CanceledException e) {
1105 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001106 }
1107
Christopher Tate14a7bb02015-10-01 10:24:31 -07001108 static final class InFlight {
Dianne Hackborn81038902012-11-26 17:04:09 -08001109 final PendingIntent mPendingIntent;
Christopher Tateeabba732017-08-17 17:12:52 -07001110 final long mWhenElapsed;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001111 final IBinder mListener;
David Christieebe51fc2013-07-26 13:23:29 -07001112 final WorkSource mWorkSource;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001113 final int mUid;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001114 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001115 final BroadcastStats mBroadcastStats;
1116 final FilterStats mFilterStats;
Dianne Hackborne5167ca2014-03-08 14:39:10 -08001117 final int mAlarmType;
Dianne Hackborn81038902012-11-26 17:04:09 -08001118
Christopher Tate14a7bb02015-10-01 10:24:31 -07001119 InFlight(AlarmManagerService service, PendingIntent pendingIntent, IAlarmListener listener,
1120 WorkSource workSource, int uid, String alarmPkg, int alarmType, String tag,
1121 long nowELAPSED) {
Dianne Hackborn81038902012-11-26 17:04:09 -08001122 mPendingIntent = pendingIntent;
Christopher Tateeabba732017-08-17 17:12:52 -07001123 mWhenElapsed = nowELAPSED;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001124 mListener = listener != null ? listener.asBinder() : null;
David Christieebe51fc2013-07-26 13:23:29 -07001125 mWorkSource = workSource;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001126 mUid = uid;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001127 mTag = tag;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001128 mBroadcastStats = (pendingIntent != null)
1129 ? service.getStatsLocked(pendingIntent)
1130 : service.getStatsLocked(uid, alarmPkg);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001131 FilterStats fs = mBroadcastStats.filterStats.get(mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08001132 if (fs == null) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001133 fs = new FilterStats(mBroadcastStats, mTag);
1134 mBroadcastStats.filterStats.put(mTag, fs);
Dianne Hackborn81038902012-11-26 17:04:09 -08001135 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001136 fs.lastTime = nowELAPSED;
Dianne Hackborn81038902012-11-26 17:04:09 -08001137 mFilterStats = fs;
Dianne Hackborne5167ca2014-03-08 14:39:10 -08001138 mAlarmType = alarmType;
Dianne Hackborn81038902012-11-26 17:04:09 -08001139 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001140
1141 @Override
1142 public String toString() {
1143 return "InFlight{"
1144 + "pendingIntent=" + mPendingIntent
Christopher Tateeabba732017-08-17 17:12:52 -07001145 + ", when=" + mWhenElapsed
Makoto Onuki33955e12017-03-01 18:11:00 -08001146 + ", workSource=" + mWorkSource
1147 + ", uid=" + mUid
1148 + ", tag=" + mTag
1149 + ", broadcastStats=" + mBroadcastStats
1150 + ", filterStats=" + mFilterStats
1151 + ", alarmType=" + mAlarmType
1152 + "}";
1153 }
Kweku Adams61e03292017-10-19 14:27:12 -07001154
1155 public void writeToProto(ProtoOutputStream proto, long fieldId) {
1156 final long token = proto.start(fieldId);
1157
1158 proto.write(InFlightProto.UID, mUid);
1159 proto.write(InFlightProto.TAG, mTag);
1160 proto.write(InFlightProto.WHEN_ELAPSED_MS, mWhenElapsed);
1161 proto.write(InFlightProto.ALARM_TYPE, mAlarmType);
1162 if (mPendingIntent != null) {
1163 mPendingIntent.writeToProto(proto, InFlightProto.PENDING_INTENT);
1164 }
1165 if (mBroadcastStats != null) {
1166 mBroadcastStats.writeToProto(proto, InFlightProto.BROADCAST_STATS);
1167 }
1168 if (mFilterStats != null) {
1169 mFilterStats.writeToProto(proto, InFlightProto.FILTER_STATS);
1170 }
1171 if (mWorkSource != null) {
1172 mWorkSource.writeToProto(proto, InFlightProto.WORK_SOURCE);
1173 }
1174
1175 proto.end(token);
1176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001178
Adam Lesinski182f73f2013-12-05 16:48:06 -08001179 static final class FilterStats {
Dianne Hackborn81038902012-11-26 17:04:09 -08001180 final BroadcastStats mBroadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001181 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001182
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001183 long lastTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 long aggregateTime;
Dianne Hackborn81038902012-11-26 17:04:09 -08001185 int count;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 int numWakeup;
1187 long startTime;
1188 int nesting;
Dianne Hackborn81038902012-11-26 17:04:09 -08001189
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001190 FilterStats(BroadcastStats broadcastStats, String tag) {
Dianne Hackborn81038902012-11-26 17:04:09 -08001191 mBroadcastStats = broadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001192 mTag = tag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001193 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001194
1195 @Override
1196 public String toString() {
1197 return "FilterStats{"
1198 + "tag=" + mTag
1199 + ", lastTime=" + lastTime
1200 + ", aggregateTime=" + aggregateTime
1201 + ", count=" + count
1202 + ", numWakeup=" + numWakeup
1203 + ", startTime=" + startTime
1204 + ", nesting=" + nesting
1205 + "}";
1206 }
Kweku Adams61e03292017-10-19 14:27:12 -07001207
1208 public void writeToProto(ProtoOutputStream proto, long fieldId) {
1209 final long token = proto.start(fieldId);
1210
1211 proto.write(FilterStatsProto.TAG, mTag);
1212 proto.write(FilterStatsProto.LAST_FLIGHT_TIME_REALTIME, lastTime);
1213 proto.write(FilterStatsProto.TOTAL_FLIGHT_DURATION_MS, aggregateTime);
1214 proto.write(FilterStatsProto.COUNT, count);
1215 proto.write(FilterStatsProto.WAKEUP_COUNT, numWakeup);
1216 proto.write(FilterStatsProto.START_TIME_REALTIME, startTime);
1217 proto.write(FilterStatsProto.NESTING, nesting);
1218
1219 proto.end(token);
1220 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001221 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001222
Adam Lesinski182f73f2013-12-05 16:48:06 -08001223 static final class BroadcastStats {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001224 final int mUid;
Dianne Hackborn81038902012-11-26 17:04:09 -08001225 final String mPackageName;
1226
1227 long aggregateTime;
1228 int count;
1229 int numWakeup;
1230 long startTime;
1231 int nesting;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001232 final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
Dianne Hackborn81038902012-11-26 17:04:09 -08001233
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001234 BroadcastStats(int uid, String packageName) {
1235 mUid = uid;
Dianne Hackborn81038902012-11-26 17:04:09 -08001236 mPackageName = packageName;
1237 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001238
1239 @Override
1240 public String toString() {
1241 return "BroadcastStats{"
1242 + "uid=" + mUid
1243 + ", packageName=" + mPackageName
1244 + ", aggregateTime=" + aggregateTime
1245 + ", count=" + count
1246 + ", numWakeup=" + numWakeup
1247 + ", startTime=" + startTime
1248 + ", nesting=" + nesting
1249 + "}";
1250 }
Kweku Adams61e03292017-10-19 14:27:12 -07001251
1252 public void writeToProto(ProtoOutputStream proto, long fieldId) {
1253 final long token = proto.start(fieldId);
1254
1255 proto.write(BroadcastStatsProto.UID, mUid);
1256 proto.write(BroadcastStatsProto.PACKAGE_NAME, mPackageName);
1257 proto.write(BroadcastStatsProto.TOTAL_FLIGHT_DURATION_MS, aggregateTime);
1258 proto.write(BroadcastStatsProto.COUNT, count);
1259 proto.write(BroadcastStatsProto.WAKEUP_COUNT, numWakeup);
1260 proto.write(BroadcastStatsProto.START_TIME_REALTIME, startTime);
1261 proto.write(BroadcastStatsProto.NESTING, nesting);
1262
1263 proto.end(token);
1264 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001266
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001267 final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
1268 = new SparseArray<ArrayMap<String, BroadcastStats>>();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001269
1270 int mNumDelayedAlarms = 0;
1271 long mTotalDelayTime = 0;
1272 long mMaxDelayTime = 0;
1273
Adam Lesinski182f73f2013-12-05 16:48:06 -08001274 @Override
1275 public void onStart() {
Greg Hackmanna1d6f922013-12-09 16:56:53 -08001276 mNativeData = init();
Christopher Tate0dab4dc2014-12-16 12:14:06 -08001277 mNextWakeup = mNextNonWakeup = 0;
Robert CH Chou64ba8e42009-11-04 21:38:49 +08001278
1279 // We have to set current TimeZone info to kernel
1280 // because kernel doesn't keep this after reboot
Adam Lesinski182f73f2013-12-05 16:48:06 -08001281 setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
Robert CH Chou64ba8e42009-11-04 21:38:49 +08001282
Christopher Tate247571462017-04-10 11:45:05 -07001283 // Also sure that we're booting with a halfway sensible current time
1284 if (mNativeData != 0) {
1285 final long systemBuildTime = Environment.getRootDirectory().lastModified();
1286 if (System.currentTimeMillis() < systemBuildTime) {
1287 Slog.i(TAG, "Current time only " + System.currentTimeMillis()
1288 + ", advancing to build time " + systemBuildTime);
1289 setKernelTime(mNativeData, systemBuildTime);
1290 }
1291 }
1292
Christopher Tatebb9cce52017-04-18 14:19:43 -07001293 // Determine SysUI's uid
1294 final PackageManager packMan = getContext().getPackageManager();
1295 try {
1296 PermissionInfo sysUiPerm = packMan.getPermissionInfo(SYSTEM_UI_SELF_PERMISSION, 0);
1297 ApplicationInfo sysUi = packMan.getApplicationInfo(sysUiPerm.packageName, 0);
1298 if ((sysUi.privateFlags&ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
1299 mSystemUiUid = sysUi.uid;
1300 } else {
1301 Slog.e(TAG, "SysUI permission " + SYSTEM_UI_SELF_PERMISSION
1302 + " defined by non-privileged app " + sysUi.packageName
1303 + " - ignoring");
1304 }
1305 } catch (NameNotFoundException e) {
1306 }
1307
1308 if (mSystemUiUid <= 0) {
1309 Slog.wtf(TAG, "SysUI package not found!");
1310 }
1311
Adam Lesinski182f73f2013-12-05 16:48:06 -08001312 PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001313 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
Dianne Hackborna1f1a3c2014-02-24 18:12:28 -08001314
Adam Lesinski182f73f2013-12-05 16:48:06 -08001315 mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316 new Intent(Intent.ACTION_TIME_TICK).addFlags(
Dianne Hackborn3bc8f78d2013-09-19 13:34:35 -07001317 Intent.FLAG_RECEIVER_REGISTERED_ONLY
Chad Brubaker291df4f2017-03-14 10:23:02 -07001318 | Intent.FLAG_RECEIVER_FOREGROUND
1319 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS), 0,
Dianne Hackborndb5aca92012-10-26 13:39:41 -07001320 UserHandle.ALL);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001321 Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
Chad Brubaker291df4f2017-03-14 10:23:02 -07001322 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
1323 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001324 mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
Dianne Hackborndb5aca92012-10-26 13:39:41 -07001325 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
Kweku Adams61e03292017-10-19 14:27:12 -07001326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 // now that we have initied the driver schedule the alarm
Adam Lesinski182f73f2013-12-05 16:48:06 -08001328 mClockReceiver = new ClockReceiver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 mClockReceiver.scheduleTimeTickEvent();
1330 mClockReceiver.scheduleDateChangedEvent();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001331 mInteractiveStateReceiver = new InteractiveStateReceiver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332 mUninstallReceiver = new UninstallReceiver();
Kweku Adams61e03292017-10-19 14:27:12 -07001333
Greg Hackmanna1d6f922013-12-09 16:56:53 -08001334 if (mNativeData != 0) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001335 AlarmThread waitThread = new AlarmThread();
1336 waitThread.start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001338 Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001340
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001341 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001342 ActivityManager.getService().registerUidObserver(new UidObserver(),
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001343 ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
1344 | ActivityManager.UID_OBSERVER_ACTIVE,
1345 ActivityManager.PROCESS_STATE_UNKNOWN, null);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001346 } catch (RemoteException e) {
1347 // ignored; both services live in system_server
1348 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001349 publishBinderService(Context.ALARM_SERVICE, mService);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001351
1352 @Override
Dianne Hackborna750a632015-06-16 17:18:23 -07001353 public void onBootPhase(int phase) {
1354 if (phase == PHASE_SYSTEM_SERVICES_READY) {
1355 mConstants.start(getContext().getContentResolver());
Christopher Tate14a7bb02015-10-01 10:24:31 -07001356 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
Dianne Hackborn627dfa12015-11-11 18:10:30 -08001357 mLocalDeviceIdleController
1358 = LocalServices.getService(DeviceIdleController.LocalService.class);
Suprabh Shukla75edab12018-01-29 14:09:06 -08001359 mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
1360 mUsageStatsManagerInternal.addAppIdleStateChangeListener(new AppStandbyTracker());
Makoto Onukie4918212018-02-06 11:30:15 -08001361
1362 mAppStateTracker = LocalServices.getService(AppStateTracker.class);
1363 mAppStateTracker.addListener(mForceAppStandbyListener);
Dianne Hackborna750a632015-06-16 17:18:23 -07001364 }
1365 }
1366
1367 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 protected void finalize() throws Throwable {
1369 try {
Greg Hackmanna1d6f922013-12-09 16:56:53 -08001370 close(mNativeData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001371 } finally {
1372 super.finalize();
1373 }
1374 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001375
mswest463f4c99d2018-02-01 10:13:10 -08001376 boolean setTimeImpl(long millis) {
1377 if (mNativeData == 0) {
1378 Slog.w(TAG, "Not setting time since no alarm driver is available.");
1379 return false;
1380 }
1381
1382 synchronized (mLock) {
1383 return setKernelTime(mNativeData, millis) == 0;
1384 }
1385 }
1386
Adam Lesinski182f73f2013-12-05 16:48:06 -08001387 void setTimeZoneImpl(String tz) {
1388 if (TextUtils.isEmpty(tz)) {
1389 return;
David Christieebe51fc2013-07-26 13:23:29 -07001390 }
1391
Adam Lesinski182f73f2013-12-05 16:48:06 -08001392 TimeZone zone = TimeZone.getTimeZone(tz);
1393 // Prevent reentrant calls from stepping on each other when writing
1394 // the time zone property
1395 boolean timeZoneWasChanged = false;
1396 synchronized (this) {
1397 String current = SystemProperties.get(TIMEZONE_PROPERTY);
1398 if (current == null || !current.equals(zone.getID())) {
1399 if (localLOGV) {
1400 Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
1401 }
1402 timeZoneWasChanged = true;
1403 SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
1404 }
1405
1406 // Update the kernel timezone information
1407 // Kernel tracks time offsets as 'minutes west of GMT'
1408 int gmtOffset = zone.getOffset(System.currentTimeMillis());
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -08001409 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
Adam Lesinski182f73f2013-12-05 16:48:06 -08001410 }
1411
1412 TimeZone.setDefault(null);
1413
1414 if (timeZoneWasChanged) {
1415 Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
Chad Brubaker291df4f2017-03-14 10:23:02 -07001416 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
Christopher Tate5cdf9f82017-05-03 18:10:39 -07001417 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
Chad Brubaker291df4f2017-03-14 10:23:02 -07001418 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001419 intent.putExtra("time-zone", zone.getID());
1420 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
1421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001423
Adam Lesinski182f73f2013-12-05 16:48:06 -08001424 void removeImpl(PendingIntent operation) {
1425 if (operation == null) {
1426 return;
1427 }
1428 synchronized (mLock) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07001429 removeLocked(operation, null);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001430 }
1431 }
1432
1433 void setImpl(int type, long triggerAtTime, long windowLength, long interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001434 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1435 int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
1436 int callingUid, String callingPackage) {
1437 // must be *either* PendingIntent or AlarmReceiver, but not both
1438 if ((operation == null && directReceiver == null)
1439 || (operation != null && directReceiver != null)) {
1440 Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver");
1441 // NB: previous releases failed silently here, so we are continuing to do the same
1442 // rather than throw an IllegalArgumentException.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 return;
1444 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001445
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001446 // Sanity check the window length. This will catch people mistakenly
1447 // trying to pass an end-of-window timestamp rather than a duration.
1448 if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
1449 Slog.w(TAG, "Window length " + windowLength
1450 + "ms suspiciously long; limiting to 1 hour");
1451 windowLength = AlarmManager.INTERVAL_HOUR;
1452 }
1453
Christopher Tate498c6cb2014-11-17 16:09:27 -08001454 // Sanity check the recurrence interval. This will catch people who supply
Christopher Tate22e919d2018-02-16 16:16:50 -08001455 // seconds when the API expects milliseconds, or apps trying shenanigans
1456 // around intentional period overflow, etc.
Dianne Hackborna750a632015-06-16 17:18:23 -07001457 final long minInterval = mConstants.MIN_INTERVAL;
1458 if (interval > 0 && interval < minInterval) {
Christopher Tate498c6cb2014-11-17 16:09:27 -08001459 Slog.w(TAG, "Suspiciously short interval " + interval
Dianne Hackborna750a632015-06-16 17:18:23 -07001460 + " millis; expanding to " + (minInterval/1000)
Christopher Tate498c6cb2014-11-17 16:09:27 -08001461 + " seconds");
Dianne Hackborna750a632015-06-16 17:18:23 -07001462 interval = minInterval;
Christopher Tate22e919d2018-02-16 16:16:50 -08001463 } else if (interval > mConstants.MAX_INTERVAL) {
1464 Slog.w(TAG, "Suspiciously long interval " + interval
1465 + " millis; clamping");
1466 interval = mConstants.MAX_INTERVAL;
Christopher Tate498c6cb2014-11-17 16:09:27 -08001467 }
1468
Christopher Tatee0a22b32013-07-11 14:43:13 -07001469 if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
1470 throw new IllegalArgumentException("Invalid alarm type " + type);
1471 }
1472
Christopher Tate5f221e82013-07-30 17:13:15 -07001473 if (triggerAtTime < 0) {
Christopher Tate5f221e82013-07-30 17:13:15 -07001474 final long what = Binder.getCallingPid();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001475 Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
Christopher Tate5f221e82013-07-30 17:13:15 -07001476 + " pid=" + what);
1477 triggerAtTime = 0;
1478 }
1479
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001480 final long nowElapsed = SystemClock.elapsedRealtime();
Christopher Tate498c6cb2014-11-17 16:09:27 -08001481 final long nominalTrigger = convertToElapsed(triggerAtTime, type);
1482 // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
Dianne Hackborna750a632015-06-16 17:18:23 -07001483 final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
Christopher Tate498c6cb2014-11-17 16:09:27 -08001484 final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
1485
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001486 final long maxElapsed;
1487 if (windowLength == AlarmManager.WINDOW_EXACT) {
1488 maxElapsed = triggerElapsed;
1489 } else if (windowLength < 0) {
1490 maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001491 // Fix this window in place, so that as time approaches we don't collapse it.
1492 windowLength = maxElapsed - triggerElapsed;
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001493 } else {
1494 maxElapsed = triggerElapsed + windowLength;
1495 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 synchronized (mLock) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07001498 if (DEBUG_BATCH) {
1499 Slog.v(TAG, "set(" + operation + ") : type=" + type
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001500 + " triggerAtTime=" + triggerAtTime + " win=" + windowLength
Christopher Tatee0a22b32013-07-11 14:43:13 -07001501 + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001502 + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 }
Christopher Tate3e04b472013-10-21 17:51:31 -07001504 setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001505 interval, operation, directReceiver, listenerTag, flags, true, workSource,
1506 alarmClock, callingUid, callingPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 }
1508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509
Christopher Tate3e04b472013-10-21 17:51:31 -07001510 private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001511 long maxWhen, long interval, PendingIntent operation, IAlarmListener directReceiver,
1512 String listenerTag, int flags, boolean doValidate, WorkSource workSource,
1513 AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) {
Christopher Tate3e04b472013-10-21 17:51:31 -07001514 Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001515 operation, directReceiver, listenerTag, workSource, flags, alarmClock,
1516 callingUid, callingPackage);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001517 try {
Dianne Hackbornc3af19a2017-01-20 17:00:44 -08001518 if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001519 Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
1520 + " -- package not allowed to start");
1521 return;
1522 }
1523 } catch (RemoteException e) {
1524 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07001525 removeLocked(operation, directReceiver);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001526 setImplLocked(a, false, doValidate);
1527 }
Christopher Tateb8849c12011-02-08 13:39:01 -08001528
Suprabh Shukla75edab12018-01-29 14:09:06 -08001529 private long getMinDelayForBucketLocked(int bucket) {
1530 // Return the minimum time that should elapse before an app in the specified bucket
1531 // can receive alarms again
1532 if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) {
1533 return mConstants.APP_STANDBY_MIN_DELAYS[4];
1534 }
1535 else if (bucket >= UsageStatsManager.STANDBY_BUCKET_RARE) {
1536 return mConstants.APP_STANDBY_MIN_DELAYS[3];
1537 }
1538 else if (bucket >= UsageStatsManager.STANDBY_BUCKET_FREQUENT) {
1539 return mConstants.APP_STANDBY_MIN_DELAYS[2];
1540 }
1541 else if (bucket >= UsageStatsManager.STANDBY_BUCKET_WORKING_SET) {
1542 return mConstants.APP_STANDBY_MIN_DELAYS[1];
1543 }
1544 else return mConstants.APP_STANDBY_MIN_DELAYS[0];
1545 }
1546
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001547 /**
1548 * Adjusts the alarm delivery time based on the current app standby bucket.
1549 * @param alarm The alarm to adjust
1550 * @return true if the alarm delivery time was updated.
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001551 */
1552 private boolean adjustDeliveryTimeBasedOnStandbyBucketLocked(Alarm alarm) {
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001553 if (isExemptFromAppStandby(alarm)) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001554 return false;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001555 }
1556 if (mAppStandbyParole) {
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001557 if (alarm.whenElapsed > alarm.expectedWhenElapsed) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001558 // We did defer this alarm earlier, restore original requirements
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001559 alarm.whenElapsed = alarm.expectedWhenElapsed;
1560 alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
1561 return true;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001562 }
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001563 return false;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001564 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001565 final long oldWhenElapsed = alarm.whenElapsed;
1566 final long oldMaxWhenElapsed = alarm.maxWhenElapsed;
1567
Suprabh Shukla75edab12018-01-29 14:09:06 -08001568 final String sourcePackage = alarm.sourcePackage;
1569 final int sourceUserId = UserHandle.getUserId(alarm.creatorUid);
1570 final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket(
1571 sourcePackage, sourceUserId, SystemClock.elapsedRealtime());
1572
1573 final Pair<String, Integer> packageUser = Pair.create(sourcePackage, sourceUserId);
1574 final long lastElapsed = mLastAlarmDeliveredForPackage.getOrDefault(packageUser, 0L);
1575 if (lastElapsed > 0) {
1576 final long minElapsed = lastElapsed + getMinDelayForBucketLocked(standbyBucket);
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001577 if (alarm.expectedWhenElapsed < minElapsed) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08001578 alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001579 } else {
1580 // app is now eligible to run alarms at the originally requested window.
1581 // Restore original requirements in case they were changed earlier.
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001582 alarm.whenElapsed = alarm.expectedWhenElapsed;
1583 alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001584 }
1585 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001586 return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed);
Suprabh Shukla75edab12018-01-29 14:09:06 -08001587 }
1588
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001589 private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
1590 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001591 // This is a special alarm that will put the system into idle until it goes off.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001592 // The caller has given the time they want this to happen at, however we need
1593 // to pull that earlier if there are existing alarms that have requested to
Dianne Hackbornf3831292015-10-15 14:51:06 -07001594 // bring us out of idle at an earlier time.
1595 if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001596 a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001597 }
1598 // Add fuzz to make the alarm go off some time before the actual desired time.
1599 final long nowElapsed = SystemClock.elapsedRealtime();
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001600 final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001601 if (fuzz > 0) {
1602 if (mRandom == null) {
1603 mRandom = new Random();
1604 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001605 final int delta = mRandom.nextInt(fuzz);
1606 a.whenElapsed -= delta;
1607 if (false) {
1608 Slog.d(TAG, "Alarm when: " + a.whenElapsed);
1609 Slog.d(TAG, "Delta until alarm: " + (a.whenElapsed-nowElapsed));
1610 Slog.d(TAG, "Applied fuzz: " + fuzz);
1611 Slog.d(TAG, "Final delta: " + delta);
1612 Slog.d(TAG, "Final when: " + a.whenElapsed);
1613 }
1614 a.when = a.maxWhenElapsed = a.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001615 }
1616
1617 } else if (mPendingIdleUntil != null) {
1618 // We currently have an idle until alarm scheduled; if the new alarm has
1619 // not explicitly stated it wants to run while idle, then put it on hold.
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001620 if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
1621 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
1622 | AlarmManager.FLAG_WAKE_FROM_IDLE))
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001623 == 0) {
1624 mPendingWhileIdleAlarms.add(a);
1625 return;
1626 }
1627 }
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001628 if (RECORD_DEVICE_IDLE_ALARMS) {
1629 if ((a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
1630 IdleDispatchEntry ent = new IdleDispatchEntry();
1631 ent.uid = a.uid;
1632 ent.pkg = a.operation.getCreatorPackage();
1633 ent.tag = a.operation.getTag("");
1634 ent.op = "SET";
1635 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1636 ent.argRealtime = a.whenElapsed;
1637 mAllowWhileIdleDispatches.add(ent);
1638 }
1639 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08001640 adjustDeliveryTimeBasedOnStandbyBucketLocked(a);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001641 insertAndBatchAlarmLocked(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001643 if (a.alarmClock != null) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001644 mNextAlarmClockMayChange = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +02001645 }
1646
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001647 boolean needRebatch = false;
1648
1649 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001650 if (RECORD_DEVICE_IDLE_ALARMS) {
1651 if (mPendingIdleUntil == null) {
1652 IdleDispatchEntry ent = new IdleDispatchEntry();
1653 ent.uid = 0;
1654 ent.pkg = "START IDLE";
1655 ent.elapsedRealtime = SystemClock.elapsedRealtime();
1656 mAllowWhileIdleDispatches.add(ent);
1657 }
1658 }
Makoto Onuki4274a6d2017-04-21 12:21:25 -07001659 if ((mPendingIdleUntil != a) && (mPendingIdleUntil != null)) {
1660 Slog.wtfStack(TAG, "setImplLocked: idle until changed from " + mPendingIdleUntil
1661 + " to " + a);
1662 }
1663
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001664 mPendingIdleUntil = a;
1665 needRebatch = true;
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001666 } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
1667 if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
1668 mNextWakeFromIdle = a;
1669 // If this wake from idle is earlier than whatever was previously scheduled,
1670 // and we are currently idling, then we need to rebatch alarms in case the idle
1671 // until time needs to be updated.
1672 if (mPendingIdleUntil != null) {
1673 needRebatch = true;
1674 }
1675 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001676 }
1677
1678 if (!rebatching) {
1679 if (DEBUG_VALIDATE) {
1680 if (doValidate && !validateConsistencyLocked()) {
1681 Slog.v(TAG, "Tipping-point operation: type=" + a.type + " when=" + a.when
1682 + " when(hex)=" + Long.toHexString(a.when)
1683 + " whenElapsed=" + a.whenElapsed
1684 + " maxWhenElapsed=" + a.maxWhenElapsed
1685 + " interval=" + a.repeatInterval + " op=" + a.operation
1686 + " flags=0x" + Integer.toHexString(a.flags));
1687 rebatchAllAlarmsLocked(false);
1688 needRebatch = false;
1689 }
1690 }
1691
1692 if (needRebatch) {
Christopher Tate4cb338d2013-07-26 13:11:31 -07001693 rebatchAllAlarmsLocked(false);
Christopher Tate4cb338d2013-07-26 13:11:31 -07001694 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001695
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001696 rescheduleKernelAlarmsLocked();
1697 updateNextAlarmClockLocked();
1698 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001699 }
1700
Christopher Tate1d99c392017-12-07 16:54:04 -08001701 /**
1702 * System-process internal API
1703 */
1704 private final class LocalService implements AlarmManagerInternal {
1705 @Override
1706 public void removeAlarmsForUid(int uid) {
1707 synchronized (mLock) {
1708 removeLocked(uid);
1709 }
1710 }
1711 }
1712
1713 /**
1714 * Public-facing binder interface
1715 */
Adam Lesinski182f73f2013-12-05 16:48:06 -08001716 private final IBinder mService = new IAlarmManager.Stub() {
1717 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07001718 public void set(String callingPackage,
1719 int type, long triggerAtTime, long windowLength, long interval, int flags,
1720 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1721 WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001722 final int callingUid = Binder.getCallingUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07001723
1724 // make sure the caller is not lying about which package should be blamed for
1725 // wakelock time spent in alarm delivery
1726 mAppOps.checkPackage(callingUid, callingPackage);
1727
1728 // Repeating alarms must use PendingIntent, not direct listener
1729 if (interval != 0) {
1730 if (directReceiver != null) {
1731 throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers");
1732 }
1733 }
1734
Adam Lesinski182f73f2013-12-05 16:48:06 -08001735 if (workSource != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001736 getContext().enforcePermission(
Adam Lesinski182f73f2013-12-05 16:48:06 -08001737 android.Manifest.permission.UPDATE_DEVICE_STATS,
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001738 Binder.getCallingPid(), callingUid, "AlarmManager.set");
Christopher Tate89779822012-08-31 14:40:03 -07001739 }
1740
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001741 // No incoming callers can request either WAKE_FROM_IDLE or
1742 // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
1743 flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
1744 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
1745
1746 // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
1747 // manager when to come out of idle mode, which is only for DeviceIdleController.
1748 if (callingUid != Process.SYSTEM_UID) {
1749 flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
1750 }
1751
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001752 // If this is an exact time alarm, then it can't be batched with other alarms.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001753 if (windowLength == AlarmManager.WINDOW_EXACT) {
1754 flags |= AlarmManager.FLAG_STANDALONE;
1755 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001756
1757 // If this alarm is for an alarm clock, then it must be standalone and we will
1758 // use it to wake early from idle if needed.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001759 if (alarmClock != null) {
1760 flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001761
1762 // If the caller is a core system component or on the user's whitelist, and not calling
1763 // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
1764 // This means we will allow these alarms to go off as normal even while idle, with no
1765 // timing restrictions.
1766 } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001767 || UserHandle.isSameApp(callingUid, mSystemUiUid)
Makoto Onukie4918212018-02-06 11:30:15 -08001768 || ((mAppStateTracker != null)
1769 && mAppStateTracker.isUidPowerSaveWhitelisted(callingUid)))) {
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001770 flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
1771 flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001772 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001773
Christopher Tate14a7bb02015-10-01 10:24:31 -07001774 setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
1775 listenerTag, flags, workSource, alarmClock, callingUid, callingPackage);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001776 }
Christopher Tate89779822012-08-31 14:40:03 -07001777
Adam Lesinski182f73f2013-12-05 16:48:06 -08001778 @Override
Greg Hackmann0cab8962014-02-21 16:35:52 -08001779 public boolean setTime(long millis) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001780 getContext().enforceCallingOrSelfPermission(
1781 "android.permission.SET_TIME",
1782 "setTime");
1783
mswest463f4c99d2018-02-01 10:13:10 -08001784 return setTimeImpl(millis);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001786
1787 @Override
1788 public void setTimeZone(String tz) {
1789 getContext().enforceCallingOrSelfPermission(
1790 "android.permission.SET_TIME_ZONE",
1791 "setTimeZone");
1792
1793 final long oldId = Binder.clearCallingIdentity();
1794 try {
1795 setTimeZoneImpl(tz);
1796 } finally {
1797 Binder.restoreCallingIdentity(oldId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 }
1799 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001800
Adam Lesinski182f73f2013-12-05 16:48:06 -08001801 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07001802 public void remove(PendingIntent operation, IAlarmListener listener) {
1803 if (operation == null && listener == null) {
1804 Slog.w(TAG, "remove() with no intent or listener");
1805 return;
1806 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001807
Christopher Tate14a7bb02015-10-01 10:24:31 -07001808 synchronized (mLock) {
1809 removeLocked(operation, listener);
1810 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001812
Adam Lesinski182f73f2013-12-05 16:48:06 -08001813 @Override
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001814 public long getNextWakeFromIdleTime() {
1815 return getNextWakeFromIdleTimeImpl();
1816 }
1817
1818 @Override
Jose Lima235510e2014-08-13 12:50:01 -07001819 public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001820 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1821 Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */,
1822 "getNextAlarmClock", null);
1823
1824 return getNextAlarmClockImpl(userId);
1825 }
1826
1827 @Override
Jeff Sharkey9911a282018-02-14 22:29:11 -07001828 public long currentNetworkTimeMillis() {
1829 final NtpTrustedTime time = NtpTrustedTime.getInstance(getContext());
1830 if (time.hasCache()) {
1831 return time.currentTimeMillis();
1832 } else {
1833 throw new ParcelableException(new DateTimeException("Missing NTP fix"));
1834 }
1835 }
1836
1837 @Override
Adam Lesinski182f73f2013-12-05 16:48:06 -08001838 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -06001839 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
Kweku Adams61e03292017-10-19 14:27:12 -07001840
1841 if (args.length > 0 && "--proto".equals(args[0])) {
1842 dumpProto(fd);
1843 } else {
1844 dumpImpl(pw);
1845 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001846 }
mswest463f4c99d2018-02-01 10:13:10 -08001847
1848 @Override
1849 public void onShellCommand(FileDescriptor in, FileDescriptor out,
1850 FileDescriptor err, String[] args, ShellCallback callback,
1851 ResultReceiver resultReceiver) {
1852 (new ShellCmd()).exec(this, in, out, err, args, callback, resultReceiver);
1853 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001854 };
Christopher Tate4cb338d2013-07-26 13:11:31 -07001855
Adam Lesinski182f73f2013-12-05 16:48:06 -08001856 void dumpImpl(PrintWriter pw) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 synchronized (mLock) {
1858 pw.println("Current Alarm Manager state:");
Dianne Hackborna750a632015-06-16 17:18:23 -07001859 mConstants.dump(pw);
1860 pw.println();
1861
Makoto Onukie4918212018-02-06 11:30:15 -08001862 if (mAppStateTracker != null) {
1863 mAppStateTracker.dump(pw, " ");
1864 pw.println();
1865 }
Makoto Onuki2206af32017-11-21 16:25:35 -08001866
Suprabh Shukla75edab12018-01-29 14:09:06 -08001867 pw.println(" App Standby Parole: " + mAppStandbyParole);
1868 pw.println();
1869
Christopher Tatee0a22b32013-07-11 14:43:13 -07001870 final long nowRTC = System.currentTimeMillis();
1871 final long nowELAPSED = SystemClock.elapsedRealtime();
Makoto Onukie8edbcf2018-03-02 16:49:29 -08001872 final long nowUPTIME = SystemClock.uptimeMillis();
Makoto Onuki5d93b832018-01-10 16:12:39 -08001873 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Christopher Tatee0a22b32013-07-11 14:43:13 -07001874
Dianne Hackborna750a632015-06-16 17:18:23 -07001875 pw.print(" nowRTC="); pw.print(nowRTC);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001876 pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
Christopher Tate7f2a0352015-12-08 10:24:33 -08001877 pw.print(" nowELAPSED="); pw.print(nowELAPSED);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001878 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001879 pw.print(" mLastTimeChangeClockTime="); pw.print(mLastTimeChangeClockTime);
Dianne Hackbornc3527222015-05-13 14:03:20 -07001880 pw.print("="); pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
Christopher Tate12cf0b62018-01-05 18:40:14 -08001881 pw.print(" mLastTimeChangeRealtime="); pw.println(mLastTimeChangeRealtime);
1882 pw.print(" mLastTickIssued=");
Makoto Onuki5d93b832018-01-10 16:12:39 -08001883 pw.println(sdf.format(new Date(nowRTC - (nowELAPSED - mLastTickIssued))));
Christopher Tate12cf0b62018-01-05 18:40:14 -08001884 pw.print(" mLastTickReceived="); pw.println(sdf.format(new Date(mLastTickReceived)));
1885 pw.print(" mLastTickSet="); pw.println(sdf.format(new Date(mLastTickSet)));
Makoto Onuki5d93b832018-01-10 16:12:39 -08001886 pw.print(" mLastTickAdded="); pw.println(sdf.format(new Date(mLastTickAdded)));
1887 pw.print(" mLastTickRemoved="); pw.println(sdf.format(new Date(mLastTickRemoved)));
Makoto Onukie8edbcf2018-03-02 16:49:29 -08001888
1889 SystemServiceManager ssm = LocalServices.getService(SystemServiceManager.class);
1890 if (ssm != null) {
1891 pw.println();
1892 pw.print(" RuntimeStarted=");
1893 pw.print(sdf.format(
1894 new Date(nowRTC - nowELAPSED + ssm.getRuntimeStartElapsedTime())));
1895 if (ssm.isRuntimeRestarted()) {
1896 pw.print(" (Runtime restarted)");
1897 }
1898 pw.println();
1899 pw.print(" Runtime uptime (elapsed): ");
1900 TimeUtils.formatDuration(nowELAPSED, ssm.getRuntimeStartElapsedTime(), pw);
1901 pw.println();
1902 pw.print(" Runtime uptime (uptime): ");
1903 TimeUtils.formatDuration(nowUPTIME, ssm.getRuntimeStartUptime(), pw);
1904 pw.println();
1905 }
1906
Dianne Hackbornc3527222015-05-13 14:03:20 -07001907 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001908 if (!mInteractive) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001909 pw.print(" Time since non-interactive: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001910 TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
1911 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001912 }
Makoto Onuki0b05aa62018-02-09 16:14:26 -08001913 pw.print(" Max wakeup delay: ");
1914 TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
1915 pw.println();
1916 pw.print(" Time since last dispatch: ");
1917 TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
1918 pw.println();
1919 pw.print(" Next non-wakeup delivery time: ");
1920 TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
1921 pw.println();
Christopher Tatee0a22b32013-07-11 14:43:13 -07001922
1923 long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
1924 long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
Dianne Hackborna750a632015-06-16 17:18:23 -07001925 pw.print(" Next non-wakeup alarm: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001926 TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
Christopher Tate8b98ade2018-02-09 11:13:19 -08001927 pw.print(" = "); pw.print(mNextNonWakeup);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001928 pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
Christopher Tate8b98ade2018-02-09 11:13:19 -08001929 pw.print(" Next wakeup alarm: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
1930 pw.print(" = "); pw.print(mNextWakeup);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001931 pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
Christopher Tate8b98ade2018-02-09 11:13:19 -08001932 pw.print(" set at "); TimeUtils.formatDuration(mLastWakeupSet, nowELAPSED, pw);
1933 pw.println();
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07001934 pw.print(" Last wakeup: "); TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw);
Christopher Tate8b98ade2018-02-09 11:13:19 -08001935 pw.print(" = "); pw.println(mLastWakeup);
1936 pw.print(" Last trigger: "); TimeUtils.formatDuration(mLastTrigger, nowELAPSED, pw);
1937 pw.print(" = "); pw.println(mLastTrigger);
Dianne Hackborna750a632015-06-16 17:18:23 -07001938 pw.print(" Num time change events: "); pw.println(mNumTimeChanged);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001939
John Spurlock604a5ee2015-06-01 12:27:22 -04001940 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001941 pw.println(" Next alarm clock information: ");
John Spurlock604a5ee2015-06-01 12:27:22 -04001942 final TreeSet<Integer> users = new TreeSet<>();
1943 for (int i = 0; i < mNextAlarmClockForUser.size(); i++) {
1944 users.add(mNextAlarmClockForUser.keyAt(i));
1945 }
1946 for (int i = 0; i < mPendingSendNextAlarmClockChangedForUser.size(); i++) {
1947 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
1948 }
1949 for (int user : users) {
1950 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
1951 final long time = next != null ? next.getTriggerTime() : 0;
1952 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
Dianne Hackborna750a632015-06-16 17:18:23 -07001953 pw.print(" user:"); pw.print(user);
John Spurlock604a5ee2015-06-01 12:27:22 -04001954 pw.print(" pendingSend:"); pw.print(pendingSend);
1955 pw.print(" time:"); pw.print(time);
1956 if (time > 0) {
1957 pw.print(" = "); pw.print(sdf.format(new Date(time)));
1958 pw.print(" = "); TimeUtils.formatDuration(time, nowRTC, pw);
1959 }
1960 pw.println();
1961 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001962 if (mAlarmBatches.size() > 0) {
1963 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001964 pw.print(" Pending alarm batches: ");
Christopher Tatee0a22b32013-07-11 14:43:13 -07001965 pw.println(mAlarmBatches.size());
1966 for (Batch b : mAlarmBatches) {
1967 pw.print(b); pw.println(':');
Dianne Hackborna750a632015-06-16 17:18:23 -07001968 dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001971 pw.println();
1972 pw.println(" Pending user blocked background alarms: ");
1973 boolean blocked = false;
1974 for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
1975 final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
1976 if (blockedAlarms != null && blockedAlarms.size() > 0) {
1977 blocked = true;
1978 dumpAlarmList(pw, blockedAlarms, " ", nowELAPSED, nowRTC, sdf);
1979 }
1980 }
1981 if (!blocked) {
1982 pw.println(" none");
1983 }
Suprabh Shuklac25447d2018-01-19 16:43:35 -08001984
Suprabh Shukla75edab12018-01-29 14:09:06 -08001985 pw.println(" mLastAlarmDeliveredForPackage:");
1986 for (int i = 0; i < mLastAlarmDeliveredForPackage.size(); i++) {
1987 Pair<String, Integer> packageUser = mLastAlarmDeliveredForPackage.keyAt(i);
1988 pw.print(" Package " + packageUser.first + ", User " + packageUser.second + ":");
1989 TimeUtils.formatDuration(mLastAlarmDeliveredForPackage.valueAt(i), nowELAPSED, pw);
1990 pw.println();
1991 }
1992 pw.println();
1993
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001994 if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001995 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001996 pw.println(" Idle mode state:");
1997 pw.print(" Idling until: ");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001998 if (mPendingIdleUntil != null) {
1999 pw.println(mPendingIdleUntil);
Kweku Adams61e03292017-10-19 14:27:12 -07002000 mPendingIdleUntil.dump(pw, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002001 } else {
2002 pw.println("null");
2003 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002004 pw.println(" Pending alarms:");
2005 dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002006 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002007 if (mNextWakeFromIdle != null) {
2008 pw.println();
2009 pw.print(" Next wake from idle: "); pw.println(mNextWakeFromIdle);
Kweku Adams61e03292017-10-19 14:27:12 -07002010 mNextWakeFromIdle.dump(pw, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002011 }
Dianne Hackborn81038902012-11-26 17:04:09 -08002012
2013 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002014 pw.print(" Past-due non-wakeup alarms: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002015 if (mPendingNonWakeupAlarms.size() > 0) {
2016 pw.println(mPendingNonWakeupAlarms.size());
Dianne Hackborna750a632015-06-16 17:18:23 -07002017 dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002018 } else {
2019 pw.println("(none)");
2020 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002021 pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002022 pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
2023 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002024 pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002025 pw.print(", max non-interactive time: ");
2026 TimeUtils.formatDuration(mNonInteractiveTime, pw);
2027 pw.println();
2028
2029 pw.println();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002030 pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
Christopher Tateeabba732017-08-17 17:12:52 -07002031 pw.print(" PendingIntent send count: "); pw.println(mSendCount);
2032 pw.print(" PendingIntent finish count: "); pw.println(mSendFinishCount);
2033 pw.print(" Listener send count: "); pw.println(mListenerCount);
2034 pw.print(" Listener finish count: "); pw.println(mListenerFinishCount);
Dianne Hackborn81038902012-11-26 17:04:09 -08002035 pw.println();
2036
Christopher Tate7f2a0352015-12-08 10:24:33 -08002037 if (mInFlight.size() > 0) {
2038 pw.println("Outstanding deliveries:");
2039 for (int i = 0; i < mInFlight.size(); i++) {
2040 pw.print(" #"); pw.print(i); pw.print(": ");
2041 pw.println(mInFlight.get(i));
2042 }
2043 pw.println();
2044 }
2045
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002046 if (mLastAllowWhileIdleDispatch.size() > 0) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002047 pw.println(" Last allow while idle dispatch times:");
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002048 for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
Makoto Onukiadb50d82018-01-29 16:20:30 -08002049 pw.print(" UID ");
2050 final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
2051 UserHandle.formatUid(pw, uid);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002052 pw.print(": ");
Makoto Onukiadb50d82018-01-29 16:20:30 -08002053 final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
2054 TimeUtils.formatDuration(lastTime, nowELAPSED, pw);
2055
2056 final long minInterval = getWhileIdleMinIntervalLocked(uid);
2057 pw.print(" Next allowed:");
2058 TimeUtils.formatDuration(lastTime + minInterval, nowELAPSED, pw);
2059 pw.print(" (");
2060 TimeUtils.formatDuration(minInterval, 0, pw);
2061 pw.print(")");
2062
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002063 pw.println();
2064 }
2065 }
Makoto Onukiadb50d82018-01-29 16:20:30 -08002066
2067 pw.print(" mUseAllowWhileIdleShortTime: [");
2068 for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
2069 if (mUseAllowWhileIdleShortTime.valueAt(i)) {
2070 UserHandle.formatUid(pw, mUseAllowWhileIdleShortTime.keyAt(i));
2071 pw.print(" ");
2072 }
2073 }
2074 pw.println("]");
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002075 pw.println();
2076
Dianne Hackborn81038902012-11-26 17:04:09 -08002077 if (mLog.dump(pw, " Recent problems", " ")) {
2078 pw.println();
2079 }
2080
2081 final FilterStats[] topFilters = new FilterStats[10];
2082 final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
2083 @Override
2084 public int compare(FilterStats lhs, FilterStats rhs) {
2085 if (lhs.aggregateTime < rhs.aggregateTime) {
2086 return 1;
2087 } else if (lhs.aggregateTime > rhs.aggregateTime) {
2088 return -1;
2089 }
2090 return 0;
2091 }
2092 };
2093 int len = 0;
Kweku Adams61e03292017-10-19 14:27:12 -07002094 // Get the top 10 FilterStats, ordered by aggregateTime.
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002095 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
2096 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2097 for (int ip=0; ip<uidStats.size(); ip++) {
2098 BroadcastStats bs = uidStats.valueAt(ip);
2099 for (int is=0; is<bs.filterStats.size(); is++) {
2100 FilterStats fs = bs.filterStats.valueAt(is);
2101 int pos = len > 0
2102 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
2103 if (pos < 0) {
2104 pos = -pos - 1;
Dianne Hackborn81038902012-11-26 17:04:09 -08002105 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002106 if (pos < topFilters.length) {
2107 int copylen = topFilters.length - pos - 1;
2108 if (copylen > 0) {
2109 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
2110 }
2111 topFilters[pos] = fs;
2112 if (len < topFilters.length) {
2113 len++;
2114 }
Dianne Hackborn81038902012-11-26 17:04:09 -08002115 }
2116 }
2117 }
2118 }
2119 if (len > 0) {
2120 pw.println(" Top Alarms:");
2121 for (int i=0; i<len; i++) {
2122 FilterStats fs = topFilters[i];
2123 pw.print(" ");
2124 if (fs.nesting > 0) pw.print("*ACTIVE* ");
2125 TimeUtils.formatDuration(fs.aggregateTime, pw);
2126 pw.print(" running, "); pw.print(fs.numWakeup);
2127 pw.print(" wakeups, "); pw.print(fs.count);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002128 pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
2129 pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
Dianne Hackborn81038902012-11-26 17:04:09 -08002130 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002131 pw.print(" "); pw.print(fs.mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08002132 pw.println();
2133 }
2134 }
2135
2136 pw.println(" ");
2137 pw.println(" Alarm Stats:");
2138 final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002139 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
2140 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2141 for (int ip=0; ip<uidStats.size(); ip++) {
2142 BroadcastStats bs = uidStats.valueAt(ip);
2143 pw.print(" ");
2144 if (bs.nesting > 0) pw.print("*ACTIVE* ");
2145 UserHandle.formatUid(pw, bs.mUid);
2146 pw.print(":");
2147 pw.print(bs.mPackageName);
2148 pw.print(" "); TimeUtils.formatDuration(bs.aggregateTime, pw);
2149 pw.print(" running, "); pw.print(bs.numWakeup);
2150 pw.println(" wakeups:");
2151 tmpFilters.clear();
2152 for (int is=0; is<bs.filterStats.size(); is++) {
2153 tmpFilters.add(bs.filterStats.valueAt(is));
2154 }
2155 Collections.sort(tmpFilters, comparator);
2156 for (int i=0; i<tmpFilters.size(); i++) {
2157 FilterStats fs = tmpFilters.get(i);
2158 pw.print(" ");
2159 if (fs.nesting > 0) pw.print("*ACTIVE* ");
2160 TimeUtils.formatDuration(fs.aggregateTime, pw);
2161 pw.print(" "); pw.print(fs.numWakeup);
2162 pw.print(" wakes " ); pw.print(fs.count);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002163 pw.print(" alarms, last ");
2164 TimeUtils.formatDuration(fs.lastTime, nowELAPSED, pw);
2165 pw.println(":");
2166 pw.print(" ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002167 pw.print(fs.mTag);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002168 pw.println();
2169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 }
2171 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08002172 pw.println();
2173 mStatLogger.dump(pw, " ");
Christopher Tate18a75f12013-07-01 18:18:59 -07002174
Dianne Hackbornae78bf82015-10-26 13:33:20 -07002175 if (RECORD_DEVICE_IDLE_ALARMS) {
2176 pw.println();
2177 pw.println(" Allow while idle dispatches:");
2178 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
2179 IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
2180 pw.print(" ");
2181 TimeUtils.formatDuration(ent.elapsedRealtime, nowELAPSED, pw);
2182 pw.print(": ");
2183 UserHandle.formatUid(pw, ent.uid);
2184 pw.print(":");
2185 pw.println(ent.pkg);
2186 if (ent.op != null) {
2187 pw.print(" ");
2188 pw.print(ent.op);
2189 pw.print(" / ");
2190 pw.print(ent.tag);
2191 if (ent.argRealtime != 0) {
2192 pw.print(" (");
2193 TimeUtils.formatDuration(ent.argRealtime, nowELAPSED, pw);
2194 pw.print(")");
2195 }
2196 pw.println();
2197 }
2198 }
2199 }
2200
Christopher Tate18a75f12013-07-01 18:18:59 -07002201 if (WAKEUP_STATS) {
2202 pw.println();
2203 pw.println(" Recent Wakeup History:");
Christopher Tate18a75f12013-07-01 18:18:59 -07002204 long last = -1;
2205 for (WakeupEvent event : mRecentWakeups) {
2206 pw.print(" "); pw.print(sdf.format(new Date(event.when)));
2207 pw.print('|');
2208 if (last < 0) {
2209 pw.print('0');
2210 } else {
2211 pw.print(event.when - last);
2212 }
2213 last = event.when;
2214 pw.print('|'); pw.print(event.uid);
2215 pw.print('|'); pw.print(event.action);
2216 pw.println();
2217 }
2218 pw.println();
2219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 }
2221 }
2222
Kweku Adams61e03292017-10-19 14:27:12 -07002223 void dumpProto(FileDescriptor fd) {
2224 final ProtoOutputStream proto = new ProtoOutputStream(fd);
2225
2226 synchronized (mLock) {
2227 final long nowRTC = System.currentTimeMillis();
2228 final long nowElapsed = SystemClock.elapsedRealtime();
Yi Jin2b30f322018-02-20 15:41:47 -08002229 proto.write(AlarmManagerServiceDumpProto.CURRENT_TIME, nowRTC);
2230 proto.write(AlarmManagerServiceDumpProto.ELAPSED_REALTIME, nowElapsed);
2231 proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_CLOCK_TIME,
Kweku Adams61e03292017-10-19 14:27:12 -07002232 mLastTimeChangeClockTime);
Yi Jin2b30f322018-02-20 15:41:47 -08002233 proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_REALTIME,
Kweku Adams61e03292017-10-19 14:27:12 -07002234 mLastTimeChangeRealtime);
2235
Yi Jin2b30f322018-02-20 15:41:47 -08002236 mConstants.dumpProto(proto, AlarmManagerServiceDumpProto.SETTINGS);
Kweku Adams61e03292017-10-19 14:27:12 -07002237
Makoto Onukie4918212018-02-06 11:30:15 -08002238 if (mAppStateTracker != null) {
2239 mAppStateTracker.dumpProto(proto,
Yi Jin2b30f322018-02-20 15:41:47 -08002240 AlarmManagerServiceDumpProto.FORCE_APP_STANDBY_TRACKER);
Makoto Onukie4918212018-02-06 11:30:15 -08002241 }
Kweku Adams61e03292017-10-19 14:27:12 -07002242
Yi Jin2b30f322018-02-20 15:41:47 -08002243 proto.write(AlarmManagerServiceDumpProto.IS_INTERACTIVE, mInteractive);
Kweku Adams61e03292017-10-19 14:27:12 -07002244 if (!mInteractive) {
2245 // Durations
Yi Jin2b30f322018-02-20 15:41:47 -08002246 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_NON_INTERACTIVE_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002247 nowElapsed - mNonInteractiveStartTime);
Yi Jin2b30f322018-02-20 15:41:47 -08002248 proto.write(AlarmManagerServiceDumpProto.MAX_WAKEUP_DELAY_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002249 currentNonWakeupFuzzLocked(nowElapsed));
Yi Jin2b30f322018-02-20 15:41:47 -08002250 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_DISPATCH_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002251 nowElapsed - mLastAlarmDeliveryTime);
Yi Jin2b30f322018-02-20 15:41:47 -08002252 proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_NON_WAKEUP_DELIVERY_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002253 nowElapsed - mNextNonWakeupDeliveryTime);
2254 }
2255
Yi Jin2b30f322018-02-20 15:41:47 -08002256 proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_NON_WAKEUP_ALARM_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002257 mNextNonWakeup - nowElapsed);
Yi Jin2b30f322018-02-20 15:41:47 -08002258 proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_WAKEUP_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002259 mNextWakeup - nowElapsed);
Yi Jin2b30f322018-02-20 15:41:47 -08002260 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_WAKEUP_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002261 nowElapsed - mLastWakeup);
Yi Jin2b30f322018-02-20 15:41:47 -08002262 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_WAKEUP_SET_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002263 nowElapsed - mLastWakeupSet);
Yi Jin2b30f322018-02-20 15:41:47 -08002264 proto.write(AlarmManagerServiceDumpProto.TIME_CHANGE_EVENT_COUNT, mNumTimeChanged);
Kweku Adams61e03292017-10-19 14:27:12 -07002265
2266 final TreeSet<Integer> users = new TreeSet<>();
2267 final int nextAlarmClockForUserSize = mNextAlarmClockForUser.size();
2268 for (int i = 0; i < nextAlarmClockForUserSize; i++) {
2269 users.add(mNextAlarmClockForUser.keyAt(i));
2270 }
2271 final int pendingSendNextAlarmClockChangedForUserSize =
2272 mPendingSendNextAlarmClockChangedForUser.size();
2273 for (int i = 0; i < pendingSendNextAlarmClockChangedForUserSize; i++) {
2274 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
2275 }
2276 for (int user : users) {
2277 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
2278 final long time = next != null ? next.getTriggerTime() : 0;
2279 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
Yi Jin2b30f322018-02-20 15:41:47 -08002280 final long aToken = proto.start(AlarmManagerServiceDumpProto.NEXT_ALARM_CLOCK_METADATA);
Kweku Adams61e03292017-10-19 14:27:12 -07002281 proto.write(AlarmClockMetadataProto.USER, user);
2282 proto.write(AlarmClockMetadataProto.IS_PENDING_SEND, pendingSend);
2283 proto.write(AlarmClockMetadataProto.TRIGGER_TIME_MS, time);
2284 proto.end(aToken);
2285 }
2286 for (Batch b : mAlarmBatches) {
Yi Jin2b30f322018-02-20 15:41:47 -08002287 b.writeToProto(proto, AlarmManagerServiceDumpProto.PENDING_ALARM_BATCHES,
Kweku Adams61e03292017-10-19 14:27:12 -07002288 nowElapsed, nowRTC);
2289 }
2290 for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
2291 final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
2292 if (blockedAlarms != null) {
2293 for (Alarm a : blockedAlarms) {
2294 a.writeToProto(proto,
Yi Jin2b30f322018-02-20 15:41:47 -08002295 AlarmManagerServiceDumpProto.PENDING_USER_BLOCKED_BACKGROUND_ALARMS,
Kweku Adams61e03292017-10-19 14:27:12 -07002296 nowElapsed, nowRTC);
2297 }
2298 }
2299 }
2300 if (mPendingIdleUntil != null) {
2301 mPendingIdleUntil.writeToProto(
Yi Jin2b30f322018-02-20 15:41:47 -08002302 proto, AlarmManagerServiceDumpProto.PENDING_IDLE_UNTIL, nowElapsed, nowRTC);
Kweku Adams61e03292017-10-19 14:27:12 -07002303 }
2304 for (Alarm a : mPendingWhileIdleAlarms) {
Yi Jin2b30f322018-02-20 15:41:47 -08002305 a.writeToProto(proto, AlarmManagerServiceDumpProto.PENDING_WHILE_IDLE_ALARMS,
Kweku Adams61e03292017-10-19 14:27:12 -07002306 nowElapsed, nowRTC);
2307 }
2308 if (mNextWakeFromIdle != null) {
Yi Jin2b30f322018-02-20 15:41:47 -08002309 mNextWakeFromIdle.writeToProto(proto, AlarmManagerServiceDumpProto.NEXT_WAKE_FROM_IDLE,
Kweku Adams61e03292017-10-19 14:27:12 -07002310 nowElapsed, nowRTC);
2311 }
2312
2313 for (Alarm a : mPendingNonWakeupAlarms) {
Yi Jin2b30f322018-02-20 15:41:47 -08002314 a.writeToProto(proto, AlarmManagerServiceDumpProto.PAST_DUE_NON_WAKEUP_ALARMS,
Kweku Adams61e03292017-10-19 14:27:12 -07002315 nowElapsed, nowRTC);
2316 }
2317
Yi Jin2b30f322018-02-20 15:41:47 -08002318 proto.write(AlarmManagerServiceDumpProto.DELAYED_ALARM_COUNT, mNumDelayedAlarms);
2319 proto.write(AlarmManagerServiceDumpProto.TOTAL_DELAY_TIME_MS, mTotalDelayTime);
2320 proto.write(AlarmManagerServiceDumpProto.MAX_DELAY_DURATION_MS, mMaxDelayTime);
2321 proto.write(AlarmManagerServiceDumpProto.MAX_NON_INTERACTIVE_DURATION_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002322 mNonInteractiveTime);
2323
Yi Jin2b30f322018-02-20 15:41:47 -08002324 proto.write(AlarmManagerServiceDumpProto.BROADCAST_REF_COUNT, mBroadcastRefCount);
2325 proto.write(AlarmManagerServiceDumpProto.PENDING_INTENT_SEND_COUNT, mSendCount);
2326 proto.write(AlarmManagerServiceDumpProto.PENDING_INTENT_FINISH_COUNT, mSendFinishCount);
2327 proto.write(AlarmManagerServiceDumpProto.LISTENER_SEND_COUNT, mListenerCount);
2328 proto.write(AlarmManagerServiceDumpProto.LISTENER_FINISH_COUNT, mListenerFinishCount);
Kweku Adams61e03292017-10-19 14:27:12 -07002329
2330 for (InFlight f : mInFlight) {
Yi Jin2b30f322018-02-20 15:41:47 -08002331 f.writeToProto(proto, AlarmManagerServiceDumpProto.OUTSTANDING_DELIVERIES);
Kweku Adams61e03292017-10-19 14:27:12 -07002332 }
2333
Kweku Adams61e03292017-10-19 14:27:12 -07002334 for (int i = 0; i < mLastAllowWhileIdleDispatch.size(); ++i) {
2335 final long token = proto.start(
Yi Jin2b30f322018-02-20 15:41:47 -08002336 AlarmManagerServiceDumpProto.LAST_ALLOW_WHILE_IDLE_DISPATCH_TIMES);
Makoto Onukiadb50d82018-01-29 16:20:30 -08002337 final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
2338 final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
2339
Yi Jin2b30f322018-02-20 15:41:47 -08002340 proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.UID, uid);
2341 proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.TIME_MS, lastTime);
2342 proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.NEXT_ALLOWED_MS,
Makoto Onukiadb50d82018-01-29 16:20:30 -08002343 lastTime + getWhileIdleMinIntervalLocked(uid));
Kweku Adams61e03292017-10-19 14:27:12 -07002344 proto.end(token);
2345 }
2346
Makoto Onukiadb50d82018-01-29 16:20:30 -08002347 for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
2348 if (mUseAllowWhileIdleShortTime.valueAt(i)) {
Yi Jin2b30f322018-02-20 15:41:47 -08002349 proto.write(AlarmManagerServiceDumpProto.USE_ALLOW_WHILE_IDLE_SHORT_TIME,
Makoto Onukiadb50d82018-01-29 16:20:30 -08002350 mUseAllowWhileIdleShortTime.keyAt(i));
2351 }
2352 }
2353
Yi Jin2b30f322018-02-20 15:41:47 -08002354 mLog.writeToProto(proto, AlarmManagerServiceDumpProto.RECENT_PROBLEMS);
Kweku Adams61e03292017-10-19 14:27:12 -07002355
2356 final FilterStats[] topFilters = new FilterStats[10];
2357 final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
2358 @Override
2359 public int compare(FilterStats lhs, FilterStats rhs) {
2360 if (lhs.aggregateTime < rhs.aggregateTime) {
2361 return 1;
2362 } else if (lhs.aggregateTime > rhs.aggregateTime) {
2363 return -1;
2364 }
2365 return 0;
2366 }
2367 };
2368 int len = 0;
2369 // Get the top 10 FilterStats, ordered by aggregateTime.
2370 for (int iu = 0; iu < mBroadcastStats.size(); ++iu) {
2371 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2372 for (int ip = 0; ip < uidStats.size(); ++ip) {
2373 BroadcastStats bs = uidStats.valueAt(ip);
2374 for (int is = 0; is < bs.filterStats.size(); ++is) {
2375 FilterStats fs = bs.filterStats.valueAt(is);
2376 int pos = len > 0
2377 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
2378 if (pos < 0) {
2379 pos = -pos - 1;
2380 }
2381 if (pos < topFilters.length) {
2382 int copylen = topFilters.length - pos - 1;
2383 if (copylen > 0) {
2384 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
2385 }
2386 topFilters[pos] = fs;
2387 if (len < topFilters.length) {
2388 len++;
2389 }
2390 }
2391 }
2392 }
2393 }
2394 for (int i = 0; i < len; ++i) {
Yi Jin2b30f322018-02-20 15:41:47 -08002395 final long token = proto.start(AlarmManagerServiceDumpProto.TOP_ALARMS);
Kweku Adams61e03292017-10-19 14:27:12 -07002396 FilterStats fs = topFilters[i];
2397
Yi Jin2b30f322018-02-20 15:41:47 -08002398 proto.write(AlarmManagerServiceDumpProto.TopAlarm.UID, fs.mBroadcastStats.mUid);
2399 proto.write(AlarmManagerServiceDumpProto.TopAlarm.PACKAGE_NAME,
Kweku Adams61e03292017-10-19 14:27:12 -07002400 fs.mBroadcastStats.mPackageName);
Yi Jin2b30f322018-02-20 15:41:47 -08002401 fs.writeToProto(proto, AlarmManagerServiceDumpProto.TopAlarm.FILTER);
Kweku Adams61e03292017-10-19 14:27:12 -07002402
2403 proto.end(token);
2404 }
2405
2406 final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
2407 for (int iu = 0; iu < mBroadcastStats.size(); ++iu) {
2408 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2409 for (int ip = 0; ip < uidStats.size(); ++ip) {
Yi Jin2b30f322018-02-20 15:41:47 -08002410 final long token = proto.start(AlarmManagerServiceDumpProto.ALARM_STATS);
Kweku Adams61e03292017-10-19 14:27:12 -07002411
2412 BroadcastStats bs = uidStats.valueAt(ip);
Yi Jin2b30f322018-02-20 15:41:47 -08002413 bs.writeToProto(proto, AlarmManagerServiceDumpProto.AlarmStat.BROADCAST);
Kweku Adams61e03292017-10-19 14:27:12 -07002414
2415 // uidStats is an ArrayMap, which we can't sort.
2416 tmpFilters.clear();
2417 for (int is = 0; is < bs.filterStats.size(); ++is) {
2418 tmpFilters.add(bs.filterStats.valueAt(is));
2419 }
2420 Collections.sort(tmpFilters, comparator);
2421 for (FilterStats fs : tmpFilters) {
Yi Jin2b30f322018-02-20 15:41:47 -08002422 fs.writeToProto(proto, AlarmManagerServiceDumpProto.AlarmStat.FILTERS);
Kweku Adams61e03292017-10-19 14:27:12 -07002423 }
2424
2425 proto.end(token);
2426 }
2427 }
2428
2429 if (RECORD_DEVICE_IDLE_ALARMS) {
2430 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
2431 IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
2432 final long token = proto.start(
Yi Jin2b30f322018-02-20 15:41:47 -08002433 AlarmManagerServiceDumpProto.ALLOW_WHILE_IDLE_DISPATCHES);
Kweku Adams61e03292017-10-19 14:27:12 -07002434
2435 proto.write(IdleDispatchEntryProto.UID, ent.uid);
2436 proto.write(IdleDispatchEntryProto.PKG, ent.pkg);
2437 proto.write(IdleDispatchEntryProto.TAG, ent.tag);
2438 proto.write(IdleDispatchEntryProto.OP, ent.op);
2439 proto.write(IdleDispatchEntryProto.ENTRY_CREATION_REALTIME,
2440 ent.elapsedRealtime);
2441 proto.write(IdleDispatchEntryProto.ARG_REALTIME, ent.argRealtime);
2442
2443 proto.end(token);
2444 }
2445 }
2446
2447 if (WAKEUP_STATS) {
2448 for (WakeupEvent event : mRecentWakeups) {
Yi Jin2b30f322018-02-20 15:41:47 -08002449 final long token = proto.start(AlarmManagerServiceDumpProto.RECENT_WAKEUP_HISTORY);
Kweku Adams61e03292017-10-19 14:27:12 -07002450 proto.write(WakeupEventProto.UID, event.uid);
2451 proto.write(WakeupEventProto.ACTION, event.action);
2452 proto.write(WakeupEventProto.WHEN, event.when);
2453 proto.end(token);
2454 }
2455 }
2456 }
2457
2458 proto.flush();
2459 }
2460
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002461 private void logBatchesLocked(SimpleDateFormat sdf) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08002462 ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
2463 PrintWriter pw = new PrintWriter(bs);
2464 final long nowRTC = System.currentTimeMillis();
2465 final long nowELAPSED = SystemClock.elapsedRealtime();
2466 final int NZ = mAlarmBatches.size();
2467 for (int iz = 0; iz < NZ; iz++) {
2468 Batch bz = mAlarmBatches.get(iz);
2469 pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002470 dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC, sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002471 pw.flush();
2472 Slog.v(TAG, bs.toString());
2473 bs.reset();
2474 }
2475 }
2476
2477 private boolean validateConsistencyLocked() {
2478 if (DEBUG_VALIDATE) {
2479 long lastTime = Long.MIN_VALUE;
2480 final int N = mAlarmBatches.size();
2481 for (int i = 0; i < N; i++) {
2482 Batch b = mAlarmBatches.get(i);
2483 if (b.start >= lastTime) {
2484 // duplicate start times are okay because of standalone batches
2485 lastTime = b.start;
2486 } else {
2487 Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002488 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2489 logBatchesLocked(sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002490 return false;
2491 }
2492 }
2493 }
2494 return true;
2495 }
2496
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002497 private Batch findFirstWakeupBatchLocked() {
2498 final int N = mAlarmBatches.size();
2499 for (int i = 0; i < N; i++) {
2500 Batch b = mAlarmBatches.get(i);
2501 if (b.hasWakeups()) {
2502 return b;
2503 }
2504 }
2505 return null;
2506 }
2507
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002508 long getNextWakeFromIdleTimeImpl() {
2509 synchronized (mLock) {
2510 return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE;
2511 }
2512 }
2513
2514 AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02002515 synchronized (mLock) {
2516 return mNextAlarmClockForUser.get(userId);
2517 }
2518 }
2519
2520 /**
2521 * Recomputes the next alarm clock for all users.
2522 */
2523 private void updateNextAlarmClockLocked() {
2524 if (!mNextAlarmClockMayChange) {
2525 return;
2526 }
2527 mNextAlarmClockMayChange = false;
2528
Jose Lima235510e2014-08-13 12:50:01 -07002529 SparseArray<AlarmManager.AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02002530 nextForUser.clear();
2531
2532 final int N = mAlarmBatches.size();
2533 for (int i = 0; i < N; i++) {
2534 ArrayList<Alarm> alarms = mAlarmBatches.get(i).alarms;
2535 final int M = alarms.size();
2536
2537 for (int j = 0; j < M; j++) {
2538 Alarm a = alarms.get(j);
2539 if (a.alarmClock != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002540 final int userId = UserHandle.getUserId(a.uid);
Christopher Tate76389c02016-08-03 14:57:47 -07002541 AlarmManager.AlarmClockInfo current = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002542
2543 if (DEBUG_ALARM_CLOCK) {
Christopher Tate76389c02016-08-03 14:57:47 -07002544 Log.v(TAG, "Found AlarmClockInfo " + a.alarmClock + " at " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01002545 formatNextAlarm(getContext(), a.alarmClock, userId) +
Adrian Roosc42a1e12014-07-07 23:35:53 +02002546 " for user " + userId);
2547 }
2548
2549 // Alarms and batches are sorted by time, no need to compare times here.
2550 if (nextForUser.get(userId) == null) {
2551 nextForUser.put(userId, a.alarmClock);
Christopher Tate76389c02016-08-03 14:57:47 -07002552 } else if (a.alarmClock.equals(current)
2553 && current.getTriggerTime() <= nextForUser.get(userId).getTriggerTime()) {
2554 // same/earlier time and it's the one we cited before, so stick with it
2555 nextForUser.put(userId, current);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002556 }
2557 }
2558 }
2559 }
2560
2561 // Update mNextAlarmForUser with new values.
2562 final int NN = nextForUser.size();
2563 for (int i = 0; i < NN; i++) {
Jose Lima235510e2014-08-13 12:50:01 -07002564 AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002565 int userId = nextForUser.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07002566 AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002567 if (!newAlarm.equals(currentAlarm)) {
2568 updateNextAlarmInfoForUserLocked(userId, newAlarm);
2569 }
2570 }
2571
2572 // Remove users without any alarm clocks scheduled.
2573 final int NNN = mNextAlarmClockForUser.size();
2574 for (int i = NNN - 1; i >= 0; i--) {
2575 int userId = mNextAlarmClockForUser.keyAt(i);
2576 if (nextForUser.get(userId) == null) {
2577 updateNextAlarmInfoForUserLocked(userId, null);
2578 }
2579 }
2580 }
2581
Jose Lima235510e2014-08-13 12:50:01 -07002582 private void updateNextAlarmInfoForUserLocked(int userId,
2583 AlarmManager.AlarmClockInfo alarmClock) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02002584 if (alarmClock != null) {
2585 if (DEBUG_ALARM_CLOCK) {
2586 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01002587 formatNextAlarm(getContext(), alarmClock, userId));
Adrian Roosc42a1e12014-07-07 23:35:53 +02002588 }
2589 mNextAlarmClockForUser.put(userId, alarmClock);
2590 } else {
2591 if (DEBUG_ALARM_CLOCK) {
2592 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None");
2593 }
2594 mNextAlarmClockForUser.remove(userId);
2595 }
2596
2597 mPendingSendNextAlarmClockChangedForUser.put(userId, true);
2598 mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
2599 mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
2600 }
2601
2602 /**
2603 * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
2604 * for which alarm clocks have changed since the last call to this.
2605 *
2606 * Do not call with a lock held. Only call from mHandler's thread.
2607 *
2608 * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
2609 */
2610 private void sendNextAlarmClockChanged() {
Jose Lima235510e2014-08-13 12:50:01 -07002611 SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02002612 pendingUsers.clear();
2613
2614 synchronized (mLock) {
2615 final int N = mPendingSendNextAlarmClockChangedForUser.size();
2616 for (int i = 0; i < N; i++) {
2617 int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i);
2618 pendingUsers.append(userId, mNextAlarmClockForUser.get(userId));
2619 }
2620 mPendingSendNextAlarmClockChangedForUser.clear();
2621 }
2622
2623 final int N = pendingUsers.size();
2624 for (int i = 0; i < N; i++) {
2625 int userId = pendingUsers.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07002626 AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002627 Settings.System.putStringForUser(getContext().getContentResolver(),
2628 Settings.System.NEXT_ALARM_FORMATTED,
Selim Cinek9c4a7072014-11-21 17:44:34 +01002629 formatNextAlarm(getContext(), alarmClock, userId),
Adrian Roosc42a1e12014-07-07 23:35:53 +02002630 userId);
2631
2632 getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT,
2633 new UserHandle(userId));
2634 }
2635 }
2636
2637 /**
2638 * Formats an alarm like platform/packages/apps/DeskClock used to.
2639 */
Selim Cinek9c4a7072014-11-21 17:44:34 +01002640 private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info,
2641 int userId) {
2642 String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma";
Adrian Roosc42a1e12014-07-07 23:35:53 +02002643 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
2644 return (info == null) ? "" :
2645 DateFormat.format(pattern, info.getTriggerTime()).toString();
2646 }
2647
Adam Lesinski182f73f2013-12-05 16:48:06 -08002648 void rescheduleKernelAlarmsLocked() {
2649 // Schedule the next upcoming wakeup alarm. If there is a deliverable batch
2650 // prior to that which contains no wakeups, we schedule that as well.
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002651 long nextNonWakeup = 0;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002652 if (mAlarmBatches.size() > 0) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002653 final Batch firstWakeup = findFirstWakeupBatchLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002654 final Batch firstBatch = mAlarmBatches.get(0);
Suprabh Shukla2fa95452018-02-12 12:53:23 -08002655 if (firstWakeup != null) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002656 mNextWakeup = firstWakeup.start;
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07002657 mLastWakeupSet = SystemClock.elapsedRealtime();
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002658 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002659 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002660 if (firstBatch != firstWakeup) {
2661 nextNonWakeup = firstBatch.start;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002662 }
2663 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002664 if (mPendingNonWakeupAlarms.size() > 0) {
2665 if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
2666 nextNonWakeup = mNextNonWakeupDeliveryTime;
2667 }
2668 }
Suprabh Shukla2fa95452018-02-12 12:53:23 -08002669 if (nextNonWakeup != 0) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002670 mNextNonWakeup = nextNonWakeup;
2671 setLocked(ELAPSED_REALTIME, nextNonWakeup);
2672 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002673 }
2674
Christopher Tate14a7bb02015-10-01 10:24:31 -07002675 private void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
Christopher Tate1d99c392017-12-07 16:54:04 -08002676 if (operation == null && directReceiver == null) {
2677 if (localLOGV) {
2678 Slog.w(TAG, "requested remove() of null operation",
2679 new RuntimeException("here"));
2680 }
2681 return;
2682 }
2683
Adam Lesinski182f73f2013-12-05 16:48:06 -08002684 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002685 final Predicate<Alarm> whichAlarms = (Alarm a) -> a.matches(operation, directReceiver);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002686 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2687 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002688 didRemove |= b.remove(whichAlarms);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002689 if (b.size() == 0) {
2690 mAlarmBatches.remove(i);
2691 }
2692 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002693 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002694 if (mPendingWhileIdleAlarms.get(i).matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002695 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2696 mPendingWhileIdleAlarms.remove(i);
2697 }
2698 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002699 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
2700 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
2701 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
2702 if (alarmsForUid.get(j).matches(operation, directReceiver)) {
2703 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2704 alarmsForUid.remove(j);
2705 }
2706 }
2707 if (alarmsForUid.size() == 0) {
2708 mPendingBackgroundAlarms.removeAt(i);
2709 }
2710 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002711 if (didRemove) {
2712 if (DEBUG_BATCH) {
2713 Slog.v(TAG, "remove(operation) changed bounds; rebatching");
2714 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002715 boolean restorePending = false;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002716 if (mPendingIdleUntil != null && mPendingIdleUntil.matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002717 mPendingIdleUntil = null;
2718 restorePending = true;
2719 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002720 if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002721 mNextWakeFromIdle = null;
2722 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002723 rebatchAllAlarmsLocked(true);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002724 if (restorePending) {
2725 restorePendingWhileIdleAlarmsLocked();
2726 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02002727 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002728 }
2729 }
2730
Christopher Tate1d99c392017-12-07 16:54:04 -08002731 void removeLocked(final int uid) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08002732 if (uid == Process.SYSTEM_UID) {
2733 Slog.wtf(TAG, "removeLocked: Shouldn't for UID=" + uid);
2734 return;
2735 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002736 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002737 final Predicate<Alarm> whichAlarms = (Alarm a) -> a.uid == uid;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002738 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2739 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002740 didRemove |= b.remove(whichAlarms);
2741 if (b.size() == 0) {
2742 mAlarmBatches.remove(i);
2743 }
2744 }
2745 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
2746 final Alarm a = mPendingWhileIdleAlarms.get(i);
2747 if (a.uid == uid) {
2748 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2749 mPendingWhileIdleAlarms.remove(i);
2750 }
2751 }
2752 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i --) {
2753 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
2754 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
2755 if (alarmsForUid.get(j).uid == uid) {
2756 alarmsForUid.remove(j);
2757 }
2758 }
2759 if (alarmsForUid.size() == 0) {
2760 mPendingBackgroundAlarms.removeAt(i);
2761 }
2762 }
2763 if (didRemove) {
2764 if (DEBUG_BATCH) {
2765 Slog.v(TAG, "remove(uid) changed bounds; rebatching");
2766 }
2767 rebatchAllAlarmsLocked(true);
2768 rescheduleKernelAlarmsLocked();
2769 updateNextAlarmClockLocked();
2770 }
2771 }
2772
2773 void removeLocked(final String packageName) {
2774 if (packageName == null) {
2775 if (localLOGV) {
2776 Slog.w(TAG, "requested remove() of null packageName",
2777 new RuntimeException("here"));
2778 }
2779 return;
2780 }
2781
2782 boolean didRemove = false;
2783 final Predicate<Alarm> whichAlarms = (Alarm a) -> a.matches(packageName);
Makoto Onuki5d93b832018-01-10 16:12:39 -08002784 final boolean oldHasTick = haveBatchesTimeTickAlarm(mAlarmBatches);
Christopher Tate1d99c392017-12-07 16:54:04 -08002785 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2786 Batch b = mAlarmBatches.get(i);
2787 didRemove |= b.remove(whichAlarms);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002788 if (b.size() == 0) {
2789 mAlarmBatches.remove(i);
2790 }
2791 }
Makoto Onuki5d93b832018-01-10 16:12:39 -08002792 final boolean newHasTick = haveBatchesTimeTickAlarm(mAlarmBatches);
2793 if (oldHasTick != newHasTick) {
2794 Slog.wtf(TAG, "removeLocked: hasTick changed from " + oldHasTick + " to " + newHasTick);
2795 }
2796
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002797 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002798 final Alarm a = mPendingWhileIdleAlarms.get(i);
2799 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002800 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2801 mPendingWhileIdleAlarms.remove(i);
2802 }
2803 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002804 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i --) {
2805 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
2806 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
2807 if (alarmsForUid.get(j).matches(packageName)) {
2808 alarmsForUid.remove(j);
2809 }
2810 }
2811 if (alarmsForUid.size() == 0) {
2812 mPendingBackgroundAlarms.removeAt(i);
2813 }
2814 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002815 if (didRemove) {
2816 if (DEBUG_BATCH) {
2817 Slog.v(TAG, "remove(package) changed bounds; rebatching");
2818 }
2819 rebatchAllAlarmsLocked(true);
2820 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02002821 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002822 }
2823 }
2824
Christopher Tate1d99c392017-12-07 16:54:04 -08002825 void removeForStoppedLocked(final int uid) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08002826 if (uid == Process.SYSTEM_UID) {
2827 Slog.wtf(TAG, "removeForStoppedLocked: Shouldn't for UID=" + uid);
2828 return;
2829 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002830 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002831 final Predicate<Alarm> whichAlarms = (Alarm a) -> {
2832 try {
2833 if (a.uid == uid && ActivityManager.getService().isAppStartModeDisabled(
2834 uid, a.packageName)) {
2835 return true;
2836 }
2837 } catch (RemoteException e) { /* fall through */}
2838 return false;
2839 };
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002840 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2841 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002842 didRemove |= b.remove(whichAlarms);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002843 if (b.size() == 0) {
2844 mAlarmBatches.remove(i);
2845 }
2846 }
2847 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
2848 final Alarm a = mPendingWhileIdleAlarms.get(i);
Dianne Hackborne07641d2016-11-09 15:07:23 -08002849 if (a.uid == uid) {
2850 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2851 mPendingWhileIdleAlarms.remove(i);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002852 }
2853 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002854 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
2855 if (mPendingBackgroundAlarms.keyAt(i) == uid) {
2856 mPendingBackgroundAlarms.removeAt(i);
2857 }
2858 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002859 if (didRemove) {
2860 if (DEBUG_BATCH) {
2861 Slog.v(TAG, "remove(package) changed bounds; rebatching");
2862 }
2863 rebatchAllAlarmsLocked(true);
2864 rescheduleKernelAlarmsLocked();
2865 updateNextAlarmClockLocked();
2866 }
2867 }
2868
Adam Lesinski182f73f2013-12-05 16:48:06 -08002869 void removeUserLocked(int userHandle) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08002870 if (userHandle == UserHandle.USER_SYSTEM) {
2871 Slog.wtf(TAG, "removeForStoppedLocked: Shouldn't for user=" + userHandle);
2872 return;
2873 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002874 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002875 final Predicate<Alarm> whichAlarms =
2876 (Alarm a) -> UserHandle.getUserId(a.creatorUid) == userHandle;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002877 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2878 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002879 didRemove |= b.remove(whichAlarms);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002880 if (b.size() == 0) {
2881 mAlarmBatches.remove(i);
2882 }
2883 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002884 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002885 if (UserHandle.getUserId(mPendingWhileIdleAlarms.get(i).creatorUid)
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002886 == userHandle) {
2887 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2888 mPendingWhileIdleAlarms.remove(i);
2889 }
2890 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002891 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
2892 if (UserHandle.getUserId(mPendingBackgroundAlarms.keyAt(i)) == userHandle) {
2893 mPendingBackgroundAlarms.removeAt(i);
2894 }
2895 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002896 for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
2897 if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
2898 mLastAllowWhileIdleDispatch.removeAt(i);
2899 }
2900 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002901
2902 if (didRemove) {
2903 if (DEBUG_BATCH) {
2904 Slog.v(TAG, "remove(user) changed bounds; rebatching");
2905 }
2906 rebatchAllAlarmsLocked(true);
2907 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02002908 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002909 }
2910 }
2911
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002912 void interactiveStateChangedLocked(boolean interactive) {
2913 if (mInteractive != interactive) {
2914 mInteractive = interactive;
2915 final long nowELAPSED = SystemClock.elapsedRealtime();
2916 if (interactive) {
2917 if (mPendingNonWakeupAlarms.size() > 0) {
2918 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
2919 mTotalDelayTime += thisDelayTime;
2920 if (mMaxDelayTime < thisDelayTime) {
2921 mMaxDelayTime = thisDelayTime;
2922 }
2923 deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
2924 mPendingNonWakeupAlarms.clear();
2925 }
2926 if (mNonInteractiveStartTime > 0) {
2927 long dur = nowELAPSED - mNonInteractiveStartTime;
2928 if (dur > mNonInteractiveTime) {
2929 mNonInteractiveTime = dur;
2930 }
2931 }
2932 } else {
2933 mNonInteractiveStartTime = nowELAPSED;
2934 }
2935 }
2936 }
2937
Adam Lesinski182f73f2013-12-05 16:48:06 -08002938 boolean lookForPackageLocked(String packageName) {
2939 for (int i = 0; i < mAlarmBatches.size(); i++) {
2940 Batch b = mAlarmBatches.get(i);
2941 if (b.hasPackage(packageName)) {
2942 return true;
2943 }
2944 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002945 for (int i = 0; i < mPendingWhileIdleAlarms.size(); i++) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002946 final Alarm a = mPendingWhileIdleAlarms.get(i);
2947 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002948 return true;
2949 }
2950 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002951 return false;
2952 }
2953
2954 private void setLocked(int type, long when) {
Greg Hackmannf1bdbdd2013-12-17 11:56:22 -08002955 if (mNativeData != 0) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08002956 // The kernel never triggers alarms with negative wakeup times
2957 // so we ensure they are positive.
2958 long alarmSeconds, alarmNanoseconds;
2959 if (when < 0) {
2960 alarmSeconds = 0;
2961 alarmNanoseconds = 0;
2962 } else {
2963 alarmSeconds = when / 1000;
2964 alarmNanoseconds = (when % 1000) * 1000 * 1000;
2965 }
Kweku Adams61e03292017-10-19 14:27:12 -07002966
Christopher Tate8b98ade2018-02-09 11:13:19 -08002967 final int result = set(mNativeData, type, alarmSeconds, alarmNanoseconds);
2968 if (result != 0) {
2969 final long nowElapsed = SystemClock.elapsedRealtime();
2970 Slog.wtf(TAG, "Unable to set kernel alarm, now=" + nowElapsed
2971 + " type=" + type + " when=" + when
2972 + " @ (" + alarmSeconds + "," + alarmNanoseconds
2973 + "), ret = " + result + " = " + Os.strerror(result));
2974 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002975 } else {
2976 Message msg = Message.obtain();
2977 msg.what = ALARM_EVENT;
Kweku Adams61e03292017-10-19 14:27:12 -07002978
Adam Lesinski182f73f2013-12-05 16:48:06 -08002979 mHandler.removeMessages(ALARM_EVENT);
2980 mHandler.sendMessageAtTime(msg, when);
2981 }
2982 }
2983
Dianne Hackborn043fcd92010-10-06 14:27:34 -07002984 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Kweku Adams61e03292017-10-19 14:27:12 -07002985 String prefix, String label, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 for (int i=list.size()-1; i>=0; i--) {
2987 Alarm a = list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002988 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
2989 pw.print(": "); pw.println(a);
Kweku Adams61e03292017-10-19 14:27:12 -07002990 a.dump(pw, prefix + " ", nowELAPSED, nowRTC, sdf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 }
2992 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002993
2994 private static final String labelForType(int type) {
2995 switch (type) {
2996 case RTC: return "RTC";
2997 case RTC_WAKEUP : return "RTC_WAKEUP";
2998 case ELAPSED_REALTIME : return "ELAPSED";
2999 case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP";
Christopher Tatee0a22b32013-07-11 14:43:13 -07003000 }
3001 return "--unknown--";
3002 }
3003
3004 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003005 String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07003006 for (int i=list.size()-1; i>=0; i--) {
3007 Alarm a = list.get(i);
3008 final String label = labelForType(a.type);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003009 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
3010 pw.print(": "); pw.println(a);
Kweku Adams61e03292017-10-19 14:27:12 -07003011 a.dump(pw, prefix + " ", nowELAPSED, nowRTC, sdf);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003012 }
3013 }
3014
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003015 private boolean isBackgroundRestricted(Alarm alarm) {
Suprabh Shuklac25447d2018-01-19 16:43:35 -08003016 final boolean allowWhileIdle = (alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003017 if (alarm.alarmClock != null) {
3018 // Don't block alarm clocks
3019 return false;
3020 }
3021 if (alarm.operation != null
3022 && (alarm.operation.isActivity() || alarm.operation.isForegroundService())) {
3023 // Don't block starting foreground components
3024 return false;
3025 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08003026 final String sourcePackage = alarm.sourcePackage;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003027 final int sourceUid = alarm.creatorUid;
Makoto Onukie4918212018-02-06 11:30:15 -08003028 return (mAppStateTracker != null) &&
3029 mAppStateTracker.areAlarmsRestricted(sourceUid, sourcePackage, allowWhileIdle);
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003030 }
3031
Greg Hackmanna1d6f922013-12-09 16:56:53 -08003032 private native long init();
3033 private native void close(long nativeData);
Christopher Tate8b98ade2018-02-09 11:13:19 -08003034 private native int set(long nativeData, int type, long seconds, long nanoseconds);
Greg Hackmanna1d6f922013-12-09 16:56:53 -08003035 private native int waitForAlarm(long nativeData);
Greg Hackmann38bf5142014-02-19 16:39:36 -08003036 private native int setKernelTime(long nativeData, long millis);
Greg Hackmanna1d6f922013-12-09 16:56:53 -08003037 private native int setKernelTimezone(long nativeData, int minuteswest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003038
Makoto Onukiadb50d82018-01-29 16:20:30 -08003039 private long getWhileIdleMinIntervalLocked(int uid) {
3040 final boolean dozing = mPendingIdleUntil != null;
Makoto Onukie4918212018-02-06 11:30:15 -08003041 final boolean ebs = (mAppStateTracker != null)
3042 && mAppStateTracker.isForceAllAppsStandbyEnabled();
Makoto Onukiadb50d82018-01-29 16:20:30 -08003043 if (!dozing && !ebs) {
3044 return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
3045 }
3046 if (dozing) {
3047 return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
3048 }
3049 if (mUseAllowWhileIdleShortTime.get(uid)) {
3050 // if the last allow-while-idle went off while uid was fg, or the uid
3051 // recently came into fg, don't block the alarm for long.
3052 return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
3053 }
3054 return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
3055 }
3056
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003057 boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003058 final long nowRTC) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003059 boolean hasWakeup = false;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003060 // batches are temporally sorted, so we need only pull from the
3061 // start of the list until we either empty it or hit a batch
3062 // that is not yet deliverable
Christopher Tate6578ad12013-09-24 17:12:46 -07003063 while (mAlarmBatches.size() > 0) {
3064 Batch batch = mAlarmBatches.get(0);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003065 if (batch.start > nowELAPSED) {
3066 // Everything else is scheduled for the future
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003067 break;
3068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069
Christopher Tatee0a22b32013-07-11 14:43:13 -07003070 // We will (re)schedule some alarms now; don't let that interfere
3071 // with delivery of this current batch
3072 mAlarmBatches.remove(0);
Dianne Hackborn390517b2013-05-30 15:03:32 -07003073
Christopher Tatee0a22b32013-07-11 14:43:13 -07003074 final int N = batch.size();
3075 for (int i = 0; i < N; i++) {
3076 Alarm alarm = batch.get(i);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003077
3078 if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
3079 // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
Christopher Tateddd1da142018-04-13 13:41:51 -07003080 // schedule such alarms. The first such alarm from an app is always delivered.
3081 final long lastTime = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, -1);
Makoto Onukiadb50d82018-01-29 16:20:30 -08003082 final long minTime = lastTime + getWhileIdleMinIntervalLocked(alarm.creatorUid);
Christopher Tateddd1da142018-04-13 13:41:51 -07003083 if (lastTime >= 0 && nowELAPSED < minTime) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003084 // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
3085 // alarm went off for this app. Reschedule the alarm to be in the
3086 // correct time period.
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003087 alarm.expectedWhenElapsed = alarm.whenElapsed = minTime;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003088 if (alarm.maxWhenElapsed < minTime) {
3089 alarm.maxWhenElapsed = minTime;
3090 }
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003091 alarm.expectedMaxWhenElapsed = alarm.maxWhenElapsed;
Dianne Hackbornae78bf82015-10-26 13:33:20 -07003092 if (RECORD_DEVICE_IDLE_ALARMS) {
3093 IdleDispatchEntry ent = new IdleDispatchEntry();
3094 ent.uid = alarm.uid;
3095 ent.pkg = alarm.operation.getCreatorPackage();
3096 ent.tag = alarm.operation.getTag("");
3097 ent.op = "RESCHEDULE";
3098 ent.elapsedRealtime = nowELAPSED;
3099 ent.argRealtime = lastTime;
3100 mAllowWhileIdleDispatches.add(ent);
3101 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003102 setImplLocked(alarm, true, false);
3103 continue;
3104 }
3105 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003106 if (isBackgroundRestricted(alarm)) {
3107 // Alarms with FLAG_WAKE_FROM_IDLE or mPendingIdleUntil alarm are not deferred
3108 if (DEBUG_BG_LIMIT) {
3109 Slog.d(TAG, "Deferring alarm " + alarm + " due to user forced app standby");
3110 }
3111 ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(alarm.creatorUid);
3112 if (alarmsForUid == null) {
3113 alarmsForUid = new ArrayList<>();
3114 mPendingBackgroundAlarms.put(alarm.creatorUid, alarmsForUid);
3115 }
3116 alarmsForUid.add(alarm);
3117 continue;
3118 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003119
Christopher Tatee0a22b32013-07-11 14:43:13 -07003120 alarm.count = 1;
3121 triggerList.add(alarm);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003122 if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
3123 EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003124 alarm.statsTag);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003125 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003126 if (mPendingIdleUntil == alarm) {
3127 mPendingIdleUntil = null;
3128 rebatchAllAlarmsLocked(false);
3129 restorePendingWhileIdleAlarmsLocked();
3130 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003131 if (mNextWakeFromIdle == alarm) {
3132 mNextWakeFromIdle = null;
3133 rebatchAllAlarmsLocked(false);
3134 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003135
3136 // Recurring alarms may have passed several alarm intervals while the
3137 // phone was asleep or off, so pass a trigger count when sending them.
3138 if (alarm.repeatInterval > 0) {
3139 // this adjustment will be zero if we're late by
3140 // less than one full repeat interval
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003141 alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003142
3143 // Also schedule its next recurrence
3144 final long delta = alarm.count * alarm.repeatInterval;
3145 final long nextElapsed = alarm.whenElapsed + delta;
Christopher Tate3e04b472013-10-21 17:51:31 -07003146 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
Christopher Tatee0a22b32013-07-11 14:43:13 -07003147 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
Christopher Tate14a7bb02015-10-01 10:24:31 -07003148 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
3149 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
Christopher Tate864d42e2014-12-02 11:48:53 -08003150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003151
Christopher Tate864d42e2014-12-02 11:48:53 -08003152 if (alarm.wakeup) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003153 hasWakeup = true;
3154 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02003155
3156 // We removed an alarm clock. Let the caller recompute the next alarm clock.
3157 if (alarm.alarmClock != null) {
3158 mNextAlarmClockMayChange = true;
3159 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07003160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003161 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003162
Christopher Tate1590f1e2014-10-02 17:27:57 -07003163 // This is a new alarm delivery set; bump the sequence number to indicate that
3164 // all apps' alarm delivery classes should be recalculated.
3165 mCurrentSeq++;
3166 calculateDeliveryPriorities(triggerList);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003167 Collections.sort(triggerList, mAlarmDispatchComparator);
3168
3169 if (localLOGV) {
3170 for (int i=0; i<triggerList.size(); i++) {
3171 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
3172 }
3173 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003174
3175 return hasWakeup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003176 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 /**
3179 * This Comparator sorts Alarms into increasing time order.
3180 */
3181 public static class IncreasingTimeOrder implements Comparator<Alarm> {
3182 public int compare(Alarm a1, Alarm a2) {
jinho.park1acd32a2015-05-27 14:44:18 +09003183 long when1 = a1.whenElapsed;
3184 long when2 = a2.whenElapsed;
Charles Tsaicdaaeee2015-05-20 18:16:48 +08003185 if (when1 > when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003186 return 1;
3187 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +08003188 if (when1 < when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003189 return -1;
3190 }
3191 return 0;
3192 }
3193 }
Kweku Adams61e03292017-10-19 14:27:12 -07003194
Makoto Onuki2206af32017-11-21 16:25:35 -08003195 @VisibleForTesting
3196 static class Alarm {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003197 public final int type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003198 public final long origWhen;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003199 public final boolean wakeup;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003200 public final PendingIntent operation;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003201 public final IAlarmListener listener;
3202 public final String listenerTag;
3203 public final String statsTag;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003204 public final WorkSource workSource;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003205 public final int flags;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003206 public final AlarmManager.AlarmClockInfo alarmClock;
3207 public final int uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003208 public final int creatorUid;
3209 public final String packageName;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003210 public final String sourcePackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003211 public int count;
3212 public long when;
Christopher Tate3e04b472013-10-21 17:51:31 -07003213 public long windowLength;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003214 public long whenElapsed; // 'when' in the elapsed time base
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003215 public long maxWhenElapsed; // also in the elapsed time base
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003216 // Expected alarm expiry time before app standby deferring is applied.
3217 public long expectedWhenElapsed;
3218 public long expectedMaxWhenElapsed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003219 public long repeatInterval;
Christopher Tate1590f1e2014-10-02 17:27:57 -07003220 public PriorityClass priorityClass;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003221
Christopher Tate3e04b472013-10-21 17:51:31 -07003222 public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003223 long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag,
3224 WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info,
3225 int _uid, String _pkgName) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07003226 type = _type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003227 origWhen = _when;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003228 wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
3229 || _type == AlarmManager.RTC_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003230 when = _when;
3231 whenElapsed = _whenElapsed;
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003232 expectedWhenElapsed = _whenElapsed;
Christopher Tate3e04b472013-10-21 17:51:31 -07003233 windowLength = _windowLength;
Christopher Tate22e919d2018-02-16 16:16:50 -08003234 maxWhenElapsed = expectedMaxWhenElapsed = clampPositive(_maxWhen);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003235 repeatInterval = _interval;
3236 operation = _op;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003237 listener = _rec;
3238 listenerTag = _listenerTag;
3239 statsTag = makeTag(_op, _listenerTag, _type);
David Christieebe51fc2013-07-26 13:23:29 -07003240 workSource = _ws;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003241 flags = _flags;
Adrian Roosc42a1e12014-07-07 23:35:53 +02003242 alarmClock = _info;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003243 uid = _uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003244 packageName = _pkgName;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003245 sourcePackage = (operation != null) ? operation.getCreatorPackage() : packageName;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003246 creatorUid = (operation != null) ? operation.getCreatorUid() : uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003247 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003248
Christopher Tate14a7bb02015-10-01 10:24:31 -07003249 public static String makeTag(PendingIntent pi, String tag, int type) {
3250 final String alarmString = type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
3251 ? "*walarm*:" : "*alarm*:";
3252 return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag);
3253 }
3254
3255 public WakeupEvent makeWakeupEvent(long nowRTC) {
3256 return new WakeupEvent(nowRTC, creatorUid,
3257 (operation != null)
3258 ? operation.getIntent().getAction()
3259 : ("<listener>:" + listenerTag));
3260 }
3261
3262 // Returns true if either matches
3263 public boolean matches(PendingIntent pi, IAlarmListener rec) {
3264 return (operation != null)
3265 ? operation.equals(pi)
Lorenzo Colitti9b43ce02015-11-22 22:00:08 +09003266 : rec != null && listener.asBinder().equals(rec.asBinder());
Christopher Tate14a7bb02015-10-01 10:24:31 -07003267 }
3268
3269 public boolean matches(String packageName) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08003270 return packageName.equals(sourcePackage);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003271 }
3272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003273 @Override
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003274 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003275 StringBuilder sb = new StringBuilder(128);
3276 sb.append("Alarm{");
3277 sb.append(Integer.toHexString(System.identityHashCode(this)));
3278 sb.append(" type ");
3279 sb.append(type);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003280 sb.append(" when ");
3281 sb.append(when);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003282 sb.append(" ");
Suprabh Shukla75edab12018-01-29 14:09:06 -08003283 sb.append(sourcePackage);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003284 sb.append('}');
3285 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003286 }
3287
Kweku Adams61e03292017-10-19 14:27:12 -07003288 public void dump(PrintWriter pw, String prefix, long nowELAPSED, long nowRTC,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003289 SimpleDateFormat sdf) {
3290 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003291 pw.print(prefix); pw.print("tag="); pw.println(statsTag);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003292 pw.print(prefix); pw.print("type="); pw.print(type);
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003293 pw.print(" expectedWhenElapsed="); TimeUtils.formatDuration(
3294 expectedWhenElapsed, nowELAPSED, pw);
3295 pw.print(" expectedMaxWhenElapsed="); TimeUtils.formatDuration(
3296 expectedMaxWhenElapsed, nowELAPSED, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003297 pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
3298 nowELAPSED, pw);
Suprabh Shukla2fa95452018-02-12 12:53:23 -08003299 pw.print(" maxWhenElapsed="); TimeUtils.formatDuration(maxWhenElapsed,
3300 nowELAPSED, pw);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003301 pw.print(" when=");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003302 if (isRtc) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003303 pw.print(sdf.format(new Date(when)));
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003304 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003305 TimeUtils.formatDuration(when, nowELAPSED, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003306 }
3307 pw.println();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003308 pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003309 pw.print(" repeatInterval="); pw.print(repeatInterval);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003310 pw.print(" count="); pw.print(count);
3311 pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003312 if (alarmClock != null) {
3313 pw.print(prefix); pw.println("Alarm clock:");
3314 pw.print(prefix); pw.print(" triggerTime=");
3315 pw.println(sdf.format(new Date(alarmClock.getTriggerTime())));
3316 pw.print(prefix); pw.print(" showIntent="); pw.println(alarmClock.getShowIntent());
3317 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003318 pw.print(prefix); pw.print("operation="); pw.println(operation);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003319 if (listener != null) {
3320 pw.print(prefix); pw.print("listener="); pw.println(listener.asBinder());
3321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003322 }
Kweku Adams61e03292017-10-19 14:27:12 -07003323
3324 public void writeToProto(ProtoOutputStream proto, long fieldId, long nowElapsed,
3325 long nowRTC) {
3326 final long token = proto.start(fieldId);
3327
3328 proto.write(AlarmProto.TAG, statsTag);
3329 proto.write(AlarmProto.TYPE, type);
Kweku Adams923ec432017-12-11 18:05:38 -08003330 proto.write(AlarmProto.TIME_UNTIL_WHEN_ELAPSED_MS, whenElapsed - nowElapsed);
Kweku Adams61e03292017-10-19 14:27:12 -07003331 proto.write(AlarmProto.WINDOW_LENGTH_MS, windowLength);
3332 proto.write(AlarmProto.REPEAT_INTERVAL_MS, repeatInterval);
3333 proto.write(AlarmProto.COUNT, count);
3334 proto.write(AlarmProto.FLAGS, flags);
3335 if (alarmClock != null) {
3336 alarmClock.writeToProto(proto, AlarmProto.ALARM_CLOCK);
3337 }
3338 if (operation != null) {
3339 operation.writeToProto(proto, AlarmProto.OPERATION);
3340 }
3341 if (listener != null) {
3342 proto.write(AlarmProto.LISTENER, listener.asBinder().toString());
3343 }
3344
3345 proto.end(token);
3346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 }
Christopher Tate18a75f12013-07-01 18:18:59 -07003348
Christopher Tatee0a22b32013-07-11 14:43:13 -07003349 void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) {
3350 final int numBatches = batches.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07003351 for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) {
3352 Batch b = batches.get(nextBatch);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003353 if (b.start > nowELAPSED) {
Christopher Tate18a75f12013-07-01 18:18:59 -07003354 break;
3355 }
3356
Christopher Tatee0a22b32013-07-11 14:43:13 -07003357 final int numAlarms = b.alarms.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07003358 for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) {
3359 Alarm a = b.alarms.get(nextAlarm);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003360 mRecentWakeups.add(a.makeWakeupEvent(nowRTC));
Christopher Tatee0a22b32013-07-11 14:43:13 -07003361 }
Christopher Tate18a75f12013-07-01 18:18:59 -07003362 }
3363 }
3364
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003365 long currentNonWakeupFuzzLocked(long nowELAPSED) {
3366 long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
3367 if (timeSinceOn < 5*60*1000) {
3368 // If the screen has been off for 5 minutes, only delay by at most two minutes.
3369 return 2*60*1000;
3370 } else if (timeSinceOn < 30*60*1000) {
3371 // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
3372 return 15*60*1000;
3373 } else {
3374 // Otherwise, we will delay by at most an hour.
3375 return 60*60*1000;
3376 }
3377 }
3378
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003379 static int fuzzForDuration(long duration) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003380 if (duration < 15*60*1000) {
3381 // If the duration until the time is less than 15 minutes, the maximum fuzz
3382 // is the duration.
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003383 return (int)duration;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003384 } else if (duration < 90*60*1000) {
3385 // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes,
3386 return 15*60*1000;
3387 } else {
3388 // Otherwise, we will fuzz by at most half an hour.
3389 return 30*60*1000;
3390 }
3391 }
3392
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003393 boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
3394 if (mInteractive) {
3395 return false;
3396 }
3397 if (mLastAlarmDeliveryTime <= 0) {
3398 return false;
3399 }
minho.choo649acab2014-12-12 16:13:55 +09003400 if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003401 // This is just a little paranoia, if somehow we have pending non-wakeup alarms
3402 // and the next delivery time is in the past, then just deliver them all. This
3403 // avoids bugs where we get stuck in a loop trying to poll for alarms.
3404 return false;
3405 }
3406 long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
3407 return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
3408 }
3409
3410 void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
3411 mLastAlarmDeliveryTime = nowELAPSED;
3412 for (int i=0; i<triggerList.size(); i++) {
3413 Alarm alarm = triggerList.get(i);
Dianne Hackborna750a632015-06-16 17:18:23 -07003414 final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
Tim Murray175c0f92017-11-28 15:01:04 -08003415 if (alarm.wakeup) {
3416 Trace.traceBegin(Trace.TRACE_TAG_POWER, "Dispatch wakeup alarm to " + alarm.packageName);
3417 } else {
3418 Trace.traceBegin(Trace.TRACE_TAG_POWER, "Dispatch non-wakeup alarm to " + alarm.packageName);
3419 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003420 try {
Christopher Tate2ff5a732014-09-18 13:47:57 -07003421 if (localLOGV) {
3422 Slog.v(TAG, "sending alarm " + alarm);
3423 }
Dianne Hackborn1e383822015-04-10 14:02:33 -07003424 if (RECORD_ALARMS_IN_HISTORY) {
Narayan Kamath695cf722017-12-21 18:32:47 +00003425 ActivityManager.noteAlarmStart(alarm.operation, alarm.workSource, alarm.uid,
3426 alarm.statsTag);
Dianne Hackborn1e383822015-04-10 14:02:33 -07003427 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003428 mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003429 } catch (RuntimeException e) {
3430 Slog.w(TAG, "Failure sending alarm.", e);
3431 }
Tim Murray175c0f92017-11-28 15:01:04 -08003432 Trace.traceEnd(Trace.TRACE_TAG_POWER);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003433 }
3434 }
3435
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003436 private boolean isExemptFromAppStandby(Alarm a) {
3437 return a.alarmClock != null || UserHandle.isCore(a.creatorUid)
3438 || (a.flags & FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED) != 0;
3439 }
3440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 private class AlarmThread extends Thread
3442 {
3443 public AlarmThread()
3444 {
3445 super("AlarmManager");
3446 }
Kweku Adams61e03292017-10-19 14:27:12 -07003447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 public void run()
3449 {
Dianne Hackborn390517b2013-05-30 15:03:32 -07003450 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
3451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 while (true)
3453 {
Greg Hackmanna1d6f922013-12-09 16:56:53 -08003454 int result = waitForAlarm(mNativeData);
Dianne Hackborn390517b2013-05-30 15:03:32 -07003455
Dianne Hackbornc3527222015-05-13 14:03:20 -07003456 final long nowRTC = System.currentTimeMillis();
3457 final long nowELAPSED = SystemClock.elapsedRealtime();
Christopher Tate8b98ade2018-02-09 11:13:19 -08003458 synchronized (mLock) {
3459 mLastWakeup = nowELAPSED;
3460 }
3461
3462 triggerList.clear();
Dianne Hackbornc3527222015-05-13 14:03:20 -07003463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 if ((result & TIME_CHANGED_MASK) != 0) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07003465 // The kernel can give us spurious time change notifications due to
3466 // small adjustments it makes internally; we want to filter those out.
3467 final long lastTimeChangeClockTime;
3468 final long expectedClockTime;
Dianne Hackborn998e6082014-09-11 19:13:23 -07003469 synchronized (mLock) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07003470 lastTimeChangeClockTime = mLastTimeChangeClockTime;
3471 expectedClockTime = lastTimeChangeClockTime
3472 + (nowELAPSED - mLastTimeChangeRealtime);
Dianne Hackborn998e6082014-09-11 19:13:23 -07003473 }
Christopher Tate2b6e459e2017-02-17 14:33:52 -08003474 if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-1000)
3475 || nowRTC > (expectedClockTime+1000)) {
3476 // The change is by at least +/- 1000 ms (or this is the first change),
Dianne Hackbornc3527222015-05-13 14:03:20 -07003477 // let's do it!
3478 if (DEBUG_BATCH) {
3479 Slog.v(TAG, "Time changed notification from kernel; rebatching");
3480 }
3481 removeImpl(mTimeTickSender);
Christopher Tatecf024712016-08-05 13:21:45 -07003482 removeImpl(mDateChangeSender);
Dianne Hackbornc3527222015-05-13 14:03:20 -07003483 rebatchAllAlarms();
3484 mClockReceiver.scheduleTimeTickEvent();
Christopher Tatecf024712016-08-05 13:21:45 -07003485 mClockReceiver.scheduleDateChangedEvent();
Dianne Hackbornc3527222015-05-13 14:03:20 -07003486 synchronized (mLock) {
3487 mNumTimeChanged++;
3488 mLastTimeChangeClockTime = nowRTC;
3489 mLastTimeChangeRealtime = nowELAPSED;
3490 }
3491 Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
3492 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
Christopher Tate2b6e459e2017-02-17 14:33:52 -08003493 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
Chad Brubaker291df4f2017-03-14 10:23:02 -07003494 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
3495 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Dianne Hackbornc3527222015-05-13 14:03:20 -07003496 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
3497
3498 // The world has changed on us, so we need to re-evaluate alarms
3499 // regardless of whether the kernel has told us one went off.
3500 result |= IS_WAKEUP_MASK;
3501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003503
Dianne Hackbornc3527222015-05-13 14:03:20 -07003504 if (result != TIME_CHANGED_MASK) {
3505 // If this was anything besides just a time change, then figure what if
3506 // anything to do about alarms.
3507 synchronized (mLock) {
3508 if (localLOGV) Slog.v(
3509 TAG, "Checking for alarms... rtc=" + nowRTC
3510 + ", elapsed=" + nowELAPSED);
Christopher Tate18a75f12013-07-01 18:18:59 -07003511
Dianne Hackbornc3527222015-05-13 14:03:20 -07003512 if (WAKEUP_STATS) {
3513 if ((result & IS_WAKEUP_MASK) != 0) {
3514 long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
3515 int n = 0;
3516 for (WakeupEvent event : mRecentWakeups) {
3517 if (event.when > newEarliest) break;
3518 n++; // number of now-stale entries at the list head
3519 }
3520 for (int i = 0; i < n; i++) {
3521 mRecentWakeups.remove();
3522 }
Christopher Tate18a75f12013-07-01 18:18:59 -07003523
Dianne Hackbornc3527222015-05-13 14:03:20 -07003524 recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003525 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003526 }
Dianne Hackbornc3527222015-05-13 14:03:20 -07003527
Christopher Tate8b98ade2018-02-09 11:13:19 -08003528 mLastTrigger = nowELAPSED;
Dianne Hackbornc3527222015-05-13 14:03:20 -07003529 boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
3530 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
3531 // if there are no wakeup alarms and the screen is off, we can
3532 // delay what we have so far until the future.
3533 if (mPendingNonWakeupAlarms.size() == 0) {
3534 mStartCurrentDelayTime = nowELAPSED;
3535 mNextNonWakeupDeliveryTime = nowELAPSED
3536 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
3537 }
3538 mPendingNonWakeupAlarms.addAll(triggerList);
3539 mNumDelayedAlarms += triggerList.size();
3540 rescheduleKernelAlarmsLocked();
3541 updateNextAlarmClockLocked();
3542 } else {
3543 // now deliver the alarm intents; if there are pending non-wakeup
3544 // alarms, we need to merge them in to the list. note we don't
3545 // just deliver them first because we generally want non-wakeup
3546 // alarms delivered after wakeup alarms.
Dianne Hackbornc3527222015-05-13 14:03:20 -07003547 if (mPendingNonWakeupAlarms.size() > 0) {
3548 calculateDeliveryPriorities(mPendingNonWakeupAlarms);
3549 triggerList.addAll(mPendingNonWakeupAlarms);
3550 Collections.sort(triggerList, mAlarmDispatchComparator);
3551 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
3552 mTotalDelayTime += thisDelayTime;
3553 if (mMaxDelayTime < thisDelayTime) {
3554 mMaxDelayTime = thisDelayTime;
3555 }
3556 mPendingNonWakeupAlarms.clear();
3557 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003558 final ArraySet<Pair<String, Integer>> triggerPackages =
3559 new ArraySet<>();
3560 for (int i = 0; i < triggerList.size(); i++) {
3561 final Alarm a = triggerList.get(i);
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003562 if (!isExemptFromAppStandby(a)) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003563 triggerPackages.add(Pair.create(
3564 a.sourcePackage, UserHandle.getUserId(a.creatorUid)));
Suprabh Shukla75edab12018-01-29 14:09:06 -08003565 }
3566 }
Dianne Hackbornc3527222015-05-13 14:03:20 -07003567 deliverAlarmsLocked(triggerList, nowELAPSED);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003568 reorderAlarmsBasedOnStandbyBuckets(triggerPackages);
3569 rescheduleKernelAlarmsLocked();
3570 updateNextAlarmClockLocked();
Dianne Hackbornc3527222015-05-13 14:03:20 -07003571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 }
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07003573
3574 } else {
3575 // Just in case -- even though no wakeup flag was set, make sure
3576 // we have updated the kernel to the next alarm time.
Christopher Tate7b5b7cb2016-07-07 14:41:36 -07003577 synchronized (mLock) {
3578 rescheduleKernelAlarmsLocked();
3579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 }
3581 }
3582 }
3583 }
Christopher Tatec4a07d12012-04-06 14:19:13 -07003584
David Christieebe51fc2013-07-26 13:23:29 -07003585 /**
3586 * Attribute blame for a WakeLock.
3587 * @param pi PendingIntent to attribute blame to if ws is null.
3588 * @param ws WorkSource to attribute blame.
Christopher Tate14a7bb02015-10-01 10:24:31 -07003589 * @param knownUid attribution uid; < 0 if we need to derive it from the PendingIntent sender
David Christieebe51fc2013-07-26 13:23:29 -07003590 */
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003591 void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003592 int knownUid, boolean first) {
Christopher Tatec4a07d12012-04-06 14:19:13 -07003593 try {
Dianne Hackborna1bd7922014-03-21 11:07:11 -07003594 final boolean unimportant = pi == mTimeTickSender;
3595 mWakeLock.setUnimportantForLogging(unimportant);
Dianne Hackborn4590e522014-03-24 13:36:46 -07003596 if (first || mLastWakeLockUnimportantForLogging) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003597 mWakeLock.setHistoryTag(tag);
Dianne Hackborn4590e522014-03-24 13:36:46 -07003598 } else {
3599 mWakeLock.setHistoryTag(null);
3600 }
3601 mLastWakeLockUnimportantForLogging = unimportant;
David Christieebe51fc2013-07-26 13:23:29 -07003602 if (ws != null) {
3603 mWakeLock.setWorkSource(ws);
3604 return;
3605 }
3606
Christopher Tate14a7bb02015-10-01 10:24:31 -07003607 final int uid = (knownUid >= 0)
3608 ? knownUid
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003609 : ActivityManager.getService().getUidForIntentSender(pi.getTarget());
Christopher Tatec4a07d12012-04-06 14:19:13 -07003610 if (uid >= 0) {
3611 mWakeLock.setWorkSource(new WorkSource(uid));
3612 return;
3613 }
3614 } catch (Exception e) {
3615 }
3616
3617 // Something went wrong; fall back to attributing the lock to the OS
3618 mWakeLock.setWorkSource(null);
3619 }
3620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 private class AlarmHandler extends Handler {
3622 public static final int ALARM_EVENT = 1;
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003623 public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2;
3624 public static final int LISTENER_TIMEOUT = 3;
3625 public static final int REPORT_ALARMS_ACTIVE = 4;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003626 public static final int APP_STANDBY_BUCKET_CHANGED = 5;
3627 public static final int APP_STANDBY_PAROLE_CHANGED = 6;
Makoto Onuki4d298b52018-02-05 10:54:58 -08003628 public static final int REMOVE_FOR_STOPPED = 7;
Kweku Adams61e03292017-10-19 14:27:12 -07003629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 public AlarmHandler() {
3631 }
Kweku Adams61e03292017-10-19 14:27:12 -07003632
Makoto Onuki4d298b52018-02-05 10:54:58 -08003633 public void postRemoveForStopped(int uid) {
3634 obtainMessage(REMOVE_FOR_STOPPED, uid, 0).sendToTarget();
3635 }
3636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637 public void handleMessage(Message msg) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003638 switch (msg.what) {
3639 case ALARM_EVENT: {
3640 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
3641 synchronized (mLock) {
3642 final long nowRTC = System.currentTimeMillis();
3643 final long nowELAPSED = SystemClock.elapsedRealtime();
3644 triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
3645 updateNextAlarmClockLocked();
3646 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02003647
Christopher Tate14a7bb02015-10-01 10:24:31 -07003648 // now trigger the alarms without the lock held
3649 for (int i=0; i<triggerList.size(); i++) {
3650 Alarm alarm = triggerList.get(i);
3651 try {
3652 alarm.operation.send();
3653 } catch (PendingIntent.CanceledException e) {
3654 if (alarm.repeatInterval > 0) {
3655 // This IntentSender is no longer valid, but this
3656 // is a repeating alarm, so toss the hoser.
3657 removeImpl(alarm.operation);
3658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 }
3660 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003661 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003663
3664 case SEND_NEXT_ALARM_CLOCK_CHANGED:
3665 sendNextAlarmClockChanged();
3666 break;
3667
3668 case LISTENER_TIMEOUT:
3669 mDeliveryTracker.alarmTimedOut((IBinder) msg.obj);
3670 break;
3671
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003672 case REPORT_ALARMS_ACTIVE:
3673 if (mLocalDeviceIdleController != null) {
3674 mLocalDeviceIdleController.setAlarmsActive(msg.arg1 != 0);
3675 }
3676 break;
3677
Suprabh Shukla75edab12018-01-29 14:09:06 -08003678 case APP_STANDBY_PAROLE_CHANGED:
3679 synchronized (mLock) {
3680 mAppStandbyParole = (Boolean) msg.obj;
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003681 if (reorderAlarmsBasedOnStandbyBuckets(null)) {
3682 rescheduleKernelAlarmsLocked();
3683 updateNextAlarmClockLocked();
3684 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08003685 }
3686 break;
3687
3688 case APP_STANDBY_BUCKET_CHANGED:
3689 synchronized (mLock) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003690 final ArraySet<Pair<String, Integer>> filterPackages = new ArraySet<>();
3691 filterPackages.add(Pair.create((String) msg.obj, msg.arg1));
3692 if (reorderAlarmsBasedOnStandbyBuckets(filterPackages)) {
3693 rescheduleKernelAlarmsLocked();
3694 updateNextAlarmClockLocked();
3695 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08003696 }
3697 break;
3698
Makoto Onuki4d298b52018-02-05 10:54:58 -08003699 case REMOVE_FOR_STOPPED:
3700 synchronized (mLock) {
3701 removeForStoppedLocked(msg.arg1);
3702 }
3703 break;
3704
Christopher Tate14a7bb02015-10-01 10:24:31 -07003705 default:
3706 // nope, just ignore it
3707 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 }
3709 }
3710 }
Kweku Adams61e03292017-10-19 14:27:12 -07003711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712 class ClockReceiver extends BroadcastReceiver {
3713 public ClockReceiver() {
3714 IntentFilter filter = new IntentFilter();
3715 filter.addAction(Intent.ACTION_TIME_TICK);
3716 filter.addAction(Intent.ACTION_DATE_CHANGED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003717 getContext().registerReceiver(this, filter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 }
Kweku Adams61e03292017-10-19 14:27:12 -07003719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720 @Override
3721 public void onReceive(Context context, Intent intent) {
3722 if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
Christopher Tate385e4982013-07-23 18:22:29 -07003723 if (DEBUG_BATCH) {
3724 Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
3725 }
Christopher Tate12cf0b62018-01-05 18:40:14 -08003726 synchronized (mLock) {
3727 mLastTickReceived = System.currentTimeMillis();
3728 }
Christopher Tate385e4982013-07-23 18:22:29 -07003729 scheduleTimeTickEvent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003730 } else if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
3731 // Since the kernel does not keep track of DST, we need to
3732 // reset the TZ information at the beginning of each day
3733 // based off of the current Zone gmt offset + userspace tracked
3734 // daylight savings information.
3735 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
Lavettacn Xiaoc84cc4f2010-08-30 12:47:23 +02003736 int gmtOffset = zone.getOffset(System.currentTimeMillis());
Greg Hackmanna1d6f922013-12-09 16:56:53 -08003737 setKernelTimezone(mNativeData, -(gmtOffset / 60000));
Christopher Tate385e4982013-07-23 18:22:29 -07003738 scheduleDateChangedEvent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003739 }
3740 }
Kweku Adams61e03292017-10-19 14:27:12 -07003741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742 public void scheduleTimeTickEvent() {
Paul Westbrook51608a52011-08-25 13:18:54 -07003743 final long currentTime = System.currentTimeMillis();
Sungmin Choi563914a2013-01-10 17:28:40 +09003744 final long nextTime = 60000 * ((currentTime / 60000) + 1);
Paul Westbrook51608a52011-08-25 13:18:54 -07003745
3746 // Schedule this event for the amount of time that it would take to get to
3747 // the top of the next minute.
Sungmin Choi563914a2013-01-10 17:28:40 +09003748 final long tickEventDelay = nextTime - currentTime;
Paul Westbrook51608a52011-08-25 13:18:54 -07003749
David Christieebe51fc2013-07-26 13:23:29 -07003750 final WorkSource workSource = null; // Let system take blame for time tick events.
Adam Lesinski182f73f2013-12-05 16:48:06 -08003751 setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003752 0, mTimeTickSender, null, null, AlarmManager.FLAG_STANDALONE, workSource,
3753 null, Process.myUid(), "android");
Christopher Tate12cf0b62018-01-05 18:40:14 -08003754
3755 // Finally, remember when we set the tick alarm
3756 synchronized (mLock) {
3757 mLastTickSet = currentTime;
3758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003759 }
Christopher Tate385e4982013-07-23 18:22:29 -07003760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003761 public void scheduleDateChangedEvent() {
3762 Calendar calendar = Calendar.getInstance();
3763 calendar.setTimeInMillis(System.currentTimeMillis());
Christopher Tateafa8b982016-08-10 16:15:48 -07003764 calendar.set(Calendar.HOUR_OF_DAY, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 calendar.set(Calendar.MINUTE, 0);
3766 calendar.set(Calendar.SECOND, 0);
3767 calendar.set(Calendar.MILLISECOND, 0);
3768 calendar.add(Calendar.DAY_OF_MONTH, 1);
David Christieebe51fc2013-07-26 13:23:29 -07003769
3770 final WorkSource workSource = null; // Let system take blame for date change events.
Christopher Tate14a7bb02015-10-01 10:24:31 -07003771 setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
3772 AlarmManager.FLAG_STANDALONE, workSource, null,
3773 Process.myUid(), "android");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003774 }
3775 }
Kweku Adams61e03292017-10-19 14:27:12 -07003776
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003777 class InteractiveStateReceiver extends BroadcastReceiver {
3778 public InteractiveStateReceiver() {
3779 IntentFilter filter = new IntentFilter();
3780 filter.addAction(Intent.ACTION_SCREEN_OFF);
3781 filter.addAction(Intent.ACTION_SCREEN_ON);
3782 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
3783 getContext().registerReceiver(this, filter);
3784 }
3785
3786 @Override
3787 public void onReceive(Context context, Intent intent) {
3788 synchronized (mLock) {
3789 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
3790 }
3791 }
3792 }
3793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 class UninstallReceiver extends BroadcastReceiver {
3795 public UninstallReceiver() {
3796 IntentFilter filter = new IntentFilter();
3797 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
3798 filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003799 filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 filter.addDataScheme("package");
Adam Lesinski182f73f2013-12-05 16:48:06 -08003801 getContext().registerReceiver(this, filter);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003802 // Register for events related to sdcard installation.
3803 IntentFilter sdFilter = new IntentFilter();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08003804 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003805 sdFilter.addAction(Intent.ACTION_USER_STOPPED);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003806 sdFilter.addAction(Intent.ACTION_UID_REMOVED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003807 getContext().registerReceiver(this, sdFilter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808 }
Kweku Adams61e03292017-10-19 14:27:12 -07003809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 @Override
3811 public void onReceive(Context context, Intent intent) {
Christopher Tate1d99c392017-12-07 16:54:04 -08003812 final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813 synchronized (mLock) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003814 String action = intent.getAction();
3815 String pkgList[] = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003816 if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
3817 pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3818 for (String packageName : pkgList) {
3819 if (lookForPackageLocked(packageName)) {
3820 setResultCode(Activity.RESULT_OK);
3821 return;
3822 }
3823 }
3824 return;
3825 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003826 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003827 } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
3828 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
3829 if (userHandle >= 0) {
3830 removeUserLocked(userHandle);
Suprabh Shukla75edab12018-01-29 14:09:06 -08003831 for (int i = mLastAlarmDeliveredForPackage.size() - 1; i >= 0; i--) {
3832 final Pair<String, Integer> packageUser =
3833 mLastAlarmDeliveredForPackage.keyAt(i);
3834 if (packageUser.second == userHandle) {
3835 mLastAlarmDeliveredForPackage.removeAt(i);
3836 }
3837 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003838 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003839 } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003840 if (uid >= 0) {
3841 mLastAllowWhileIdleDispatch.delete(uid);
Makoto Onukiadb50d82018-01-29 16:20:30 -08003842 mUseAllowWhileIdleShortTime.delete(uid);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003843 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003844 } else {
Dianne Hackborn409578f2010-03-10 17:23:43 -08003845 if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
3846 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
3847 // This package is being updated; don't kill its alarms.
3848 return;
3849 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003850 Uri data = intent.getData();
3851 if (data != null) {
3852 String pkg = data.getSchemeSpecificPart();
3853 if (pkg != null) {
3854 pkgList = new String[]{pkg};
3855 }
3856 }
3857 }
3858 if (pkgList != null && (pkgList.length > 0)) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08003859 for (int i = mLastAlarmDeliveredForPackage.size() - 1; i >= 0; i--) {
3860 Pair<String, Integer> packageUser = mLastAlarmDeliveredForPackage.keyAt(i);
3861 if (ArrayUtils.contains(pkgList, packageUser.first)
3862 && packageUser.second == UserHandle.getUserId(uid)) {
3863 mLastAlarmDeliveredForPackage.removeAt(i);
3864 }
3865 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003866 for (String pkg : pkgList) {
Christopher Tate1d99c392017-12-07 16:54:04 -08003867 if (uid >= 0) {
3868 // package-removed case
3869 removeLocked(uid);
3870 } else {
3871 // external-applications-unavailable etc case
3872 removeLocked(pkg);
3873 }
Christopher Tate1590f1e2014-10-02 17:27:57 -07003874 mPriorities.remove(pkg);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003875 for (int i=mBroadcastStats.size()-1; i>=0; i--) {
3876 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
3877 if (uidStats.remove(pkg) != null) {
3878 if (uidStats.size() <= 0) {
3879 mBroadcastStats.removeAt(i);
3880 }
3881 }
3882 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003883 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003884 }
3885 }
3886 }
3887 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003888
3889 final class UidObserver extends IUidObserver.Stub {
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003890 @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003891 }
3892
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003893 @Override public void onUidGone(int uid, boolean disabled) {
Makoto Onuki4d298b52018-02-05 10:54:58 -08003894 if (disabled) {
3895 mHandler.postRemoveForStopped(uid);
Dianne Hackborne07641d2016-11-09 15:07:23 -08003896 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003897 }
3898
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003899 @Override public void onUidActive(int uid) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003900 }
3901
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003902 @Override public void onUidIdle(int uid, boolean disabled) {
Makoto Onuki4d298b52018-02-05 10:54:58 -08003903 if (disabled) {
3904 mHandler.postRemoveForStopped(uid);
Dianne Hackbornde9c48b2015-11-20 14:49:59 -08003905 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003906 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -07003907
3908 @Override public void onUidCachedChanged(int uid, boolean cached) {
3909 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003910 };
3911
Suprabh Shukla75edab12018-01-29 14:09:06 -08003912 /**
3913 * Tracking of app assignments to standby buckets
3914 */
3915 final class AppStandbyTracker extends UsageStatsManagerInternal.AppIdleStateChangeListener {
3916 @Override
3917 public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
Amith Yamasani119be9a2018-02-18 22:23:00 -08003918 boolean idle, int bucket, int reason) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08003919 if (DEBUG_STANDBY) {
3920 Slog.d(TAG, "Package " + packageName + " for user " + userId + " now in bucket " +
3921 bucket);
3922 }
3923 mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003924 mHandler.obtainMessage(AlarmHandler.APP_STANDBY_BUCKET_CHANGED, userId, -1, packageName)
3925 .sendToTarget();
Suprabh Shukla75edab12018-01-29 14:09:06 -08003926 }
3927
3928 @Override
3929 public void onParoleStateChanged(boolean isParoleOn) {
3930 if (DEBUG_STANDBY) {
3931 Slog.d(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
3932 }
3933 mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
3934 mHandler.removeMessages(AlarmHandler.APP_STANDBY_PAROLE_CHANGED);
3935 mHandler.obtainMessage(AlarmHandler.APP_STANDBY_PAROLE_CHANGED,
3936 Boolean.valueOf(isParoleOn)).sendToTarget();
3937 }
3938 };
3939
Makoto Onuki2206af32017-11-21 16:25:35 -08003940 private final Listener mForceAppStandbyListener = new Listener() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003941 @Override
Makoto Onuki2206af32017-11-21 16:25:35 -08003942 public void unblockAllUnrestrictedAlarms() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003943 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -08003944 sendAllUnrestrictedPendingBackgroundAlarmsLocked();
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003945 }
3946 }
Makoto Onuki2206af32017-11-21 16:25:35 -08003947
3948 @Override
3949 public void unblockAlarmsForUid(int uid) {
3950 synchronized (mLock) {
3951 sendPendingBackgroundAlarmsLocked(uid, null);
3952 }
3953 }
3954
3955 @Override
3956 public void unblockAlarmsForUidPackage(int uid, String packageName) {
3957 synchronized (mLock) {
3958 sendPendingBackgroundAlarmsLocked(uid, packageName);
3959 }
3960 }
Makoto Onukiadb50d82018-01-29 16:20:30 -08003961
3962 @Override
3963 public void onUidForeground(int uid, boolean foreground) {
3964 synchronized (mLock) {
3965 if (foreground) {
3966 mUseAllowWhileIdleShortTime.put(uid, true);
3967
3968 // Note we don't have to drain the pending while-idle alarms here, because
3969 // this event should coincide with unblockAlarmsForUid().
3970 }
3971 }
3972 }
Makoto Onuki2206af32017-11-21 16:25:35 -08003973 };
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003975 private final BroadcastStats getStatsLocked(PendingIntent pi) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003976 String pkg = pi.getCreatorPackage();
3977 int uid = pi.getCreatorUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07003978 return getStatsLocked(uid, pkg);
3979 }
3980
3981 private final BroadcastStats getStatsLocked(int uid, String pkgName) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003982 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
3983 if (uidStats == null) {
3984 uidStats = new ArrayMap<String, BroadcastStats>();
3985 mBroadcastStats.put(uid, uidStats);
3986 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003987 BroadcastStats bs = uidStats.get(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 if (bs == null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003989 bs = new BroadcastStats(uid, pkgName);
3990 uidStats.put(pkgName, bs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003991 }
3992 return bs;
3993 }
Dianne Hackborn81038902012-11-26 17:04:09 -08003994
Christopher Tate21e9f192017-08-08 13:49:11 -07003995 /**
3996 * Canonical count of (operation.send() - onSendFinished()) and
3997 * listener send/complete/timeout invocations.
3998 * Guarded by the usual lock.
3999 */
4000 @GuardedBy("mLock")
4001 private int mSendCount = 0;
4002 @GuardedBy("mLock")
Christopher Tateeabba732017-08-17 17:12:52 -07004003 private int mSendFinishCount = 0;
4004 @GuardedBy("mLock")
Christopher Tate21e9f192017-08-08 13:49:11 -07004005 private int mListenerCount = 0;
Christopher Tateeabba732017-08-17 17:12:52 -07004006 @GuardedBy("mLock")
4007 private int mListenerFinishCount = 0;
Christopher Tate21e9f192017-08-08 13:49:11 -07004008
Christopher Tate14a7bb02015-10-01 10:24:31 -07004009 class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished {
Christopher Tate21e9f192017-08-08 13:49:11 -07004010
Christopher Tate14a7bb02015-10-01 10:24:31 -07004011 private InFlight removeLocked(PendingIntent pi, Intent intent) {
4012 for (int i = 0; i < mInFlight.size(); i++) {
Christopher Tatedb9ae422017-08-21 11:24:30 -07004013 if (mInFlight.get(i).mPendingIntent == pi) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004014 return mInFlight.remove(i);
4015 }
4016 }
4017 mLog.w("No in-flight alarm for " + pi + " " + intent);
4018 return null;
4019 }
4020
4021 private InFlight removeLocked(IBinder listener) {
4022 for (int i = 0; i < mInFlight.size(); i++) {
4023 if (mInFlight.get(i).mListener == listener) {
4024 return mInFlight.remove(i);
4025 }
4026 }
4027 mLog.w("No in-flight alarm for listener " + listener);
4028 return null;
4029 }
4030
4031 private void updateStatsLocked(InFlight inflight) {
4032 final long nowELAPSED = SystemClock.elapsedRealtime();
4033 BroadcastStats bs = inflight.mBroadcastStats;
4034 bs.nesting--;
4035 if (bs.nesting <= 0) {
4036 bs.nesting = 0;
4037 bs.aggregateTime += nowELAPSED - bs.startTime;
4038 }
4039 FilterStats fs = inflight.mFilterStats;
4040 fs.nesting--;
4041 if (fs.nesting <= 0) {
4042 fs.nesting = 0;
4043 fs.aggregateTime += nowELAPSED - fs.startTime;
4044 }
4045 if (RECORD_ALARMS_IN_HISTORY) {
Narayan Kamath695cf722017-12-21 18:32:47 +00004046 ActivityManager.noteAlarmFinish(inflight.mPendingIntent, inflight.mWorkSource,
4047 inflight.mUid, inflight.mTag);
Christopher Tate14a7bb02015-10-01 10:24:31 -07004048 }
4049 }
4050
4051 private void updateTrackingLocked(InFlight inflight) {
4052 if (inflight != null) {
4053 updateStatsLocked(inflight);
4054 }
4055 mBroadcastRefCount--;
Makoto Onuki3e7d8452017-03-02 15:33:17 -08004056 if (DEBUG_WAKELOCK) {
4057 Slog.d(TAG, "mBroadcastRefCount -> " + mBroadcastRefCount);
4058 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004059 if (mBroadcastRefCount == 0) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004060 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07004061 mWakeLock.release();
4062 if (mInFlight.size() > 0) {
4063 mLog.w("Finished all dispatches with " + mInFlight.size()
4064 + " remaining inflights");
4065 for (int i=0; i<mInFlight.size(); i++) {
4066 mLog.w(" Remaining #" + i + ": " + mInFlight.get(i));
4067 }
4068 mInFlight.clear();
4069 }
4070 } else {
4071 // the next of our alarms is now in flight. reattribute the wakelock.
4072 if (mInFlight.size() > 0) {
4073 InFlight inFlight = mInFlight.get(0);
4074 setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
4075 inFlight.mAlarmType, inFlight.mTag, -1, false);
4076 } else {
4077 // should never happen
4078 mLog.w("Alarm wakelock still held but sent queue empty");
4079 mWakeLock.setWorkSource(null);
4080 }
4081 }
4082 }
4083
4084 /**
4085 * Callback that arrives when a direct-call alarm reports that delivery has finished
4086 */
4087 @Override
4088 public void alarmComplete(IBinder who) {
4089 if (who == null) {
Christopher Tate21e9f192017-08-08 13:49:11 -07004090 mLog.w("Invalid alarmComplete: uid=" + Binder.getCallingUid()
Christopher Tate14a7bb02015-10-01 10:24:31 -07004091 + " pid=" + Binder.getCallingPid());
4092 return;
4093 }
4094
4095 final long ident = Binder.clearCallingIdentity();
4096 try {
4097 synchronized (mLock) {
4098 mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who);
4099 InFlight inflight = removeLocked(who);
4100 if (inflight != null) {
4101 if (DEBUG_LISTENER_CALLBACK) {
4102 Slog.i(TAG, "alarmComplete() from " + who);
4103 }
4104 updateTrackingLocked(inflight);
Christopher Tateeabba732017-08-17 17:12:52 -07004105 mListenerFinishCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004106 } else {
4107 // Delivery timed out, and the timeout handling already took care of
4108 // updating our tracking here, so we needn't do anything further.
4109 if (DEBUG_LISTENER_CALLBACK) {
4110 Slog.i(TAG, "Late alarmComplete() from " + who);
4111 }
4112 }
4113 }
4114 } finally {
4115 Binder.restoreCallingIdentity(ident);
4116 }
4117 }
4118
4119 /**
4120 * Callback that arrives when a PendingIntent alarm has finished delivery
4121 */
4122 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004123 public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
4124 String resultData, Bundle resultExtras) {
4125 synchronized (mLock) {
Christopher Tateeabba732017-08-17 17:12:52 -07004126 mSendFinishCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004127 updateTrackingLocked(removeLocked(pi, intent));
4128 }
4129 }
4130
4131 /**
4132 * Timeout of a direct-call alarm delivery
4133 */
4134 public void alarmTimedOut(IBinder who) {
4135 synchronized (mLock) {
4136 InFlight inflight = removeLocked(who);
Dianne Hackborn81038902012-11-26 17:04:09 -08004137 if (inflight != null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004138 // TODO: implement ANR policy for the target
4139 if (DEBUG_LISTENER_CALLBACK) {
4140 Slog.i(TAG, "Alarm listener " + who + " timed out in delivery");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004141 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004142 updateTrackingLocked(inflight);
Christopher Tateeabba732017-08-17 17:12:52 -07004143 mListenerFinishCount++;
Dianne Hackborn81038902012-11-26 17:04:09 -08004144 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004145 if (DEBUG_LISTENER_CALLBACK) {
4146 Slog.i(TAG, "Spurious timeout of listener " + who);
4147 }
Christopher Tate21e9f192017-08-08 13:49:11 -07004148 mLog.w("Spurious timeout of listener " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004149 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004150 }
4151 }
4152
4153 /**
4154 * Deliver an alarm and set up the post-delivery handling appropriately
4155 */
Andreas Gampea36dc622018-02-05 17:19:22 -08004156 @GuardedBy("mLock")
Christopher Tate14a7bb02015-10-01 10:24:31 -07004157 public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
4158 if (alarm.operation != null) {
4159 // PendingIntent alarm
Christopher Tate21e9f192017-08-08 13:49:11 -07004160 mSendCount++;
Christopher Tate12cf0b62018-01-05 18:40:14 -08004161
4162 if (alarm.priorityClass.priority == PRIO_TICK) {
4163 mLastTickIssued = nowELAPSED;
4164 }
4165
Christopher Tate14a7bb02015-10-01 10:24:31 -07004166 try {
4167 alarm.operation.send(getContext(), 0,
4168 mBackgroundIntent.putExtra(
4169 Intent.EXTRA_ALARM_COUNT, alarm.count),
4170 mDeliveryTracker, mHandler, null,
4171 allowWhileIdle ? mIdleOptions : null);
4172 } catch (PendingIntent.CanceledException e) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08004173 if (alarm.operation == mTimeTickSender) {
4174 Slog.wtf(TAG, "mTimeTickSender canceled");
4175 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004176 if (alarm.repeatInterval > 0) {
4177 // This IntentSender is no longer valid, but this
4178 // is a repeating alarm, so toss it
4179 removeImpl(alarm.operation);
4180 }
Christopher Tate7f2a0352015-12-08 10:24:33 -08004181 // No actual delivery was possible, so the delivery tracker's
4182 // 'finished' callback won't be invoked. We also don't need
4183 // to do any wakelock or stats tracking, so we have nothing
4184 // left to do here but go on to the next thing.
Christopher Tateeabba732017-08-17 17:12:52 -07004185 mSendFinishCount++;
Christopher Tate7f2a0352015-12-08 10:24:33 -08004186 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004187 }
4188 } else {
4189 // Direct listener callback alarm
Christopher Tate21e9f192017-08-08 13:49:11 -07004190 mListenerCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004191 try {
4192 if (DEBUG_LISTENER_CALLBACK) {
4193 Slog.v(TAG, "Alarm to uid=" + alarm.uid
4194 + " listener=" + alarm.listener.asBinder());
4195 }
4196 alarm.listener.doAlarm(this);
4197 mHandler.sendMessageDelayed(
4198 mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
4199 alarm.listener.asBinder()),
4200 mConstants.LISTENER_TIMEOUT);
4201 } catch (Exception e) {
4202 if (DEBUG_LISTENER_CALLBACK) {
4203 Slog.i(TAG, "Alarm undeliverable to listener "
4204 + alarm.listener.asBinder(), e);
4205 }
Christopher Tate7f2a0352015-12-08 10:24:33 -08004206 // As in the PendingIntent.CanceledException case, delivery of the
4207 // alarm was not possible, so we have no wakelock or timeout or
4208 // stats management to do. It threw before we posted the delayed
4209 // timeout message, so we're done here.
Christopher Tateeabba732017-08-17 17:12:52 -07004210 mListenerFinishCount++;
Christopher Tate7f2a0352015-12-08 10:24:33 -08004211 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004212 }
4213 }
4214
4215 // The alarm is now in flight; now arrange wakelock and stats tracking
Makoto Onuki3e7d8452017-03-02 15:33:17 -08004216 if (DEBUG_WAKELOCK) {
4217 Slog.d(TAG, "mBroadcastRefCount -> " + (mBroadcastRefCount + 1));
4218 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004219 if (mBroadcastRefCount == 0) {
4220 setWakelockWorkSource(alarm.operation, alarm.workSource,
4221 alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1,
4222 true);
4223 mWakeLock.acquire();
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004224 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07004225 }
4226 final InFlight inflight = new InFlight(AlarmManagerService.this,
4227 alarm.operation, alarm.listener, alarm.workSource, alarm.uid,
4228 alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
4229 mInFlight.add(inflight);
4230 mBroadcastRefCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004231 if (allowWhileIdle) {
4232 // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
Suprabh Shuklac25447d2018-01-19 16:43:35 -08004233 mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED);
Makoto Onukie4918212018-02-06 11:30:15 -08004234 if ((mAppStateTracker == null)
4235 || mAppStateTracker.isUidInForeground(alarm.creatorUid)) {
Suprabh Shuklac25447d2018-01-19 16:43:35 -08004236 mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true);
4237 } else {
4238 mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false);
4239 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004240 if (RECORD_DEVICE_IDLE_ALARMS) {
4241 IdleDispatchEntry ent = new IdleDispatchEntry();
4242 ent.uid = alarm.uid;
4243 ent.pkg = alarm.packageName;
4244 ent.tag = alarm.statsTag;
4245 ent.op = "DELIVER";
4246 ent.elapsedRealtime = nowELAPSED;
4247 mAllowWhileIdleDispatches.add(ent);
4248 }
4249 }
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08004250 if (!isExemptFromAppStandby(alarm)) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08004251 final Pair<String, Integer> packageUser = Pair.create(alarm.sourcePackage,
4252 UserHandle.getUserId(alarm.creatorUid));
4253 mLastAlarmDeliveredForPackage.put(packageUser, nowELAPSED);
4254 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004255
4256 final BroadcastStats bs = inflight.mBroadcastStats;
4257 bs.count++;
4258 if (bs.nesting == 0) {
4259 bs.nesting = 1;
4260 bs.startTime = nowELAPSED;
4261 } else {
4262 bs.nesting++;
4263 }
4264 final FilterStats fs = inflight.mFilterStats;
4265 fs.count++;
4266 if (fs.nesting == 0) {
4267 fs.nesting = 1;
4268 fs.startTime = nowELAPSED;
4269 } else {
4270 fs.nesting++;
4271 }
4272 if (alarm.type == ELAPSED_REALTIME_WAKEUP
4273 || alarm.type == RTC_WAKEUP) {
4274 bs.numWakeup++;
4275 fs.numWakeup++;
Narayan Kamath695cf722017-12-21 18:32:47 +00004276 ActivityManager.noteWakeupAlarm(
4277 alarm.operation, alarm.workSource, alarm.uid, alarm.packageName,
4278 alarm.statsTag);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004279 }
4280 }
4281 }
mswest463f4c99d2018-02-01 10:13:10 -08004282
4283 private class ShellCmd extends ShellCommand {
4284
4285 IAlarmManager getBinderService() {
4286 return IAlarmManager.Stub.asInterface(mService);
4287 }
4288
4289 @Override
4290 public int onCommand(String cmd) {
4291 if (cmd == null) {
4292 return handleDefaultCommands(cmd);
4293 }
4294
4295 final PrintWriter pw = getOutPrintWriter();
4296 try {
4297 switch (cmd) {
4298 case "set-time":
4299 final long millis = Long.parseLong(getNextArgRequired());
4300 return (getBinderService().setTime(millis)) ? 0 : -1;
4301 case "set-timezone":
4302 final String tz = getNextArgRequired();
4303 getBinderService().setTimeZone(tz);
4304 return 0;
4305 default:
4306 return handleDefaultCommands(cmd);
4307 }
4308 } catch (Exception e) {
4309 pw.println(e);
4310 }
4311 return -1;
4312 }
4313
4314 @Override
4315 public void onHelp() {
4316 PrintWriter pw = getOutPrintWriter();
4317 pw.println("Alarm manager service (alarm) commands:");
4318 pw.println(" help");
4319 pw.println(" Print this help text.");
4320 pw.println(" set-time TIME");
4321 pw.println(" Set the system clock time to TIME where TIME is milliseconds");
4322 pw.println(" since the Epoch.");
4323 pw.println(" set-timezone TZ");
4324 pw.println(" Set the system timezone to TZ where TZ is an Olson id.");
4325 }
4326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004327}