blob: e50f7fc2ba1ad0f1c7b5346c049eae0f45f17c34 [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;
Suprabh Shukla6226c2f2018-08-22 18:15:04 -070055import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.os.Message;
Jeff Sharkey9911a282018-02-14 22:29:11 -070057import android.os.ParcelableException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.os.PowerManager;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -070059import android.os.Process;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070060import android.os.RemoteException;
mswest463f4c99d2018-02-01 10:13:10 -080061import android.os.ResultReceiver;
62import android.os.ShellCallback;
63import android.os.ShellCommand;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.os.SystemClock;
65import android.os.SystemProperties;
Tim Murray175c0f92017-11-28 15:01:04 -080066import android.os.Trace;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070067import android.os.UserHandle;
Christopher Tatec4a07d12012-04-06 14:19:13 -070068import android.os.WorkSource;
Adrian Roosc42a1e12014-07-07 23:35:53 +020069import android.provider.Settings;
Christopher Tate8b98ade2018-02-09 11:13:19 -080070import android.system.Os;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.text.TextUtils;
Adrian Roosc42a1e12014-07-07 23:35:53 +020072import android.text.format.DateFormat;
Christopher Tate22e919d2018-02-16 16:16:50 -080073import android.text.format.DateUtils;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080074import android.util.ArrayMap;
Suprabh Shukla92994ab2018-01-31 17:39:30 -080075import android.util.ArraySet;
Dianne Hackborna750a632015-06-16 17:18:23 -070076import android.util.KeyValueListParser;
Adrian Roosc42a1e12014-07-07 23:35:53 +020077import android.util.Log;
Jeff Sharkey9911a282018-02-14 22:29:11 -070078import android.util.NtpTrustedTime;
Suprabh Shukla75edab12018-01-29 14:09:06 -080079import android.util.Pair;
Joe Onorato8a9b2202010-02-26 18:56:32 -080080import android.util.Slog;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080081import android.util.SparseArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +020082import android.util.SparseBooleanArray;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -070083import android.util.SparseLongArray;
Bookatz7948c872018-09-04 12:58:33 -070084import android.util.StatsLog;
Dianne Hackborn043fcd92010-10-06 14:27:34 -070085import android.util.TimeUtils;
Kweku Adams61e03292017-10-19 14:27:12 -070086import android.util.proto.ProtoOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087
Jeff Sharkey9911a282018-02-14 22:29:11 -070088import com.android.internal.annotations.GuardedBy;
89import com.android.internal.annotations.VisibleForTesting;
90import com.android.internal.util.ArrayUtils;
91import com.android.internal.util.DumpUtils;
92import com.android.internal.util.LocalLog;
Makoto Onuki49392d32018-04-11 13:51:02 -070093import com.android.internal.util.StatLogger;
Jeff Sharkey9911a282018-02-14 22:29:11 -070094import com.android.server.AppStateTracker.Listener;
95
Christopher Tate4cb338d2013-07-26 13:11:31 -070096import java.io.ByteArrayOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import java.io.FileDescriptor;
98import java.io.PrintWriter;
Dianne Hackborn043fcd92010-10-06 14:27:34 -070099import java.text.SimpleDateFormat;
Jeff Sharkey9911a282018-02-14 22:29:11 -0700100import java.time.DateTimeException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import java.util.ArrayList;
Dianne Hackborn81038902012-11-26 17:04:09 -0800102import java.util.Arrays;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import java.util.Calendar;
104import java.util.Collections;
105import java.util.Comparator;
Mike Lockwood1f7b4132009-11-20 15:12:51 -0500106import java.util.Date;
Christopher Tate1590f1e2014-10-02 17:27:57 -0700107import java.util.HashMap;
Christopher Tate18a75f12013-07-01 18:18:59 -0700108import java.util.LinkedList;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200109import java.util.Locale;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700110import java.util.Random;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import java.util.TimeZone;
John Spurlock604a5ee2015-06-01 12:27:22 -0400112import java.util.TreeSet;
Makoto Onuki2206af32017-11-21 16:25:35 -0800113import java.util.function.Predicate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114
Makoto Onuki2206af32017-11-21 16:25:35 -0800115/**
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700116 * Alarm manager implementation.
Makoto Onuki2206af32017-11-21 16:25:35 -0800117 *
118 * Unit test:
119 atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java
120 */
Adam Lesinski182f73f2013-12-05 16:48:06 -0800121class AlarmManagerService extends SystemService {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700122 private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
123 private static final int RTC_MASK = 1 << RTC;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800124 private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700125 private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800126 static final int TIME_CHANGED_MASK = 1 << 16;
127 static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
Christopher Tateb8849c12011-02-08 13:39:01 -0800128
Christopher Tatee0a22b32013-07-11 14:43:13 -0700129 // Mask for testing whether a given alarm type is wakeup vs non-wakeup
Adam Lesinski182f73f2013-12-05 16:48:06 -0800130 static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
Christopher Tateb8849c12011-02-08 13:39:01 -0800131
Adam Lesinski182f73f2013-12-05 16:48:06 -0800132 static final String TAG = "AlarmManager";
Adam Lesinski182f73f2013-12-05 16:48:06 -0800133 static final boolean localLOGV = false;
134 static final boolean DEBUG_BATCH = localLOGV || false;
135 static final boolean DEBUG_VALIDATE = localLOGV || false;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200136 static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700137 static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
Makoto Onuki3e7d8452017-03-02 15:33:17 -0800138 static final boolean DEBUG_WAKELOCK = localLOGV || false;
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700139 static final boolean DEBUG_BG_LIMIT = localLOGV || false;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800140 static final boolean DEBUG_STANDBY = localLOGV || false;
Dianne Hackborn1e383822015-04-10 14:02:33 -0700141 static final boolean RECORD_ALARMS_IN_HISTORY = true;
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700142 static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800143 static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
Adrian Roosc42a1e12014-07-07 23:35:53 +0200144
Christopher Tatec8b7f432018-09-28 16:23:10 -0700145 static final int TICK_HISTORY_DEPTH = 10;
146
Christopher Tatef2159712018-03-27 16:04:14 -0700147 // Indices into the APP_STANDBY_MIN_DELAYS and KEYS_APP_STANDBY_DELAY arrays
148 static final int ACTIVE_INDEX = 0;
149 static final int WORKING_INDEX = 1;
150 static final int FREQUENT_INDEX = 2;
151 static final int RARE_INDEX = 3;
152 static final int NEVER_INDEX = 4;
153
Christopher Tate14a7bb02015-10-01 10:24:31 -0700154 private final Intent mBackgroundIntent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800156 static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700157
Adam Lesinski182f73f2013-12-05 16:48:06 -0800158 static final boolean WAKEUP_STATS = false;
Christopher Tate18a75f12013-07-01 18:18:59 -0700159
Christopher Tate24cd46f2016-02-02 14:28:01 -0800160 private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT =
161 new Intent(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)
Christopher Tate50191db2017-05-09 16:02:25 -0700162 .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
163 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Adrian Roosc42a1e12014-07-07 23:35:53 +0200164
Adam Lesinski182f73f2013-12-05 16:48:06 -0800165 final LocalLog mLog = new LocalLog(TAG);
Dianne Hackborn81038902012-11-26 17:04:09 -0800166
Christopher Tate14a7bb02015-10-01 10:24:31 -0700167 AppOpsManager mAppOps;
Dianne Hackborn627dfa12015-11-11 18:10:30 -0800168 DeviceIdleController.LocalService mLocalDeviceIdleController;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800169 private UsageStatsManagerInternal mUsageStatsManagerInternal;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700170
Adam Lesinski182f73f2013-12-05 16:48:06 -0800171 final Object mLock = new Object();
Dianne Hackborn81038902012-11-26 17:04:09 -0800172
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700173 // List of alarms per uid deferred due to user applied background restrictions on the source app
174 SparseArray<ArrayList<Alarm>> mPendingBackgroundAlarms = new SparseArray<>();
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800175 private long mNextWakeup;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700176 private long mNextNonWakeup;
Suprabh Shukla0e4510d2018-06-20 17:28:26 -0700177 private long mNextWakeUpSetAt;
178 private long mNextNonWakeUpSetAt;
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -0700179 private long mLastWakeup;
Christopher Tate8b98ade2018-02-09 11:13:19 -0800180 private long mLastTrigger;
Christopher Tatec8b7f432018-09-28 16:23:10 -0700181
Christopher Tate12cf0b62018-01-05 18:40:14 -0800182 private long mLastTickSet;
Christopher Tate12cf0b62018-01-05 18:40:14 -0800183 private long mLastTickReceived;
Makoto Onuki5d93b832018-01-10 16:12:39 -0800184 private long mLastTickAdded;
185 private long mLastTickRemoved;
Christopher Tatec8b7f432018-09-28 16:23:10 -0700186 // ring buffer of recent TIME_TICK issuance, in the elapsed timebase
187 private final long[] mTickHistory = new long[TICK_HISTORY_DEPTH];
188 private int mNextTickHistory;
189
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700190 private final Injector mInjector;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800191 int mBroadcastRefCount = 0;
192 PowerManager.WakeLock mWakeLock;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700193 ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
194 ArrayList<InFlight> mInFlight = new ArrayList<>();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700195 AlarmHandler mHandler;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800196 ClockReceiver mClockReceiver;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700197 final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
Christopher Tatec8b7f432018-09-28 16:23:10 -0700198 Intent mTimeTickIntent;
199 IAlarmListener mTimeTickTrigger;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800200 PendingIntent mDateChangeSender;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700201 Random mRandom;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700202 boolean mInteractive = true;
203 long mNonInteractiveStartTime;
204 long mNonInteractiveTime;
205 long mLastAlarmDeliveryTime;
206 long mStartCurrentDelayTime;
207 long mNextNonWakeupDeliveryTime;
Dianne Hackbornc3527222015-05-13 14:03:20 -0700208 long mLastTimeChangeClockTime;
209 long mLastTimeChangeRealtime;
Dianne Hackborn998e6082014-09-11 19:13:23 -0700210 int mNumTimeChanged;
Dianne Hackborn81038902012-11-26 17:04:09 -0800211
Christopher Tatebb9cce52017-04-18 14:19:43 -0700212 // Bookkeeping about the identity of the "System UI" package, determined at runtime.
213
214 /**
215 * This permission must be defined by the canonical System UI package,
216 * with protection level "signature".
217 */
218 private static final String SYSTEM_UI_SELF_PERMISSION =
219 "android.permission.systemui.IDENTITY";
220
221 /**
222 * At boot we use SYSTEM_UI_SELF_PERMISSION to look up the definer's uid.
223 */
224 int mSystemUiUid;
225
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700226 /**
227 * For each uid, this is the last time we dispatched an "allow while idle" alarm,
Kweku Adams61e03292017-10-19 14:27:12 -0700228 * used to determine the earliest we can dispatch the next such alarm. Times are in the
229 * 'elapsed' timebase.
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700230 */
231 final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
232
Suprabh Shuklac25447d2018-01-19 16:43:35 -0800233 /**
234 * For each uid, we store whether the last allow-while-idle alarm was dispatched while
235 * the uid was in foreground or not. We will use the allow_while_idle_short_time in such cases.
236 */
237 final SparseBooleanArray mUseAllowWhileIdleShortTime = new SparseBooleanArray();
238
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700239 final static class IdleDispatchEntry {
240 int uid;
241 String pkg;
242 String tag;
243 String op;
244 long elapsedRealtime;
245 long argRealtime;
246 }
247 final ArrayList<IdleDispatchEntry> mAllowWhileIdleDispatches = new ArrayList();
248
Suprabh Shukla75edab12018-01-29 14:09:06 -0800249 interface Stats {
250 int REBATCH_ALL_ALARMS = 0;
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800251 int REORDER_ALARMS_FOR_STANDBY = 1;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800252 }
253
254 private final StatLogger mStatLogger = new StatLogger(new String[] {
255 "REBATCH_ALL_ALARMS",
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800256 "REORDER_ALARMS_FOR_STANDBY",
Suprabh Shukla75edab12018-01-29 14:09:06 -0800257 });
258
Dianne Hackborna750a632015-06-16 17:18:23 -0700259 /**
260 * Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
261 */
262 Bundle mIdleOptions;
263
Jose Lima235510e2014-08-13 12:50:01 -0700264 private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
265 new SparseArray<>();
266 private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
267 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200268 private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
269 new SparseBooleanArray();
270 private boolean mNextAlarmClockMayChange;
271
272 // May only use on mHandler's thread, locking not required.
Jose Lima235510e2014-08-13 12:50:01 -0700273 private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
274 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200275
Makoto Onukie4918212018-02-06 11:30:15 -0800276 private AppStateTracker mAppStateTracker;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800277 private boolean mAppStandbyParole;
278 private ArrayMap<Pair<String, Integer>, Long> mLastAlarmDeliveredForPackage = new ArrayMap<>();
Makoto Onuki2206af32017-11-21 16:25:35 -0800279
Dianne Hackborna750a632015-06-16 17:18:23 -0700280 /**
281 * All times are in milliseconds. These constants are kept synchronized with the system
282 * global Settings. Any access to this class or its fields should be done while
283 * holding the AlarmManagerService.mLock lock.
284 */
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700285 @VisibleForTesting
286 final class Constants extends ContentObserver {
Dianne Hackborna750a632015-06-16 17:18:23 -0700287 // Key names stored in the settings value.
Suprabh Shuklaadfa6e82018-10-19 17:32:08 -0700288 @VisibleForTesting
289 static final String KEY_MIN_FUTURITY = "min_futurity";
290 @VisibleForTesting
291 static final String KEY_MIN_INTERVAL = "min_interval";
292 @VisibleForTesting
293 static final String KEY_MAX_INTERVAL = "max_interval";
294 @VisibleForTesting
295 static final String KEY_ALLOW_WHILE_IDLE_SHORT_TIME = "allow_while_idle_short_time";
296 @VisibleForTesting
297 static final String KEY_ALLOW_WHILE_IDLE_LONG_TIME = "allow_while_idle_long_time";
298 @VisibleForTesting
299 static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
Dianne Hackborna750a632015-06-16 17:18:23 -0700300 = "allow_while_idle_whitelist_duration";
Suprabh Shuklaadfa6e82018-10-19 17:32:08 -0700301 @VisibleForTesting
302 static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
Dianne Hackborna750a632015-06-16 17:18:23 -0700303
Suprabh Shukla75edab12018-01-29 14:09:06 -0800304 // Keys for specifying throttling delay based on app standby bucketing
305 private final String[] KEYS_APP_STANDBY_DELAY = {
306 "standby_active_delay",
307 "standby_working_delay",
308 "standby_frequent_delay",
309 "standby_rare_delay",
310 "standby_never_delay",
311 };
312
Dianne Hackborna750a632015-06-16 17:18:23 -0700313 private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
314 private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
Christopher Tate22e919d2018-02-16 16:16:50 -0800315 private static final long DEFAULT_MAX_INTERVAL = 365 * DateUtils.DAY_IN_MILLIS;
Christopher Tateaa244da2015-08-27 15:57:57 -0700316 private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
Dianne Hackborn7682b262015-10-26 17:51:57 -0700317 private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000;
Dianne Hackborna750a632015-06-16 17:18:23 -0700318 private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700319 private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800320 private final long[] DEFAULT_APP_STANDBY_DELAYS = {
321 0, // Active
322 6 * 60_000, // Working
323 30 * 60_000, // Frequent
324 2 * 60 * 60_000, // Rare
325 10 * 24 * 60 * 60_000 // Never
326 };
Christopher Tate14a7bb02015-10-01 10:24:31 -0700327
Dianne Hackborna750a632015-06-16 17:18:23 -0700328 // Minimum futurity of a new alarm
329 public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
330
331 // Minimum alarm recurrence interval
332 public long MIN_INTERVAL = DEFAULT_MIN_INTERVAL;
333
Christopher Tate22e919d2018-02-16 16:16:50 -0800334 // Maximum alarm recurrence interval
335 public long MAX_INTERVAL = DEFAULT_MAX_INTERVAL;
336
Dianne Hackborna750a632015-06-16 17:18:23 -0700337 // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
338 public long ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME;
339
340 // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
341 public long ALLOW_WHILE_IDLE_LONG_TIME = DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME;
342
343 // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
344 public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
345 = DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
346
Christopher Tate14a7bb02015-10-01 10:24:31 -0700347 // Direct alarm listener callback timeout
348 public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
349
Suprabh Shukla75edab12018-01-29 14:09:06 -0800350 public long[] APP_STANDBY_MIN_DELAYS = new long[DEFAULT_APP_STANDBY_DELAYS.length];
351
Dianne Hackborna750a632015-06-16 17:18:23 -0700352 private ContentResolver mResolver;
353 private final KeyValueListParser mParser = new KeyValueListParser(',');
354 private long mLastAllowWhileIdleWhitelistDuration = -1;
355
356 public Constants(Handler handler) {
357 super(handler);
Dianne Hackborna750a632015-06-16 17:18:23 -0700358 updateAllowWhileIdleWhitelistDurationLocked();
359 }
360
361 public void start(ContentResolver resolver) {
362 mResolver = resolver;
363 mResolver.registerContentObserver(Settings.Global.getUriFor(
364 Settings.Global.ALARM_MANAGER_CONSTANTS), false, this);
365 updateConstants();
366 }
367
Dianne Hackborna750a632015-06-16 17:18:23 -0700368 public void updateAllowWhileIdleWhitelistDurationLocked() {
369 if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
370 mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
371 BroadcastOptions opts = BroadcastOptions.makeBasic();
372 opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
373 mIdleOptions = opts.toBundle();
374 }
375 }
376
377 @Override
378 public void onChange(boolean selfChange, Uri uri) {
379 updateConstants();
380 }
381
382 private void updateConstants() {
383 synchronized (mLock) {
384 try {
385 mParser.setString(Settings.Global.getString(mResolver,
386 Settings.Global.ALARM_MANAGER_CONSTANTS));
387 } catch (IllegalArgumentException e) {
388 // Failed to parse the settings string, log this and move on
389 // with defaults.
Dianne Hackborn0ef403e2017-01-24 18:22:15 -0800390 Slog.e(TAG, "Bad alarm manager settings", e);
Dianne Hackborna750a632015-06-16 17:18:23 -0700391 }
392
393 MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
394 MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
Christopher Tate22e919d2018-02-16 16:16:50 -0800395 MAX_INTERVAL = mParser.getLong(KEY_MAX_INTERVAL, DEFAULT_MAX_INTERVAL);
Dianne Hackborna750a632015-06-16 17:18:23 -0700396 ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
397 DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
398 ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME,
399 DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
400 ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong(
401 KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
402 DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700403 LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
404 DEFAULT_LISTENER_TIMEOUT);
Christopher Tatef2159712018-03-27 16:04:14 -0700405 APP_STANDBY_MIN_DELAYS[ACTIVE_INDEX] = mParser.getDurationMillis(
406 KEYS_APP_STANDBY_DELAY[ACTIVE_INDEX],
407 DEFAULT_APP_STANDBY_DELAYS[ACTIVE_INDEX]);
408 for (int i = WORKING_INDEX; i < KEYS_APP_STANDBY_DELAY.length; i++) {
Suprabh Shukla75edab12018-01-29 14:09:06 -0800409 APP_STANDBY_MIN_DELAYS[i] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[i],
410 Math.max(APP_STANDBY_MIN_DELAYS[i-1], DEFAULT_APP_STANDBY_DELAYS[i]));
411 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700412 updateAllowWhileIdleWhitelistDurationLocked();
413 }
414 }
415
416 void dump(PrintWriter pw) {
417 pw.println(" Settings:");
418
419 pw.print(" "); pw.print(KEY_MIN_FUTURITY); pw.print("=");
420 TimeUtils.formatDuration(MIN_FUTURITY, pw);
421 pw.println();
422
423 pw.print(" "); pw.print(KEY_MIN_INTERVAL); pw.print("=");
424 TimeUtils.formatDuration(MIN_INTERVAL, pw);
425 pw.println();
426
Christopher Tate22e919d2018-02-16 16:16:50 -0800427 pw.print(" "); pw.print(KEY_MAX_INTERVAL); pw.print("=");
428 TimeUtils.formatDuration(MAX_INTERVAL, pw);
429 pw.println();
430
Christopher Tate14a7bb02015-10-01 10:24:31 -0700431 pw.print(" "); pw.print(KEY_LISTENER_TIMEOUT); pw.print("=");
432 TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
433 pw.println();
434
Dianne Hackborna750a632015-06-16 17:18:23 -0700435 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME); pw.print("=");
436 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw);
437 pw.println();
438
439 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME); pw.print("=");
440 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw);
441 pw.println();
442
443 pw.print(" "); pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); pw.print("=");
444 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
445 pw.println();
Suprabh Shukla75edab12018-01-29 14:09:06 -0800446
447 for (int i = 0; i < KEYS_APP_STANDBY_DELAY.length; i++) {
448 pw.print(" "); pw.print(KEYS_APP_STANDBY_DELAY[i]); pw.print("=");
449 TimeUtils.formatDuration(APP_STANDBY_MIN_DELAYS[i], pw);
450 pw.println();
451 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700452 }
Kweku Adams61e03292017-10-19 14:27:12 -0700453
454 void dumpProto(ProtoOutputStream proto, long fieldId) {
455 final long token = proto.start(fieldId);
456
457 proto.write(ConstantsProto.MIN_FUTURITY_DURATION_MS, MIN_FUTURITY);
458 proto.write(ConstantsProto.MIN_INTERVAL_DURATION_MS, MIN_INTERVAL);
Christopher Tate22e919d2018-02-16 16:16:50 -0800459 proto.write(ConstantsProto.MAX_INTERVAL_DURATION_MS, MAX_INTERVAL);
Kweku Adams61e03292017-10-19 14:27:12 -0700460 proto.write(ConstantsProto.LISTENER_TIMEOUT_DURATION_MS, LISTENER_TIMEOUT);
461 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_SHORT_DURATION_MS,
462 ALLOW_WHILE_IDLE_SHORT_TIME);
463 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_LONG_DURATION_MS,
464 ALLOW_WHILE_IDLE_LONG_TIME);
465 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_WHITELIST_DURATION_MS,
466 ALLOW_WHILE_IDLE_WHITELIST_DURATION);
467
468 proto.end(token);
469 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700470 }
471
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700472 Constants mConstants;
Dianne Hackborna750a632015-06-16 17:18:23 -0700473
Christopher Tate1590f1e2014-10-02 17:27:57 -0700474 // Alarm delivery ordering bookkeeping
475 static final int PRIO_TICK = 0;
476 static final int PRIO_WAKEUP = 1;
477 static final int PRIO_NORMAL = 2;
478
Dianne Hackborna750a632015-06-16 17:18:23 -0700479 final class PriorityClass {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700480 int seq;
481 int priority;
482
483 PriorityClass() {
484 seq = mCurrentSeq - 1;
485 priority = PRIO_NORMAL;
486 }
487 }
488
Dianne Hackborna750a632015-06-16 17:18:23 -0700489 final HashMap<String, PriorityClass> mPriorities = new HashMap<>();
Christopher Tate1590f1e2014-10-02 17:27:57 -0700490 int mCurrentSeq = 0;
491
Dianne Hackborna750a632015-06-16 17:18:23 -0700492 static final class WakeupEvent {
Christopher Tate18a75f12013-07-01 18:18:59 -0700493 public long when;
494 public int uid;
495 public String action;
496
497 public WakeupEvent(long theTime, int theUid, String theAction) {
498 when = theTime;
499 uid = theUid;
500 action = theAction;
501 }
502 }
503
Adam Lesinski182f73f2013-12-05 16:48:06 -0800504 final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
505 final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
Christopher Tate18a75f12013-07-01 18:18:59 -0700506
Adrian Roosc42a1e12014-07-07 23:35:53 +0200507 final class Batch {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700508 long start; // These endpoints are always in ELAPSED
509 long end;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700510 int flags; // Flags for alarms, such as FLAG_STANDALONE.
Christopher Tatee0a22b32013-07-11 14:43:13 -0700511
512 final ArrayList<Alarm> alarms = new ArrayList<Alarm>();
513
514 Batch() {
515 start = 0;
516 end = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700517 flags = 0;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700518 }
519
520 Batch(Alarm seed) {
521 start = seed.whenElapsed;
Christopher Tate22e919d2018-02-16 16:16:50 -0800522 end = clampPositive(seed.maxWhenElapsed);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700523 flags = seed.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700524 alarms.add(seed);
Christopher Tatec8b7f432018-09-28 16:23:10 -0700525 if (seed.listener == mTimeTickTrigger) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700526 mLastTickAdded = mInjector.getCurrentTimeMillis();
Makoto Onuki5d93b832018-01-10 16:12:39 -0800527 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700528 }
529
530 int size() {
531 return alarms.size();
532 }
533
534 Alarm get(int index) {
535 return alarms.get(index);
536 }
537
538 boolean canHold(long whenElapsed, long maxWhen) {
539 return (end >= whenElapsed) && (start <= maxWhen);
540 }
541
542 boolean add(Alarm alarm) {
543 boolean newStart = false;
544 // narrows the batch if necessary; presumes that canHold(alarm) is true
545 int index = Collections.binarySearch(alarms, alarm, sIncreasingTimeOrder);
546 if (index < 0) {
547 index = 0 - index - 1;
548 }
549 alarms.add(index, alarm);
Christopher Tatec8b7f432018-09-28 16:23:10 -0700550 if (alarm.listener == mTimeTickTrigger) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700551 mLastTickAdded = mInjector.getCurrentTimeMillis();
Makoto Onuki5d93b832018-01-10 16:12:39 -0800552 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700553 if (DEBUG_BATCH) {
554 Slog.v(TAG, "Adding " + alarm + " to " + this);
555 }
556 if (alarm.whenElapsed > start) {
557 start = alarm.whenElapsed;
558 newStart = true;
559 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700560 if (alarm.maxWhenElapsed < end) {
561 end = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700562 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700563 flags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700564
565 if (DEBUG_BATCH) {
566 Slog.v(TAG, " => now " + this);
567 }
568 return newStart;
569 }
570
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800571 boolean remove(Alarm alarm) {
572 return remove(a -> (a == alarm));
573 }
574
Christopher Tate1d99c392017-12-07 16:54:04 -0800575 boolean remove(Predicate<Alarm> predicate) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700576 boolean didRemove = false;
577 long newStart = 0; // recalculate endpoints as we go
578 long newEnd = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700579 int newFlags = 0;
Christopher Tateae269d52013-09-26 13:11:55 -0700580 for (int i = 0; i < alarms.size(); ) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700581 Alarm alarm = alarms.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -0800582 if (predicate.test(alarm)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700583 alarms.remove(i);
584 didRemove = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200585 if (alarm.alarmClock != null) {
586 mNextAlarmClockMayChange = true;
587 }
Christopher Tatec8b7f432018-09-28 16:23:10 -0700588 if (alarm.listener == mTimeTickTrigger) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700589 mLastTickRemoved = mInjector.getCurrentTimeMillis();
Makoto Onuki5d93b832018-01-10 16:12:39 -0800590 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700591 } else {
592 if (alarm.whenElapsed > newStart) {
593 newStart = alarm.whenElapsed;
594 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700595 if (alarm.maxWhenElapsed < newEnd) {
596 newEnd = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700597 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700598 newFlags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700599 i++;
600 }
601 }
602 if (didRemove) {
603 // commit the new batch bounds
604 start = newStart;
605 end = newEnd;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700606 flags = newFlags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700607 }
608 return didRemove;
609 }
610
Christopher Tatee0a22b32013-07-11 14:43:13 -0700611 boolean hasPackage(final String packageName) {
612 final int N = alarms.size();
613 for (int i = 0; i < N; i++) {
614 Alarm a = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700615 if (a.matches(packageName)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700616 return true;
617 }
618 }
619 return false;
620 }
621
622 boolean hasWakeups() {
623 final int N = alarms.size();
624 for (int i = 0; i < N; i++) {
625 Alarm a = alarms.get(i);
626 // non-wakeup alarms are types 1 and 3, i.e. have the low bit set
627 if ((a.type & TYPE_NONWAKEUP_MASK) == 0) {
628 return true;
629 }
630 }
631 return false;
632 }
633
634 @Override
635 public String toString() {
636 StringBuilder b = new StringBuilder(40);
637 b.append("Batch{"); b.append(Integer.toHexString(this.hashCode()));
638 b.append(" num="); b.append(size());
639 b.append(" start="); b.append(start);
640 b.append(" end="); b.append(end);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700641 if (flags != 0) {
642 b.append(" flgs=0x");
643 b.append(Integer.toHexString(flags));
Christopher Tatee0a22b32013-07-11 14:43:13 -0700644 }
645 b.append('}');
646 return b.toString();
647 }
Kweku Adams61e03292017-10-19 14:27:12 -0700648
649 public void writeToProto(ProtoOutputStream proto, long fieldId, long nowElapsed,
650 long nowRTC) {
651 final long token = proto.start(fieldId);
652
653 proto.write(BatchProto.START_REALTIME, start);
654 proto.write(BatchProto.END_REALTIME, end);
655 proto.write(BatchProto.FLAGS, flags);
656 for (Alarm a : alarms) {
657 a.writeToProto(proto, BatchProto.ALARMS, nowElapsed, nowRTC);
658 }
659
660 proto.end(token);
661 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700662 }
663
664 static class BatchTimeOrder implements Comparator<Batch> {
665 public int compare(Batch b1, Batch b2) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800666 long when1 = b1.start;
667 long when2 = b2.start;
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800668 if (when1 > when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700669 return 1;
670 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800671 if (when1 < when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700672 return -1;
673 }
674 return 0;
675 }
676 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800677
678 final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
679 @Override
680 public int compare(Alarm lhs, Alarm rhs) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700681 // priority class trumps everything. TICK < WAKEUP < NORMAL
682 if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
683 return -1;
684 } else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
685 return 1;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800686 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700687
688 // within each class, sort by nominal delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800689 if (lhs.whenElapsed < rhs.whenElapsed) {
690 return -1;
691 } else if (lhs.whenElapsed > rhs.whenElapsed) {
692 return 1;
693 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700694
695 // same priority class + same target delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800696 return 0;
697 }
698 };
699
Christopher Tate1590f1e2014-10-02 17:27:57 -0700700 void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
701 final int N = alarms.size();
702 for (int i = 0; i < N; i++) {
703 Alarm a = alarms.get(i);
704
705 final int alarmPrio;
Christopher Tatec8b7f432018-09-28 16:23:10 -0700706 if (a.listener == mTimeTickTrigger) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700707 alarmPrio = PRIO_TICK;
708 } else if (a.wakeup) {
709 alarmPrio = PRIO_WAKEUP;
710 } else {
711 alarmPrio = PRIO_NORMAL;
712 }
713
714 PriorityClass packagePrio = a.priorityClass;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800715 String alarmPackage = a.sourcePackage;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700716 if (packagePrio == null) packagePrio = mPriorities.get(alarmPackage);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700717 if (packagePrio == null) {
718 packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
Christopher Tate14a7bb02015-10-01 10:24:31 -0700719 mPriorities.put(alarmPackage, packagePrio);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700720 }
721 a.priorityClass = packagePrio;
722
723 if (packagePrio.seq != mCurrentSeq) {
724 // first alarm we've seen in the current delivery generation from this package
725 packagePrio.priority = alarmPrio;
726 packagePrio.seq = mCurrentSeq;
727 } else {
728 // Multiple alarms from this package being delivered in this generation;
729 // bump the package's delivery class if it's warranted.
730 // TICK < WAKEUP < NORMAL
731 if (alarmPrio < packagePrio.priority) {
732 packagePrio.priority = alarmPrio;
733 }
734 }
735 }
736 }
737
Christopher Tatee0a22b32013-07-11 14:43:13 -0700738 // minimum recurrence period or alarm futurity for us to be able to fuzz it
Adam Lesinski182f73f2013-12-05 16:48:06 -0800739 static final long MIN_FUZZABLE_INTERVAL = 10000;
740 static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700741 final ArrayList<Batch> mAlarmBatches = new ArrayList<>();
742
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700743 // 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 -0700744 // to run during this time are placed in mPendingWhileIdleAlarms
745 Alarm mPendingIdleUntil = null;
Dianne Hackbornf70faed2015-04-21 14:11:38 -0700746 Alarm mNextWakeFromIdle = null;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700747 ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
Christopher Tatee0a22b32013-07-11 14:43:13 -0700748
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700749 @VisibleForTesting
750 AlarmManagerService(Context context, Injector injector) {
Jeff Brownb880d882014-02-10 19:47:07 -0800751 super(context);
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700752 mInjector = injector;
Jeff Brownb880d882014-02-10 19:47:07 -0800753 }
754
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700755 AlarmManagerService(Context context) {
756 this(context, new Injector(context));
757 }
758
759 private long convertToElapsed(long when, int type) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700760 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
761 if (isRtc) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700762 when -= mInjector.getCurrentTimeMillis() - mInjector.getElapsedRealtime();
Christopher Tatee0a22b32013-07-11 14:43:13 -0700763 }
764 return when;
765 }
766
767 // Apply a heuristic to { recurrence interval, futurity of the trigger time } to
768 // calculate the end of our nominal delivery window for the alarm.
769 static long maxTriggerTime(long now, long triggerAtTime, long interval) {
770 // Current heuristic: batchable window is 75% of either the recurrence interval
771 // [for a periodic alarm] or of the time from now to the desired delivery time,
772 // with a minimum delay/interval of 10 seconds, under which we will simply not
773 // defer the alarm.
774 long futurity = (interval == 0)
775 ? (triggerAtTime - now)
776 : interval;
Christopher Tate57ceaaa2013-07-19 16:30:43 -0700777 if (futurity < MIN_FUZZABLE_INTERVAL) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700778 futurity = 0;
779 }
Christopher Tate22e919d2018-02-16 16:16:50 -0800780 return clampPositive(triggerAtTime + (long)(.75 * futurity));
Christopher Tatee0a22b32013-07-11 14:43:13 -0700781 }
782
783 // returns true if the batch was added at the head
784 static boolean addBatchLocked(ArrayList<Batch> list, Batch newBatch) {
785 int index = Collections.binarySearch(list, newBatch, sBatchOrder);
786 if (index < 0) {
787 index = 0 - index - 1;
788 }
789 list.add(index, newBatch);
790 return (index == 0);
791 }
792
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800793 private void insertAndBatchAlarmLocked(Alarm alarm) {
794 final int whichBatch = ((alarm.flags & AlarmManager.FLAG_STANDALONE) != 0) ? -1
795 : attemptCoalesceLocked(alarm.whenElapsed, alarm.maxWhenElapsed);
796
797 if (whichBatch < 0) {
798 addBatchLocked(mAlarmBatches, new Batch(alarm));
799 } else {
800 final Batch batch = mAlarmBatches.get(whichBatch);
801 if (batch.add(alarm)) {
802 // The start time of this batch advanced, so batch ordering may
803 // have just been broken. Move it to where it now belongs.
804 mAlarmBatches.remove(whichBatch);
805 addBatchLocked(mAlarmBatches, batch);
806 }
807 }
808 }
809
Christopher Tate385e4982013-07-23 18:22:29 -0700810 // Return the index of the matching batch, or -1 if none found.
811 int attemptCoalesceLocked(long whenElapsed, long maxWhen) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700812 final int N = mAlarmBatches.size();
813 for (int i = 0; i < N; i++) {
814 Batch b = mAlarmBatches.get(i);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700815 if ((b.flags&AlarmManager.FLAG_STANDALONE) == 0 && b.canHold(whenElapsed, maxWhen)) {
Christopher Tate385e4982013-07-23 18:22:29 -0700816 return i;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700817 }
818 }
Christopher Tate385e4982013-07-23 18:22:29 -0700819 return -1;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700820 }
Makoto Onuki5d93b832018-01-10 16:12:39 -0800821 /** @return total count of the alarms in a set of alarm batches. */
822 static int getAlarmCount(ArrayList<Batch> batches) {
823 int ret = 0;
824
825 final int size = batches.size();
826 for (int i = 0; i < size; i++) {
827 ret += batches.get(i).size();
828 }
829 return ret;
830 }
831
832 boolean haveAlarmsTimeTickAlarm(ArrayList<Alarm> alarms) {
833 if (alarms.size() == 0) {
834 return false;
835 }
836 final int batchSize = alarms.size();
837 for (int j = 0; j < batchSize; j++) {
Christopher Tatec8b7f432018-09-28 16:23:10 -0700838 if (alarms.get(j).listener == mTimeTickTrigger) {
Makoto Onuki5d93b832018-01-10 16:12:39 -0800839 return true;
840 }
841 }
842 return false;
843 }
844
845 boolean haveBatchesTimeTickAlarm(ArrayList<Batch> batches) {
846 final int numBatches = batches.size();
847 for (int i = 0; i < numBatches; i++) {
848 if (haveAlarmsTimeTickAlarm(batches.get(i).alarms)) {
849 return true;
850 }
851 }
852 return false;
853 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700854
855 // The RTC clock has moved arbitrarily, so we need to recalculate all the batching
856 void rebatchAllAlarms() {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700857 synchronized (mLock) {
Christopher Tate4cb338d2013-07-26 13:11:31 -0700858 rebatchAllAlarmsLocked(true);
859 }
860 }
861
862 void rebatchAllAlarmsLocked(boolean doValidate) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800863 final long start = mStatLogger.getTime();
Makoto Onuki5d93b832018-01-10 16:12:39 -0800864 final int oldCount =
865 getAlarmCount(mAlarmBatches) + ArrayUtils.size(mPendingWhileIdleAlarms);
866 final boolean oldHasTick = haveBatchesTimeTickAlarm(mAlarmBatches)
867 || haveAlarmsTimeTickAlarm(mPendingWhileIdleAlarms);
868
Christopher Tate4cb338d2013-07-26 13:11:31 -0700869 ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone();
870 mAlarmBatches.clear();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700871 Alarm oldPendingIdleUntil = mPendingIdleUntil;
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700872 final long nowElapsed = mInjector.getElapsedRealtime();
Christopher Tate4cb338d2013-07-26 13:11:31 -0700873 final int oldBatches = oldSet.size();
874 for (int batchNum = 0; batchNum < oldBatches; batchNum++) {
875 Batch batch = oldSet.get(batchNum);
876 final int N = batch.size();
877 for (int i = 0; i < N; i++) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700878 reAddAlarmLocked(batch.get(i), nowElapsed, doValidate);
Christopher Tatee0a22b32013-07-11 14:43:13 -0700879 }
880 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700881 if (oldPendingIdleUntil != null && oldPendingIdleUntil != mPendingIdleUntil) {
882 Slog.wtf(TAG, "Rebatching: idle until changed from " + oldPendingIdleUntil
883 + " to " + mPendingIdleUntil);
884 if (mPendingIdleUntil == null) {
885 // Somehow we lost this... we need to restore all of the pending alarms.
886 restorePendingWhileIdleAlarmsLocked();
887 }
888 }
Makoto Onuki5d93b832018-01-10 16:12:39 -0800889 final int newCount =
890 getAlarmCount(mAlarmBatches) + ArrayUtils.size(mPendingWhileIdleAlarms);
891 final boolean newHasTick = haveBatchesTimeTickAlarm(mAlarmBatches)
892 || haveAlarmsTimeTickAlarm(mPendingWhileIdleAlarms);
893
894 if (oldCount != newCount) {
895 Slog.wtf(TAG, "Rebatching: total count changed from " + oldCount + " to " + newCount);
896 }
897 if (oldHasTick != newHasTick) {
898 Slog.wtf(TAG, "Rebatching: hasTick changed from " + oldHasTick + " to " + newHasTick);
899 }
900
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700901 rescheduleKernelAlarmsLocked();
902 updateNextAlarmClockLocked();
Suprabh Shukla75edab12018-01-29 14:09:06 -0800903 mStatLogger.logDurationStat(Stats.REBATCH_ALL_ALARMS, start);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700904 }
905
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800906 /**
907 * Re-orders the alarm batches based on newly evaluated send times based on the current
908 * app-standby buckets
909 * @param targetPackages [Package, User] pairs for which alarms need to be re-evaluated,
910 * null indicates all
911 * @return True if there was any reordering done to the current list.
912 */
913 boolean reorderAlarmsBasedOnStandbyBuckets(ArraySet<Pair<String, Integer>> targetPackages) {
914 final long start = mStatLogger.getTime();
915 final ArrayList<Alarm> rescheduledAlarms = new ArrayList<>();
916
917 for (int batchIndex = mAlarmBatches.size() - 1; batchIndex >= 0; batchIndex--) {
918 final Batch batch = mAlarmBatches.get(batchIndex);
919 for (int alarmIndex = batch.size() - 1; alarmIndex >= 0; alarmIndex--) {
920 final Alarm alarm = batch.get(alarmIndex);
921 final Pair<String, Integer> packageUser =
922 Pair.create(alarm.sourcePackage, UserHandle.getUserId(alarm.creatorUid));
923 if (targetPackages != null && !targetPackages.contains(packageUser)) {
924 continue;
925 }
926 if (adjustDeliveryTimeBasedOnStandbyBucketLocked(alarm)) {
927 batch.remove(alarm);
928 rescheduledAlarms.add(alarm);
929 }
930 }
931 if (batch.size() == 0) {
932 mAlarmBatches.remove(batchIndex);
933 }
934 }
935 for (int i = 0; i < rescheduledAlarms.size(); i++) {
936 final Alarm a = rescheduledAlarms.get(i);
937 insertAndBatchAlarmLocked(a);
938 }
939
940 mStatLogger.logDurationStat(Stats.REORDER_ALARMS_FOR_STANDBY, start);
941 return rescheduledAlarms.size() > 0;
942 }
943
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700944 void reAddAlarmLocked(Alarm a, long nowElapsed, boolean doValidate) {
945 a.when = a.origWhen;
946 long whenElapsed = convertToElapsed(a.when, a.type);
947 final long maxElapsed;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700948 if (a.windowLength == AlarmManager.WINDOW_EXACT) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700949 // Exact
950 maxElapsed = whenElapsed;
951 } else {
952 // Not exact. Preserve any explicit window, otherwise recalculate
953 // the window based on the alarm's new futurity. Note that this
954 // reflects a policy of preferring timely to deferred delivery.
955 maxElapsed = (a.windowLength > 0)
Christopher Tate22e919d2018-02-16 16:16:50 -0800956 ? clampPositive(whenElapsed + a.windowLength)
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700957 : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
958 }
959 a.whenElapsed = whenElapsed;
960 a.maxWhenElapsed = maxElapsed;
961 setImplLocked(a, true, doValidate);
962 }
963
Christopher Tate22e919d2018-02-16 16:16:50 -0800964 static long clampPositive(long val) {
965 return (val >= 0) ? val : Long.MAX_VALUE;
966 }
967
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700968 /**
969 * Sends alarms that were blocked due to user applied background restrictions - either because
970 * the user lifted those or the uid came to foreground.
971 *
972 * @param uid uid to filter on
973 * @param packageName package to filter on, or null for all packages in uid
974 */
975 void sendPendingBackgroundAlarmsLocked(int uid, String packageName) {
976 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(uid);
977 if (alarmsForUid == null || alarmsForUid.size() == 0) {
978 return;
979 }
980 final ArrayList<Alarm> alarmsToDeliver;
981 if (packageName != null) {
982 if (DEBUG_BG_LIMIT) {
983 Slog.d(TAG, "Sending blocked alarms for uid " + uid + ", package " + packageName);
984 }
985 alarmsToDeliver = new ArrayList<>();
986 for (int i = alarmsForUid.size() - 1; i >= 0; i--) {
987 final Alarm a = alarmsForUid.get(i);
988 if (a.matches(packageName)) {
989 alarmsToDeliver.add(alarmsForUid.remove(i));
990 }
991 }
992 if (alarmsForUid.size() == 0) {
993 mPendingBackgroundAlarms.remove(uid);
994 }
995 } else {
996 if (DEBUG_BG_LIMIT) {
997 Slog.d(TAG, "Sending blocked alarms for uid " + uid);
998 }
999 alarmsToDeliver = alarmsForUid;
1000 mPendingBackgroundAlarms.remove(uid);
1001 }
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001002 deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001003 }
1004
Makoto Onuki2206af32017-11-21 16:25:35 -08001005 /**
1006 * Check all alarms in {@link #mPendingBackgroundAlarms} and send the ones that are not
1007 * restricted.
1008 *
1009 * This is only called when the global "force all apps-standby" flag changes or when the
1010 * power save whitelist changes, so it's okay to be slow.
1011 */
1012 void sendAllUnrestrictedPendingBackgroundAlarmsLocked() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001013 final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
Makoto Onuki2206af32017-11-21 16:25:35 -08001014
1015 findAllUnrestrictedPendingBackgroundAlarmsLockedInner(
1016 mPendingBackgroundAlarms, alarmsToDeliver, this::isBackgroundRestricted);
1017
1018 if (alarmsToDeliver.size() > 0) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001019 deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
Makoto Onuki2206af32017-11-21 16:25:35 -08001020 }
1021 }
1022
1023 @VisibleForTesting
1024 static void findAllUnrestrictedPendingBackgroundAlarmsLockedInner(
1025 SparseArray<ArrayList<Alarm>> pendingAlarms, ArrayList<Alarm> unrestrictedAlarms,
1026 Predicate<Alarm> isBackgroundRestricted) {
1027
1028 for (int uidIndex = pendingAlarms.size() - 1; uidIndex >= 0; uidIndex--) {
1029 final int uid = pendingAlarms.keyAt(uidIndex);
1030 final ArrayList<Alarm> alarmsForUid = pendingAlarms.valueAt(uidIndex);
1031
1032 for (int alarmIndex = alarmsForUid.size() - 1; alarmIndex >= 0; alarmIndex--) {
1033 final Alarm alarm = alarmsForUid.get(alarmIndex);
1034
1035 if (isBackgroundRestricted.test(alarm)) {
1036 continue;
1037 }
1038
1039 unrestrictedAlarms.add(alarm);
1040 alarmsForUid.remove(alarmIndex);
1041 }
1042
1043 if (alarmsForUid.size() == 0) {
1044 pendingAlarms.removeAt(uidIndex);
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001045 }
1046 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001047 }
1048
1049 private void deliverPendingBackgroundAlarmsLocked(ArrayList<Alarm> alarms, long nowELAPSED) {
1050 final int N = alarms.size();
1051 boolean hasWakeup = false;
1052 for (int i = 0; i < N; i++) {
1053 final Alarm alarm = alarms.get(i);
1054 if (alarm.wakeup) {
1055 hasWakeup = true;
1056 }
1057 alarm.count = 1;
1058 // Recurring alarms may have passed several alarm intervals while the
1059 // alarm was kept pending. Send the appropriate trigger count.
1060 if (alarm.repeatInterval > 0) {
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001061 alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001062 // Also schedule its next recurrence
1063 final long delta = alarm.count * alarm.repeatInterval;
1064 final long nextElapsed = alarm.whenElapsed + delta;
1065 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
1066 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
1067 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
1068 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
1069 // Kernel alarms will be rescheduled as needed in setImplLocked
1070 }
1071 }
1072 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
1073 // No need to wakeup for non wakeup alarms
1074 if (mPendingNonWakeupAlarms.size() == 0) {
1075 mStartCurrentDelayTime = nowELAPSED;
1076 mNextNonWakeupDeliveryTime = nowELAPSED
1077 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
1078 }
1079 mPendingNonWakeupAlarms.addAll(alarms);
1080 mNumDelayedAlarms += alarms.size();
1081 } else {
1082 if (DEBUG_BG_LIMIT) {
1083 Slog.d(TAG, "Waking up to deliver pending blocked alarms");
1084 }
1085 // Since we are waking up, also deliver any pending non wakeup alarms we have.
1086 if (mPendingNonWakeupAlarms.size() > 0) {
1087 alarms.addAll(mPendingNonWakeupAlarms);
1088 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
1089 mTotalDelayTime += thisDelayTime;
1090 if (mMaxDelayTime < thisDelayTime) {
1091 mMaxDelayTime = thisDelayTime;
1092 }
1093 mPendingNonWakeupAlarms.clear();
1094 }
1095 calculateDeliveryPriorities(alarms);
1096 Collections.sort(alarms, mAlarmDispatchComparator);
1097 deliverAlarmsLocked(alarms, nowELAPSED);
1098 }
1099 }
1100
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001101 void restorePendingWhileIdleAlarmsLocked() {
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001102 if (RECORD_DEVICE_IDLE_ALARMS) {
1103 IdleDispatchEntry ent = new IdleDispatchEntry();
1104 ent.uid = 0;
1105 ent.pkg = "FINISH IDLE";
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001106 ent.elapsedRealtime = mInjector.getElapsedRealtime();
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001107 mAllowWhileIdleDispatches.add(ent);
1108 }
1109
Dianne Hackborn35d54032015-04-23 10:30:43 -07001110 // Bring pending alarms back into the main list.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001111 if (mPendingWhileIdleAlarms.size() > 0) {
1112 ArrayList<Alarm> alarms = mPendingWhileIdleAlarms;
1113 mPendingWhileIdleAlarms = new ArrayList<>();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001114 final long nowElapsed = mInjector.getElapsedRealtime();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001115 for (int i=alarms.size() - 1; i >= 0; i--) {
1116 Alarm a = alarms.get(i);
1117 reAddAlarmLocked(a, nowElapsed, false);
1118 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001119 }
Dianne Hackborn35d54032015-04-23 10:30:43 -07001120
1121 // Reschedule everything.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001122 rescheduleKernelAlarmsLocked();
1123 updateNextAlarmClockLocked();
Dianne Hackborn35d54032015-04-23 10:30:43 -07001124
Christopher Tatee0a22b32013-07-11 14:43:13 -07001125 }
1126
Christopher Tate14a7bb02015-10-01 10:24:31 -07001127 static final class InFlight {
Dianne Hackborn81038902012-11-26 17:04:09 -08001128 final PendingIntent mPendingIntent;
Christopher Tateeabba732017-08-17 17:12:52 -07001129 final long mWhenElapsed;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001130 final IBinder mListener;
David Christieebe51fc2013-07-26 13:23:29 -07001131 final WorkSource mWorkSource;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001132 final int mUid;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001133 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001134 final BroadcastStats mBroadcastStats;
1135 final FilterStats mFilterStats;
Dianne Hackborne5167ca2014-03-08 14:39:10 -08001136 final int mAlarmType;
Dianne Hackborn81038902012-11-26 17:04:09 -08001137
Christopher Tate14a7bb02015-10-01 10:24:31 -07001138 InFlight(AlarmManagerService service, PendingIntent pendingIntent, IAlarmListener listener,
1139 WorkSource workSource, int uid, String alarmPkg, int alarmType, String tag,
1140 long nowELAPSED) {
Dianne Hackborn81038902012-11-26 17:04:09 -08001141 mPendingIntent = pendingIntent;
Christopher Tateeabba732017-08-17 17:12:52 -07001142 mWhenElapsed = nowELAPSED;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001143 mListener = listener != null ? listener.asBinder() : null;
David Christieebe51fc2013-07-26 13:23:29 -07001144 mWorkSource = workSource;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001145 mUid = uid;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001146 mTag = tag;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001147 mBroadcastStats = (pendingIntent != null)
1148 ? service.getStatsLocked(pendingIntent)
1149 : service.getStatsLocked(uid, alarmPkg);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001150 FilterStats fs = mBroadcastStats.filterStats.get(mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08001151 if (fs == null) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001152 fs = new FilterStats(mBroadcastStats, mTag);
1153 mBroadcastStats.filterStats.put(mTag, fs);
Dianne Hackborn81038902012-11-26 17:04:09 -08001154 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001155 fs.lastTime = nowELAPSED;
Dianne Hackborn81038902012-11-26 17:04:09 -08001156 mFilterStats = fs;
Dianne Hackborne5167ca2014-03-08 14:39:10 -08001157 mAlarmType = alarmType;
Dianne Hackborn81038902012-11-26 17:04:09 -08001158 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001159
1160 @Override
1161 public String toString() {
1162 return "InFlight{"
1163 + "pendingIntent=" + mPendingIntent
Christopher Tateeabba732017-08-17 17:12:52 -07001164 + ", when=" + mWhenElapsed
Makoto Onuki33955e12017-03-01 18:11:00 -08001165 + ", workSource=" + mWorkSource
1166 + ", uid=" + mUid
1167 + ", tag=" + mTag
1168 + ", broadcastStats=" + mBroadcastStats
1169 + ", filterStats=" + mFilterStats
1170 + ", alarmType=" + mAlarmType
1171 + "}";
1172 }
Kweku Adams61e03292017-10-19 14:27:12 -07001173
1174 public void writeToProto(ProtoOutputStream proto, long fieldId) {
1175 final long token = proto.start(fieldId);
1176
1177 proto.write(InFlightProto.UID, mUid);
1178 proto.write(InFlightProto.TAG, mTag);
1179 proto.write(InFlightProto.WHEN_ELAPSED_MS, mWhenElapsed);
1180 proto.write(InFlightProto.ALARM_TYPE, mAlarmType);
1181 if (mPendingIntent != null) {
1182 mPendingIntent.writeToProto(proto, InFlightProto.PENDING_INTENT);
1183 }
1184 if (mBroadcastStats != null) {
1185 mBroadcastStats.writeToProto(proto, InFlightProto.BROADCAST_STATS);
1186 }
1187 if (mFilterStats != null) {
1188 mFilterStats.writeToProto(proto, InFlightProto.FILTER_STATS);
1189 }
1190 if (mWorkSource != null) {
1191 mWorkSource.writeToProto(proto, InFlightProto.WORK_SOURCE);
1192 }
1193
1194 proto.end(token);
1195 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001197
Adam Lesinski182f73f2013-12-05 16:48:06 -08001198 static final class FilterStats {
Dianne Hackborn81038902012-11-26 17:04:09 -08001199 final BroadcastStats mBroadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001200 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001201
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001202 long lastTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 long aggregateTime;
Dianne Hackborn81038902012-11-26 17:04:09 -08001204 int count;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 int numWakeup;
1206 long startTime;
1207 int nesting;
Dianne Hackborn81038902012-11-26 17:04:09 -08001208
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001209 FilterStats(BroadcastStats broadcastStats, String tag) {
Dianne Hackborn81038902012-11-26 17:04:09 -08001210 mBroadcastStats = broadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001211 mTag = tag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001212 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001213
1214 @Override
1215 public String toString() {
1216 return "FilterStats{"
1217 + "tag=" + mTag
1218 + ", lastTime=" + lastTime
1219 + ", aggregateTime=" + aggregateTime
1220 + ", count=" + count
1221 + ", numWakeup=" + numWakeup
1222 + ", startTime=" + startTime
1223 + ", nesting=" + nesting
1224 + "}";
1225 }
Kweku Adams61e03292017-10-19 14:27:12 -07001226
1227 public void writeToProto(ProtoOutputStream proto, long fieldId) {
1228 final long token = proto.start(fieldId);
1229
1230 proto.write(FilterStatsProto.TAG, mTag);
1231 proto.write(FilterStatsProto.LAST_FLIGHT_TIME_REALTIME, lastTime);
1232 proto.write(FilterStatsProto.TOTAL_FLIGHT_DURATION_MS, aggregateTime);
1233 proto.write(FilterStatsProto.COUNT, count);
1234 proto.write(FilterStatsProto.WAKEUP_COUNT, numWakeup);
1235 proto.write(FilterStatsProto.START_TIME_REALTIME, startTime);
1236 proto.write(FilterStatsProto.NESTING, nesting);
1237
1238 proto.end(token);
1239 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001240 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001241
Adam Lesinski182f73f2013-12-05 16:48:06 -08001242 static final class BroadcastStats {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001243 final int mUid;
Dianne Hackborn81038902012-11-26 17:04:09 -08001244 final String mPackageName;
1245
1246 long aggregateTime;
1247 int count;
1248 int numWakeup;
1249 long startTime;
1250 int nesting;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001251 final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
Dianne Hackborn81038902012-11-26 17:04:09 -08001252
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001253 BroadcastStats(int uid, String packageName) {
1254 mUid = uid;
Dianne Hackborn81038902012-11-26 17:04:09 -08001255 mPackageName = packageName;
1256 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001257
1258 @Override
1259 public String toString() {
1260 return "BroadcastStats{"
1261 + "uid=" + mUid
1262 + ", packageName=" + mPackageName
1263 + ", aggregateTime=" + aggregateTime
1264 + ", count=" + count
1265 + ", numWakeup=" + numWakeup
1266 + ", startTime=" + startTime
1267 + ", nesting=" + nesting
1268 + "}";
1269 }
Kweku Adams61e03292017-10-19 14:27:12 -07001270
1271 public void writeToProto(ProtoOutputStream proto, long fieldId) {
1272 final long token = proto.start(fieldId);
1273
1274 proto.write(BroadcastStatsProto.UID, mUid);
1275 proto.write(BroadcastStatsProto.PACKAGE_NAME, mPackageName);
1276 proto.write(BroadcastStatsProto.TOTAL_FLIGHT_DURATION_MS, aggregateTime);
1277 proto.write(BroadcastStatsProto.COUNT, count);
1278 proto.write(BroadcastStatsProto.WAKEUP_COUNT, numWakeup);
1279 proto.write(BroadcastStatsProto.START_TIME_REALTIME, startTime);
1280 proto.write(BroadcastStatsProto.NESTING, nesting);
1281
1282 proto.end(token);
1283 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001285
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001286 final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
1287 = new SparseArray<ArrayMap<String, BroadcastStats>>();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001288
1289 int mNumDelayedAlarms = 0;
1290 long mTotalDelayTime = 0;
1291 long mMaxDelayTime = 0;
1292
Adam Lesinski182f73f2013-12-05 16:48:06 -08001293 @Override
1294 public void onStart() {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001295 mInjector.init();
Robert CH Chou64ba8e42009-11-04 21:38:49 +08001296
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001297 synchronized (mLock) {
Suprabh Shukla12bd0162018-11-12 18:00:18 -08001298 mHandler = new AlarmHandler();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001299 mConstants = new Constants(mHandler);
Robert CH Chou64ba8e42009-11-04 21:38:49 +08001300
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001301 mNextWakeup = mNextNonWakeup = 0;
1302
1303 // We have to set current TimeZone info to kernel
1304 // because kernel doesn't keep this after reboot
1305 setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
1306
1307 // Also sure that we're booting with a halfway sensible current time
Christopher Tate247571462017-04-10 11:45:05 -07001308 final long systemBuildTime = Environment.getRootDirectory().lastModified();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001309 if (mInjector.getCurrentTimeMillis() < systemBuildTime) {
1310 Slog.i(TAG, "Current time only " + mInjector.getCurrentTimeMillis()
Christopher Tate247571462017-04-10 11:45:05 -07001311 + ", advancing to build time " + systemBuildTime);
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001312 mInjector.setKernelTime(systemBuildTime);
Christopher Tate247571462017-04-10 11:45:05 -07001313 }
Christopher Tate247571462017-04-10 11:45:05 -07001314
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001315 // Determine SysUI's uid
1316 mSystemUiUid = mInjector.getSystemUiUid();
1317 if (mSystemUiUid <= 0) {
1318 Slog.wtf(TAG, "SysUI package not found!");
1319 }
1320 mWakeLock = mInjector.getAlarmWakeLock();
1321
Christopher Tatec8b7f432018-09-28 16:23:10 -07001322 mTimeTickIntent = new Intent(Intent.ACTION_TIME_TICK).addFlags(
1323 Intent.FLAG_RECEIVER_REGISTERED_ONLY
1324 | Intent.FLAG_RECEIVER_FOREGROUND
1325 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
1326
1327 mTimeTickTrigger = new IAlarmListener.Stub() {
1328 @Override
1329 public void doAlarm(final IAlarmCompleteListener callback) throws RemoteException {
1330 if (DEBUG_BATCH) {
1331 Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
1332 }
1333
1334 // Via handler because dispatch invokes this within its lock. OnAlarmListener
1335 // takes care of this automatically, but we're using the direct internal
1336 // interface here rather than that client-side wrapper infrastructure.
1337 mHandler.post(() -> {
1338 getContext().sendBroadcastAsUser(mTimeTickIntent, UserHandle.ALL);
1339
1340 try {
1341 callback.alarmComplete(this);
1342 } catch (RemoteException e) { /* local method call */ }
1343 });
1344
1345 synchronized (mLock) {
1346 mLastTickReceived = mInjector.getCurrentTimeMillis();
1347 }
1348 mClockReceiver.scheduleTimeTickEvent();
1349 }
1350 };
1351
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001352 Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
1353 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
1354 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
1355 mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
1356 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
1357
1358 mClockReceiver = mInjector.getClockReceiver(this);
1359 new InteractiveStateReceiver();
1360 new UninstallReceiver();
1361
1362 if (mInjector.isAlarmDriverPresent()) {
1363 AlarmThread waitThread = new AlarmThread();
1364 waitThread.start();
Christopher Tatebb9cce52017-04-18 14:19:43 -07001365 } else {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001366 Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
Christopher Tatebb9cce52017-04-18 14:19:43 -07001367 }
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001368
1369 try {
1370 ActivityManager.getService().registerUidObserver(new UidObserver(),
1371 ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
1372 | ActivityManager.UID_OBSERVER_ACTIVE,
1373 ActivityManager.PROCESS_STATE_UNKNOWN, null);
1374 } catch (RemoteException e) {
1375 // ignored; both services live in system_server
1376 }
Christopher Tatebb9cce52017-04-18 14:19:43 -07001377 }
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001378 publishLocalService(AlarmManagerInternal.class, new LocalService());
Adam Lesinski182f73f2013-12-05 16:48:06 -08001379 publishBinderService(Context.ALARM_SERVICE, mService);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001381
1382 @Override
Dianne Hackborna750a632015-06-16 17:18:23 -07001383 public void onBootPhase(int phase) {
1384 if (phase == PHASE_SYSTEM_SERVICES_READY) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001385 synchronized (mLock) {
1386 mConstants.start(getContext().getContentResolver());
1387 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
1388 mLocalDeviceIdleController =
1389 LocalServices.getService(DeviceIdleController.LocalService.class);
1390 mUsageStatsManagerInternal =
1391 LocalServices.getService(UsageStatsManagerInternal.class);
1392 mUsageStatsManagerInternal.addAppIdleStateChangeListener(new AppStandbyTracker());
Makoto Onukie4918212018-02-06 11:30:15 -08001393
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001394 mAppStateTracker = LocalServices.getService(AppStateTracker.class);
1395 mAppStateTracker.addListener(mForceAppStandbyListener);
1396
1397 mClockReceiver.scheduleTimeTickEvent();
1398 mClockReceiver.scheduleDateChangedEvent();
1399 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001400 }
1401 }
1402
1403 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 protected void finalize() throws Throwable {
1405 try {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001406 mInjector.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 } finally {
1408 super.finalize();
1409 }
1410 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001411
mswest463f4c99d2018-02-01 10:13:10 -08001412 boolean setTimeImpl(long millis) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001413 if (!mInjector.isAlarmDriverPresent()) {
mswest463f4c99d2018-02-01 10:13:10 -08001414 Slog.w(TAG, "Not setting time since no alarm driver is available.");
1415 return false;
1416 }
1417
1418 synchronized (mLock) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001419 final long currentTimeMillis = mInjector.getCurrentTimeMillis();
1420 mInjector.setKernelTime(millis);
Christine Hallstromf5d585a2018-05-21 14:27:23 -07001421 final TimeZone timeZone = TimeZone.getDefault();
1422 final int currentTzOffset = timeZone.getOffset(currentTimeMillis);
1423 final int newTzOffset = timeZone.getOffset(millis);
1424 if (currentTzOffset != newTzOffset) {
1425 Slog.i(TAG, "Timezone offset has changed, updating kernel timezone");
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001426 mInjector.setKernelTimezone(-(newTzOffset / 60000));
Christine Hallstromf5d585a2018-05-21 14:27:23 -07001427 }
1428 // The native implementation of setKernelTime can return -1 even when the kernel
1429 // time was set correctly, so assume setting kernel time was successful and always
1430 // return true.
1431 return true;
mswest463f4c99d2018-02-01 10:13:10 -08001432 }
1433 }
1434
Adam Lesinski182f73f2013-12-05 16:48:06 -08001435 void setTimeZoneImpl(String tz) {
1436 if (TextUtils.isEmpty(tz)) {
1437 return;
David Christieebe51fc2013-07-26 13:23:29 -07001438 }
1439
Adam Lesinski182f73f2013-12-05 16:48:06 -08001440 TimeZone zone = TimeZone.getTimeZone(tz);
1441 // Prevent reentrant calls from stepping on each other when writing
1442 // the time zone property
1443 boolean timeZoneWasChanged = false;
1444 synchronized (this) {
1445 String current = SystemProperties.get(TIMEZONE_PROPERTY);
1446 if (current == null || !current.equals(zone.getID())) {
1447 if (localLOGV) {
1448 Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
1449 }
1450 timeZoneWasChanged = true;
1451 SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
1452 }
1453
1454 // Update the kernel timezone information
1455 // Kernel tracks time offsets as 'minutes west of GMT'
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001456 int gmtOffset = zone.getOffset(mInjector.getCurrentTimeMillis());
1457 mInjector.setKernelTimezone(-(gmtOffset / 60000));
Adam Lesinski182f73f2013-12-05 16:48:06 -08001458 }
1459
1460 TimeZone.setDefault(null);
1461
1462 if (timeZoneWasChanged) {
Christopher Tatea4618b02018-10-11 16:22:55 -07001463 // Don't wait for broadcasts to update our midnight alarm
1464 mClockReceiver.scheduleDateChangedEvent();
1465
1466 // And now let everyone else know
Adam Lesinski182f73f2013-12-05 16:48:06 -08001467 Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
Chad Brubaker291df4f2017-03-14 10:23:02 -07001468 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
Christopher Tate5cdf9f82017-05-03 18:10:39 -07001469 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
Chad Brubaker291df4f2017-03-14 10:23:02 -07001470 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001471 intent.putExtra("time-zone", zone.getID());
1472 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
1473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001475
Christopher Tatec8b7f432018-09-28 16:23:10 -07001476 void removeImpl(PendingIntent operation, IAlarmListener listener) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001477 synchronized (mLock) {
Christopher Tatec8b7f432018-09-28 16:23:10 -07001478 removeLocked(operation, listener);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001479 }
1480 }
1481
1482 void setImpl(int type, long triggerAtTime, long windowLength, long interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001483 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1484 int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
1485 int callingUid, String callingPackage) {
1486 // must be *either* PendingIntent or AlarmReceiver, but not both
1487 if ((operation == null && directReceiver == null)
1488 || (operation != null && directReceiver != null)) {
1489 Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver");
1490 // NB: previous releases failed silently here, so we are continuing to do the same
1491 // rather than throw an IllegalArgumentException.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 return;
1493 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001494
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001495 // Sanity check the window length. This will catch people mistakenly
1496 // trying to pass an end-of-window timestamp rather than a duration.
1497 if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
1498 Slog.w(TAG, "Window length " + windowLength
1499 + "ms suspiciously long; limiting to 1 hour");
1500 windowLength = AlarmManager.INTERVAL_HOUR;
1501 }
1502
Christopher Tate498c6cb2014-11-17 16:09:27 -08001503 // Sanity check the recurrence interval. This will catch people who supply
Christopher Tate22e919d2018-02-16 16:16:50 -08001504 // seconds when the API expects milliseconds, or apps trying shenanigans
1505 // around intentional period overflow, etc.
Dianne Hackborna750a632015-06-16 17:18:23 -07001506 final long minInterval = mConstants.MIN_INTERVAL;
1507 if (interval > 0 && interval < minInterval) {
Christopher Tate498c6cb2014-11-17 16:09:27 -08001508 Slog.w(TAG, "Suspiciously short interval " + interval
Dianne Hackborna750a632015-06-16 17:18:23 -07001509 + " millis; expanding to " + (minInterval/1000)
Christopher Tate498c6cb2014-11-17 16:09:27 -08001510 + " seconds");
Dianne Hackborna750a632015-06-16 17:18:23 -07001511 interval = minInterval;
Christopher Tate22e919d2018-02-16 16:16:50 -08001512 } else if (interval > mConstants.MAX_INTERVAL) {
1513 Slog.w(TAG, "Suspiciously long interval " + interval
1514 + " millis; clamping");
1515 interval = mConstants.MAX_INTERVAL;
Christopher Tate498c6cb2014-11-17 16:09:27 -08001516 }
1517
Christopher Tatee0a22b32013-07-11 14:43:13 -07001518 if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
1519 throw new IllegalArgumentException("Invalid alarm type " + type);
1520 }
1521
Christopher Tate5f221e82013-07-30 17:13:15 -07001522 if (triggerAtTime < 0) {
Christopher Tate5f221e82013-07-30 17:13:15 -07001523 final long what = Binder.getCallingPid();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001524 Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
Christopher Tate5f221e82013-07-30 17:13:15 -07001525 + " pid=" + what);
1526 triggerAtTime = 0;
1527 }
1528
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001529 final long nowElapsed = mInjector.getElapsedRealtime();
Christopher Tate498c6cb2014-11-17 16:09:27 -08001530 final long nominalTrigger = convertToElapsed(triggerAtTime, type);
1531 // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
Dianne Hackborna750a632015-06-16 17:18:23 -07001532 final long minTrigger = nowElapsed + mConstants.MIN_FUTURITY;
Christopher Tate498c6cb2014-11-17 16:09:27 -08001533 final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
1534
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001535 final long maxElapsed;
1536 if (windowLength == AlarmManager.WINDOW_EXACT) {
1537 maxElapsed = triggerElapsed;
1538 } else if (windowLength < 0) {
1539 maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001540 // Fix this window in place, so that as time approaches we don't collapse it.
1541 windowLength = maxElapsed - triggerElapsed;
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001542 } else {
1543 maxElapsed = triggerElapsed + windowLength;
1544 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 synchronized (mLock) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07001547 if (DEBUG_BATCH) {
1548 Slog.v(TAG, "set(" + operation + ") : type=" + type
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001549 + " triggerAtTime=" + triggerAtTime + " win=" + windowLength
Christopher Tatee0a22b32013-07-11 14:43:13 -07001550 + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001551 + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 }
Christopher Tate3e04b472013-10-21 17:51:31 -07001553 setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001554 interval, operation, directReceiver, listenerTag, flags, true, workSource,
1555 alarmClock, callingUid, callingPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 }
1557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558
Christopher Tate3e04b472013-10-21 17:51:31 -07001559 private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001560 long maxWhen, long interval, PendingIntent operation, IAlarmListener directReceiver,
1561 String listenerTag, int flags, boolean doValidate, WorkSource workSource,
1562 AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) {
Christopher Tate3e04b472013-10-21 17:51:31 -07001563 Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001564 operation, directReceiver, listenerTag, workSource, flags, alarmClock,
1565 callingUid, callingPackage);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001566 try {
Dianne Hackbornc3af19a2017-01-20 17:00:44 -08001567 if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001568 Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
1569 + " -- package not allowed to start");
1570 return;
1571 }
1572 } catch (RemoteException e) {
1573 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07001574 removeLocked(operation, directReceiver);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001575 setImplLocked(a, false, doValidate);
1576 }
Christopher Tateb8849c12011-02-08 13:39:01 -08001577
Christopher Tatef2159712018-03-27 16:04:14 -07001578 /**
1579 * Return the minimum time that should elapse before an app in the specified bucket
1580 * can receive alarms again
1581 */
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001582 @VisibleForTesting
1583 long getMinDelayForBucketLocked(int bucket) {
Christopher Tatef2159712018-03-27 16:04:14 -07001584 // UsageStats bucket values are treated as floors of their behavioral range.
1585 // In other words, a bucket value between WORKING and ACTIVE is treated as
1586 // WORKING, not as ACTIVE. The ACTIVE and NEVER bucket apply only at specific
1587 // values.
1588 final int index;
1589
1590 if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) index = NEVER_INDEX;
1591 else if (bucket > UsageStatsManager.STANDBY_BUCKET_FREQUENT) index = RARE_INDEX;
1592 else if (bucket > UsageStatsManager.STANDBY_BUCKET_WORKING_SET) index = FREQUENT_INDEX;
1593 else if (bucket > UsageStatsManager.STANDBY_BUCKET_ACTIVE) index = WORKING_INDEX;
1594 else index = ACTIVE_INDEX;
1595
1596 return mConstants.APP_STANDBY_MIN_DELAYS[index];
Suprabh Shukla75edab12018-01-29 14:09:06 -08001597 }
1598
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001599 /**
1600 * Adjusts the alarm delivery time based on the current app standby bucket.
1601 * @param alarm The alarm to adjust
1602 * @return true if the alarm delivery time was updated.
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001603 */
1604 private boolean adjustDeliveryTimeBasedOnStandbyBucketLocked(Alarm alarm) {
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001605 if (isExemptFromAppStandby(alarm)) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001606 return false;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001607 }
1608 if (mAppStandbyParole) {
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001609 if (alarm.whenElapsed > alarm.expectedWhenElapsed) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001610 // We did defer this alarm earlier, restore original requirements
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001611 alarm.whenElapsed = alarm.expectedWhenElapsed;
1612 alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
1613 return true;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001614 }
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001615 return false;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001616 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001617 final long oldWhenElapsed = alarm.whenElapsed;
1618 final long oldMaxWhenElapsed = alarm.maxWhenElapsed;
1619
Suprabh Shukla75edab12018-01-29 14:09:06 -08001620 final String sourcePackage = alarm.sourcePackage;
1621 final int sourceUserId = UserHandle.getUserId(alarm.creatorUid);
1622 final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket(
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001623 sourcePackage, sourceUserId, mInjector.getElapsedRealtime());
Suprabh Shukla75edab12018-01-29 14:09:06 -08001624
1625 final Pair<String, Integer> packageUser = Pair.create(sourcePackage, sourceUserId);
1626 final long lastElapsed = mLastAlarmDeliveredForPackage.getOrDefault(packageUser, 0L);
1627 if (lastElapsed > 0) {
1628 final long minElapsed = lastElapsed + getMinDelayForBucketLocked(standbyBucket);
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001629 if (alarm.expectedWhenElapsed < minElapsed) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08001630 alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001631 } else {
1632 // app is now eligible to run alarms at the originally requested window.
1633 // Restore original requirements in case they were changed earlier.
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001634 alarm.whenElapsed = alarm.expectedWhenElapsed;
1635 alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001636 }
1637 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001638 return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed);
Suprabh Shukla75edab12018-01-29 14:09:06 -08001639 }
1640
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001641 private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
1642 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001643 // This is a special alarm that will put the system into idle until it goes off.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001644 // The caller has given the time they want this to happen at, however we need
1645 // to pull that earlier if there are existing alarms that have requested to
Dianne Hackbornf3831292015-10-15 14:51:06 -07001646 // bring us out of idle at an earlier time.
1647 if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001648 a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001649 }
1650 // Add fuzz to make the alarm go off some time before the actual desired time.
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001651 final long nowElapsed = mInjector.getElapsedRealtime();
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001652 final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001653 if (fuzz > 0) {
1654 if (mRandom == null) {
1655 mRandom = new Random();
1656 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001657 final int delta = mRandom.nextInt(fuzz);
1658 a.whenElapsed -= delta;
1659 if (false) {
1660 Slog.d(TAG, "Alarm when: " + a.whenElapsed);
1661 Slog.d(TAG, "Delta until alarm: " + (a.whenElapsed-nowElapsed));
1662 Slog.d(TAG, "Applied fuzz: " + fuzz);
1663 Slog.d(TAG, "Final delta: " + delta);
1664 Slog.d(TAG, "Final when: " + a.whenElapsed);
1665 }
1666 a.when = a.maxWhenElapsed = a.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001667 }
1668
1669 } else if (mPendingIdleUntil != null) {
1670 // We currently have an idle until alarm scheduled; if the new alarm has
1671 // not explicitly stated it wants to run while idle, then put it on hold.
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001672 if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
1673 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
1674 | AlarmManager.FLAG_WAKE_FROM_IDLE))
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001675 == 0) {
1676 mPendingWhileIdleAlarms.add(a);
1677 return;
1678 }
1679 }
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001680 if (RECORD_DEVICE_IDLE_ALARMS) {
1681 if ((a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
1682 IdleDispatchEntry ent = new IdleDispatchEntry();
1683 ent.uid = a.uid;
1684 ent.pkg = a.operation.getCreatorPackage();
1685 ent.tag = a.operation.getTag("");
1686 ent.op = "SET";
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001687 ent.elapsedRealtime = mInjector.getElapsedRealtime();
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001688 ent.argRealtime = a.whenElapsed;
1689 mAllowWhileIdleDispatches.add(ent);
1690 }
1691 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08001692 adjustDeliveryTimeBasedOnStandbyBucketLocked(a);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001693 insertAndBatchAlarmLocked(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001695 if (a.alarmClock != null) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001696 mNextAlarmClockMayChange = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +02001697 }
1698
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001699 boolean needRebatch = false;
1700
1701 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001702 if (RECORD_DEVICE_IDLE_ALARMS) {
1703 if (mPendingIdleUntil == null) {
1704 IdleDispatchEntry ent = new IdleDispatchEntry();
1705 ent.uid = 0;
1706 ent.pkg = "START IDLE";
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001707 ent.elapsedRealtime = mInjector.getElapsedRealtime();
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001708 mAllowWhileIdleDispatches.add(ent);
1709 }
1710 }
Makoto Onuki4274a6d2017-04-21 12:21:25 -07001711 if ((mPendingIdleUntil != a) && (mPendingIdleUntil != null)) {
1712 Slog.wtfStack(TAG, "setImplLocked: idle until changed from " + mPendingIdleUntil
1713 + " to " + a);
1714 }
1715
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001716 mPendingIdleUntil = a;
1717 needRebatch = true;
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001718 } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
1719 if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
1720 mNextWakeFromIdle = a;
1721 // If this wake from idle is earlier than whatever was previously scheduled,
1722 // and we are currently idling, then we need to rebatch alarms in case the idle
1723 // until time needs to be updated.
1724 if (mPendingIdleUntil != null) {
1725 needRebatch = true;
1726 }
1727 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001728 }
1729
1730 if (!rebatching) {
1731 if (DEBUG_VALIDATE) {
1732 if (doValidate && !validateConsistencyLocked()) {
1733 Slog.v(TAG, "Tipping-point operation: type=" + a.type + " when=" + a.when
1734 + " when(hex)=" + Long.toHexString(a.when)
1735 + " whenElapsed=" + a.whenElapsed
1736 + " maxWhenElapsed=" + a.maxWhenElapsed
1737 + " interval=" + a.repeatInterval + " op=" + a.operation
1738 + " flags=0x" + Integer.toHexString(a.flags));
1739 rebatchAllAlarmsLocked(false);
1740 needRebatch = false;
1741 }
1742 }
1743
1744 if (needRebatch) {
Christopher Tate4cb338d2013-07-26 13:11:31 -07001745 rebatchAllAlarmsLocked(false);
Christopher Tate4cb338d2013-07-26 13:11:31 -07001746 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001747
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001748 rescheduleKernelAlarmsLocked();
1749 updateNextAlarmClockLocked();
1750 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001751 }
1752
Christopher Tate1d99c392017-12-07 16:54:04 -08001753 /**
1754 * System-process internal API
1755 */
1756 private final class LocalService implements AlarmManagerInternal {
1757 @Override
1758 public void removeAlarmsForUid(int uid) {
1759 synchronized (mLock) {
1760 removeLocked(uid);
1761 }
1762 }
1763 }
1764
1765 /**
1766 * Public-facing binder interface
1767 */
Adam Lesinski182f73f2013-12-05 16:48:06 -08001768 private final IBinder mService = new IAlarmManager.Stub() {
1769 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07001770 public void set(String callingPackage,
1771 int type, long triggerAtTime, long windowLength, long interval, int flags,
1772 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1773 WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001774 final int callingUid = Binder.getCallingUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07001775
1776 // make sure the caller is not lying about which package should be blamed for
1777 // wakelock time spent in alarm delivery
1778 mAppOps.checkPackage(callingUid, callingPackage);
1779
1780 // Repeating alarms must use PendingIntent, not direct listener
1781 if (interval != 0) {
1782 if (directReceiver != null) {
1783 throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers");
1784 }
1785 }
1786
Adam Lesinski182f73f2013-12-05 16:48:06 -08001787 if (workSource != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001788 getContext().enforcePermission(
Adam Lesinski182f73f2013-12-05 16:48:06 -08001789 android.Manifest.permission.UPDATE_DEVICE_STATS,
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001790 Binder.getCallingPid(), callingUid, "AlarmManager.set");
Christopher Tate89779822012-08-31 14:40:03 -07001791 }
1792
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001793 // No incoming callers can request either WAKE_FROM_IDLE or
1794 // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
1795 flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
1796 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
1797
1798 // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
1799 // manager when to come out of idle mode, which is only for DeviceIdleController.
1800 if (callingUid != Process.SYSTEM_UID) {
1801 flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
1802 }
1803
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001804 // If this is an exact time alarm, then it can't be batched with other alarms.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001805 if (windowLength == AlarmManager.WINDOW_EXACT) {
1806 flags |= AlarmManager.FLAG_STANDALONE;
1807 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001808
1809 // If this alarm is for an alarm clock, then it must be standalone and we will
1810 // use it to wake early from idle if needed.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001811 if (alarmClock != null) {
1812 flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001813
1814 // If the caller is a core system component or on the user's whitelist, and not calling
1815 // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
1816 // This means we will allow these alarms to go off as normal even while idle, with no
1817 // timing restrictions.
1818 } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001819 || UserHandle.isSameApp(callingUid, mSystemUiUid)
Makoto Onukie4918212018-02-06 11:30:15 -08001820 || ((mAppStateTracker != null)
Suprabh Shukla5bf49812018-05-24 18:38:50 -07001821 && mAppStateTracker.isUidPowerSaveUserWhitelisted(callingUid)))) {
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08001822 flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
1823 flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001824 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001825
Christopher Tate14a7bb02015-10-01 10:24:31 -07001826 setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
1827 listenerTag, flags, workSource, alarmClock, callingUid, callingPackage);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001828 }
Christopher Tate89779822012-08-31 14:40:03 -07001829
Adam Lesinski182f73f2013-12-05 16:48:06 -08001830 @Override
Greg Hackmann0cab8962014-02-21 16:35:52 -08001831 public boolean setTime(long millis) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001832 getContext().enforceCallingOrSelfPermission(
1833 "android.permission.SET_TIME",
1834 "setTime");
1835
mswest463f4c99d2018-02-01 10:13:10 -08001836 return setTimeImpl(millis);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001838
1839 @Override
1840 public void setTimeZone(String tz) {
1841 getContext().enforceCallingOrSelfPermission(
1842 "android.permission.SET_TIME_ZONE",
1843 "setTimeZone");
1844
1845 final long oldId = Binder.clearCallingIdentity();
1846 try {
1847 setTimeZoneImpl(tz);
1848 } finally {
1849 Binder.restoreCallingIdentity(oldId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 }
1851 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001852
Adam Lesinski182f73f2013-12-05 16:48:06 -08001853 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07001854 public void remove(PendingIntent operation, IAlarmListener listener) {
1855 if (operation == null && listener == null) {
1856 Slog.w(TAG, "remove() with no intent or listener");
1857 return;
1858 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001859
Christopher Tate14a7bb02015-10-01 10:24:31 -07001860 synchronized (mLock) {
1861 removeLocked(operation, listener);
1862 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07001864
Adam Lesinski182f73f2013-12-05 16:48:06 -08001865 @Override
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001866 public long getNextWakeFromIdleTime() {
1867 return getNextWakeFromIdleTimeImpl();
1868 }
1869
1870 @Override
Jose Lima235510e2014-08-13 12:50:01 -07001871 public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02001872 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1873 Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */,
1874 "getNextAlarmClock", null);
1875
1876 return getNextAlarmClockImpl(userId);
1877 }
1878
1879 @Override
Jeff Sharkey9911a282018-02-14 22:29:11 -07001880 public long currentNetworkTimeMillis() {
1881 final NtpTrustedTime time = NtpTrustedTime.getInstance(getContext());
1882 if (time.hasCache()) {
1883 return time.currentTimeMillis();
1884 } else {
1885 throw new ParcelableException(new DateTimeException("Missing NTP fix"));
1886 }
1887 }
1888
1889 @Override
Adam Lesinski182f73f2013-12-05 16:48:06 -08001890 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -06001891 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
Kweku Adams61e03292017-10-19 14:27:12 -07001892
1893 if (args.length > 0 && "--proto".equals(args[0])) {
1894 dumpProto(fd);
1895 } else {
1896 dumpImpl(pw);
1897 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07001898 }
mswest463f4c99d2018-02-01 10:13:10 -08001899
1900 @Override
1901 public void onShellCommand(FileDescriptor in, FileDescriptor out,
1902 FileDescriptor err, String[] args, ShellCallback callback,
1903 ResultReceiver resultReceiver) {
1904 (new ShellCmd()).exec(this, in, out, err, args, callback, resultReceiver);
1905 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001906 };
Christopher Tate4cb338d2013-07-26 13:11:31 -07001907
Adam Lesinski182f73f2013-12-05 16:48:06 -08001908 void dumpImpl(PrintWriter pw) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909 synchronized (mLock) {
1910 pw.println("Current Alarm Manager state:");
Dianne Hackborna750a632015-06-16 17:18:23 -07001911 mConstants.dump(pw);
1912 pw.println();
1913
Makoto Onukie4918212018-02-06 11:30:15 -08001914 if (mAppStateTracker != null) {
1915 mAppStateTracker.dump(pw, " ");
1916 pw.println();
1917 }
Makoto Onuki2206af32017-11-21 16:25:35 -08001918
Suprabh Shukla75edab12018-01-29 14:09:06 -08001919 pw.println(" App Standby Parole: " + mAppStandbyParole);
1920 pw.println();
1921
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001922 final long nowELAPSED = mInjector.getElapsedRealtime();
Makoto Onukie8edbcf2018-03-02 16:49:29 -08001923 final long nowUPTIME = SystemClock.uptimeMillis();
Christopher Tatec8b7f432018-09-28 16:23:10 -07001924 final long nowRTC = mInjector.getCurrentTimeMillis();
Makoto Onuki5d93b832018-01-10 16:12:39 -08001925 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Christopher Tatee0a22b32013-07-11 14:43:13 -07001926
Dianne Hackborna750a632015-06-16 17:18:23 -07001927 pw.print(" nowRTC="); pw.print(nowRTC);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001928 pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
Christopher Tate7f2a0352015-12-08 10:24:33 -08001929 pw.print(" nowELAPSED="); pw.print(nowELAPSED);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001930 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07001931 pw.print(" mLastTimeChangeClockTime="); pw.print(mLastTimeChangeClockTime);
Dianne Hackbornc3527222015-05-13 14:03:20 -07001932 pw.print("="); pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
Christopher Tate12cf0b62018-01-05 18:40:14 -08001933 pw.print(" mLastTimeChangeRealtime="); pw.println(mLastTimeChangeRealtime);
Christopher Tate12cf0b62018-01-05 18:40:14 -08001934 pw.print(" mLastTickReceived="); pw.println(sdf.format(new Date(mLastTickReceived)));
1935 pw.print(" mLastTickSet="); pw.println(sdf.format(new Date(mLastTickSet)));
Makoto Onuki5d93b832018-01-10 16:12:39 -08001936 pw.print(" mLastTickAdded="); pw.println(sdf.format(new Date(mLastTickAdded)));
1937 pw.print(" mLastTickRemoved="); pw.println(sdf.format(new Date(mLastTickRemoved)));
Makoto Onukie8edbcf2018-03-02 16:49:29 -08001938
Christopher Tatec8b7f432018-09-28 16:23:10 -07001939 if (RECORD_ALARMS_IN_HISTORY) {
1940 pw.println();
1941 pw.println(" Recent TIME_TICK history:");
1942 int i = mNextTickHistory;
1943 do {
1944 i--;
1945 if (i < 0) i = TICK_HISTORY_DEPTH - 1;
1946 final long time = mTickHistory[i];
1947 pw.print(" ");
1948 pw.println((time > 0)
1949 ? sdf.format(new Date(nowRTC - (nowELAPSED - time)))
1950 : "-");
1951 } while (i != mNextTickHistory);
1952 pw.println();
1953 }
1954
Makoto Onukie8edbcf2018-03-02 16:49:29 -08001955 SystemServiceManager ssm = LocalServices.getService(SystemServiceManager.class);
1956 if (ssm != null) {
1957 pw.println();
1958 pw.print(" RuntimeStarted=");
1959 pw.print(sdf.format(
1960 new Date(nowRTC - nowELAPSED + ssm.getRuntimeStartElapsedTime())));
1961 if (ssm.isRuntimeRestarted()) {
1962 pw.print(" (Runtime restarted)");
1963 }
1964 pw.println();
1965 pw.print(" Runtime uptime (elapsed): ");
1966 TimeUtils.formatDuration(nowELAPSED, ssm.getRuntimeStartElapsedTime(), pw);
1967 pw.println();
1968 pw.print(" Runtime uptime (uptime): ");
1969 TimeUtils.formatDuration(nowUPTIME, ssm.getRuntimeStartUptime(), pw);
1970 pw.println();
1971 }
1972
Dianne Hackbornc3527222015-05-13 14:03:20 -07001973 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001974 if (!mInteractive) {
Dianne Hackborna750a632015-06-16 17:18:23 -07001975 pw.print(" Time since non-interactive: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001976 TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
1977 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001978 }
Makoto Onuki0b05aa62018-02-09 16:14:26 -08001979 pw.print(" Max wakeup delay: ");
1980 TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
1981 pw.println();
1982 pw.print(" Time since last dispatch: ");
1983 TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
1984 pw.println();
1985 pw.print(" Next non-wakeup delivery time: ");
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07001986 TimeUtils.formatDuration(mNextNonWakeupDeliveryTime, nowELAPSED, pw);
Makoto Onuki0b05aa62018-02-09 16:14:26 -08001987 pw.println();
Christopher Tatee0a22b32013-07-11 14:43:13 -07001988
1989 long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
1990 long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
Dianne Hackborna750a632015-06-16 17:18:23 -07001991 pw.print(" Next non-wakeup alarm: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001992 TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
Christopher Tate8b98ade2018-02-09 11:13:19 -08001993 pw.print(" = "); pw.print(mNextNonWakeup);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001994 pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07001995 pw.print(" set at "); TimeUtils.formatDuration(mNextNonWakeUpSetAt, nowELAPSED, pw);
1996 pw.println();
Christopher Tate8b98ade2018-02-09 11:13:19 -08001997 pw.print(" Next wakeup alarm: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
1998 pw.print(" = "); pw.print(mNextWakeup);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001999 pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002000 pw.print(" set at "); TimeUtils.formatDuration(mNextWakeUpSetAt, nowELAPSED, pw);
Christopher Tate8b98ade2018-02-09 11:13:19 -08002001 pw.println();
Suprabh Shukla2324e982018-06-05 21:06:22 -07002002
2003 pw.print(" Next kernel non-wakeup alarm: ");
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002004 TimeUtils.formatDuration(mInjector.getNextAlarm(ELAPSED_REALTIME), pw);
Suprabh Shukla2324e982018-06-05 21:06:22 -07002005 pw.println();
2006 pw.print(" Next kernel wakeup alarm: ");
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002007 TimeUtils.formatDuration(mInjector.getNextAlarm(ELAPSED_REALTIME_WAKEUP), pw);
Suprabh Shukla2324e982018-06-05 21:06:22 -07002008 pw.println();
2009
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07002010 pw.print(" Last wakeup: "); TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw);
Christopher Tate8b98ade2018-02-09 11:13:19 -08002011 pw.print(" = "); pw.println(mLastWakeup);
2012 pw.print(" Last trigger: "); TimeUtils.formatDuration(mLastTrigger, nowELAPSED, pw);
2013 pw.print(" = "); pw.println(mLastTrigger);
Dianne Hackborna750a632015-06-16 17:18:23 -07002014 pw.print(" Num time change events: "); pw.println(mNumTimeChanged);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002015
John Spurlock604a5ee2015-06-01 12:27:22 -04002016 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002017 pw.println(" Next alarm clock information: ");
John Spurlock604a5ee2015-06-01 12:27:22 -04002018 final TreeSet<Integer> users = new TreeSet<>();
2019 for (int i = 0; i < mNextAlarmClockForUser.size(); i++) {
2020 users.add(mNextAlarmClockForUser.keyAt(i));
2021 }
2022 for (int i = 0; i < mPendingSendNextAlarmClockChangedForUser.size(); i++) {
2023 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
2024 }
2025 for (int user : users) {
2026 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
2027 final long time = next != null ? next.getTriggerTime() : 0;
2028 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
Dianne Hackborna750a632015-06-16 17:18:23 -07002029 pw.print(" user:"); pw.print(user);
John Spurlock604a5ee2015-06-01 12:27:22 -04002030 pw.print(" pendingSend:"); pw.print(pendingSend);
2031 pw.print(" time:"); pw.print(time);
2032 if (time > 0) {
2033 pw.print(" = "); pw.print(sdf.format(new Date(time)));
2034 pw.print(" = "); TimeUtils.formatDuration(time, nowRTC, pw);
2035 }
2036 pw.println();
2037 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002038 if (mAlarmBatches.size() > 0) {
2039 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002040 pw.print(" Pending alarm batches: ");
Christopher Tatee0a22b32013-07-11 14:43:13 -07002041 pw.println(mAlarmBatches.size());
2042 for (Batch b : mAlarmBatches) {
2043 pw.print(b); pw.println(':');
Dianne Hackborna750a632015-06-16 17:18:23 -07002044 dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002047 pw.println();
2048 pw.println(" Pending user blocked background alarms: ");
2049 boolean blocked = false;
2050 for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
2051 final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
2052 if (blockedAlarms != null && blockedAlarms.size() > 0) {
2053 blocked = true;
2054 dumpAlarmList(pw, blockedAlarms, " ", nowELAPSED, nowRTC, sdf);
2055 }
2056 }
2057 if (!blocked) {
2058 pw.println(" none");
2059 }
Suprabh Shuklac25447d2018-01-19 16:43:35 -08002060
Suprabh Shukla75edab12018-01-29 14:09:06 -08002061 pw.println(" mLastAlarmDeliveredForPackage:");
2062 for (int i = 0; i < mLastAlarmDeliveredForPackage.size(); i++) {
2063 Pair<String, Integer> packageUser = mLastAlarmDeliveredForPackage.keyAt(i);
2064 pw.print(" Package " + packageUser.first + ", User " + packageUser.second + ":");
2065 TimeUtils.formatDuration(mLastAlarmDeliveredForPackage.valueAt(i), nowELAPSED, pw);
2066 pw.println();
2067 }
2068 pw.println();
2069
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002070 if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002071 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002072 pw.println(" Idle mode state:");
2073 pw.print(" Idling until: ");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002074 if (mPendingIdleUntil != null) {
2075 pw.println(mPendingIdleUntil);
Kweku Adams61e03292017-10-19 14:27:12 -07002076 mPendingIdleUntil.dump(pw, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002077 } else {
2078 pw.println("null");
2079 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002080 pw.println(" Pending alarms:");
2081 dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002082 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002083 if (mNextWakeFromIdle != null) {
2084 pw.println();
2085 pw.print(" Next wake from idle: "); pw.println(mNextWakeFromIdle);
Kweku Adams61e03292017-10-19 14:27:12 -07002086 mNextWakeFromIdle.dump(pw, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002087 }
Dianne Hackborn81038902012-11-26 17:04:09 -08002088
2089 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002090 pw.print(" Past-due non-wakeup alarms: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002091 if (mPendingNonWakeupAlarms.size() > 0) {
2092 pw.println(mPendingNonWakeupAlarms.size());
Dianne Hackborna750a632015-06-16 17:18:23 -07002093 dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002094 } else {
2095 pw.println("(none)");
2096 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002097 pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002098 pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
2099 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002100 pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002101 pw.print(", max non-interactive time: ");
2102 TimeUtils.formatDuration(mNonInteractiveTime, pw);
2103 pw.println();
2104
2105 pw.println();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002106 pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
Christopher Tateeabba732017-08-17 17:12:52 -07002107 pw.print(" PendingIntent send count: "); pw.println(mSendCount);
2108 pw.print(" PendingIntent finish count: "); pw.println(mSendFinishCount);
2109 pw.print(" Listener send count: "); pw.println(mListenerCount);
2110 pw.print(" Listener finish count: "); pw.println(mListenerFinishCount);
Dianne Hackborn81038902012-11-26 17:04:09 -08002111 pw.println();
2112
Christopher Tate7f2a0352015-12-08 10:24:33 -08002113 if (mInFlight.size() > 0) {
2114 pw.println("Outstanding deliveries:");
2115 for (int i = 0; i < mInFlight.size(); i++) {
2116 pw.print(" #"); pw.print(i); pw.print(": ");
2117 pw.println(mInFlight.get(i));
2118 }
2119 pw.println();
2120 }
2121
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002122 if (mLastAllowWhileIdleDispatch.size() > 0) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002123 pw.println(" Last allow while idle dispatch times:");
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002124 for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
Makoto Onukiadb50d82018-01-29 16:20:30 -08002125 pw.print(" UID ");
2126 final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
2127 UserHandle.formatUid(pw, uid);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002128 pw.print(": ");
Makoto Onukiadb50d82018-01-29 16:20:30 -08002129 final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
2130 TimeUtils.formatDuration(lastTime, nowELAPSED, pw);
2131
2132 final long minInterval = getWhileIdleMinIntervalLocked(uid);
2133 pw.print(" Next allowed:");
2134 TimeUtils.formatDuration(lastTime + minInterval, nowELAPSED, pw);
2135 pw.print(" (");
2136 TimeUtils.formatDuration(minInterval, 0, pw);
2137 pw.print(")");
2138
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002139 pw.println();
2140 }
2141 }
Makoto Onukiadb50d82018-01-29 16:20:30 -08002142
2143 pw.print(" mUseAllowWhileIdleShortTime: [");
2144 for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
2145 if (mUseAllowWhileIdleShortTime.valueAt(i)) {
2146 UserHandle.formatUid(pw, mUseAllowWhileIdleShortTime.keyAt(i));
2147 pw.print(" ");
2148 }
2149 }
2150 pw.println("]");
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002151 pw.println();
2152
Dianne Hackborn81038902012-11-26 17:04:09 -08002153 if (mLog.dump(pw, " Recent problems", " ")) {
2154 pw.println();
2155 }
2156
2157 final FilterStats[] topFilters = new FilterStats[10];
2158 final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
2159 @Override
2160 public int compare(FilterStats lhs, FilterStats rhs) {
2161 if (lhs.aggregateTime < rhs.aggregateTime) {
2162 return 1;
2163 } else if (lhs.aggregateTime > rhs.aggregateTime) {
2164 return -1;
2165 }
2166 return 0;
2167 }
2168 };
2169 int len = 0;
Kweku Adams61e03292017-10-19 14:27:12 -07002170 // Get the top 10 FilterStats, ordered by aggregateTime.
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002171 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
2172 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2173 for (int ip=0; ip<uidStats.size(); ip++) {
2174 BroadcastStats bs = uidStats.valueAt(ip);
2175 for (int is=0; is<bs.filterStats.size(); is++) {
2176 FilterStats fs = bs.filterStats.valueAt(is);
2177 int pos = len > 0
2178 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
2179 if (pos < 0) {
2180 pos = -pos - 1;
Dianne Hackborn81038902012-11-26 17:04:09 -08002181 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002182 if (pos < topFilters.length) {
2183 int copylen = topFilters.length - pos - 1;
2184 if (copylen > 0) {
2185 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
2186 }
2187 topFilters[pos] = fs;
2188 if (len < topFilters.length) {
2189 len++;
2190 }
Dianne Hackborn81038902012-11-26 17:04:09 -08002191 }
2192 }
2193 }
2194 }
2195 if (len > 0) {
2196 pw.println(" Top Alarms:");
2197 for (int i=0; i<len; i++) {
2198 FilterStats fs = topFilters[i];
2199 pw.print(" ");
2200 if (fs.nesting > 0) pw.print("*ACTIVE* ");
2201 TimeUtils.formatDuration(fs.aggregateTime, pw);
2202 pw.print(" running, "); pw.print(fs.numWakeup);
2203 pw.print(" wakeups, "); pw.print(fs.count);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002204 pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
2205 pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
Dianne Hackborn81038902012-11-26 17:04:09 -08002206 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002207 pw.print(" "); pw.print(fs.mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08002208 pw.println();
2209 }
2210 }
2211
2212 pw.println(" ");
2213 pw.println(" Alarm Stats:");
2214 final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002215 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
2216 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2217 for (int ip=0; ip<uidStats.size(); ip++) {
2218 BroadcastStats bs = uidStats.valueAt(ip);
2219 pw.print(" ");
2220 if (bs.nesting > 0) pw.print("*ACTIVE* ");
2221 UserHandle.formatUid(pw, bs.mUid);
2222 pw.print(":");
2223 pw.print(bs.mPackageName);
2224 pw.print(" "); TimeUtils.formatDuration(bs.aggregateTime, pw);
2225 pw.print(" running, "); pw.print(bs.numWakeup);
2226 pw.println(" wakeups:");
2227 tmpFilters.clear();
2228 for (int is=0; is<bs.filterStats.size(); is++) {
2229 tmpFilters.add(bs.filterStats.valueAt(is));
2230 }
2231 Collections.sort(tmpFilters, comparator);
2232 for (int i=0; i<tmpFilters.size(); i++) {
2233 FilterStats fs = tmpFilters.get(i);
2234 pw.print(" ");
2235 if (fs.nesting > 0) pw.print("*ACTIVE* ");
2236 TimeUtils.formatDuration(fs.aggregateTime, pw);
2237 pw.print(" "); pw.print(fs.numWakeup);
2238 pw.print(" wakes " ); pw.print(fs.count);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002239 pw.print(" alarms, last ");
2240 TimeUtils.formatDuration(fs.lastTime, nowELAPSED, pw);
2241 pw.println(":");
2242 pw.print(" ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002243 pw.print(fs.mTag);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002244 pw.println();
2245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002246 }
2247 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08002248 pw.println();
2249 mStatLogger.dump(pw, " ");
Christopher Tate18a75f12013-07-01 18:18:59 -07002250
Dianne Hackbornae78bf82015-10-26 13:33:20 -07002251 if (RECORD_DEVICE_IDLE_ALARMS) {
2252 pw.println();
2253 pw.println(" Allow while idle dispatches:");
2254 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
2255 IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
2256 pw.print(" ");
2257 TimeUtils.formatDuration(ent.elapsedRealtime, nowELAPSED, pw);
2258 pw.print(": ");
2259 UserHandle.formatUid(pw, ent.uid);
2260 pw.print(":");
2261 pw.println(ent.pkg);
2262 if (ent.op != null) {
2263 pw.print(" ");
2264 pw.print(ent.op);
2265 pw.print(" / ");
2266 pw.print(ent.tag);
2267 if (ent.argRealtime != 0) {
2268 pw.print(" (");
2269 TimeUtils.formatDuration(ent.argRealtime, nowELAPSED, pw);
2270 pw.print(")");
2271 }
2272 pw.println();
2273 }
2274 }
2275 }
2276
Christopher Tate18a75f12013-07-01 18:18:59 -07002277 if (WAKEUP_STATS) {
2278 pw.println();
2279 pw.println(" Recent Wakeup History:");
Christopher Tate18a75f12013-07-01 18:18:59 -07002280 long last = -1;
2281 for (WakeupEvent event : mRecentWakeups) {
2282 pw.print(" "); pw.print(sdf.format(new Date(event.when)));
2283 pw.print('|');
2284 if (last < 0) {
2285 pw.print('0');
2286 } else {
2287 pw.print(event.when - last);
2288 }
2289 last = event.when;
2290 pw.print('|'); pw.print(event.uid);
2291 pw.print('|'); pw.print(event.action);
2292 pw.println();
2293 }
2294 pw.println();
2295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002296 }
2297 }
2298
Kweku Adams61e03292017-10-19 14:27:12 -07002299 void dumpProto(FileDescriptor fd) {
2300 final ProtoOutputStream proto = new ProtoOutputStream(fd);
2301
2302 synchronized (mLock) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002303 final long nowRTC = mInjector.getCurrentTimeMillis();
2304 final long nowElapsed = mInjector.getElapsedRealtime();
Yi Jin2b30f322018-02-20 15:41:47 -08002305 proto.write(AlarmManagerServiceDumpProto.CURRENT_TIME, nowRTC);
2306 proto.write(AlarmManagerServiceDumpProto.ELAPSED_REALTIME, nowElapsed);
2307 proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_CLOCK_TIME,
Kweku Adams61e03292017-10-19 14:27:12 -07002308 mLastTimeChangeClockTime);
Yi Jin2b30f322018-02-20 15:41:47 -08002309 proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_REALTIME,
Kweku Adams61e03292017-10-19 14:27:12 -07002310 mLastTimeChangeRealtime);
2311
Yi Jin2b30f322018-02-20 15:41:47 -08002312 mConstants.dumpProto(proto, AlarmManagerServiceDumpProto.SETTINGS);
Kweku Adams61e03292017-10-19 14:27:12 -07002313
Makoto Onukie4918212018-02-06 11:30:15 -08002314 if (mAppStateTracker != null) {
2315 mAppStateTracker.dumpProto(proto,
Yi Jin2b30f322018-02-20 15:41:47 -08002316 AlarmManagerServiceDumpProto.FORCE_APP_STANDBY_TRACKER);
Makoto Onukie4918212018-02-06 11:30:15 -08002317 }
Kweku Adams61e03292017-10-19 14:27:12 -07002318
Yi Jin2b30f322018-02-20 15:41:47 -08002319 proto.write(AlarmManagerServiceDumpProto.IS_INTERACTIVE, mInteractive);
Kweku Adams61e03292017-10-19 14:27:12 -07002320 if (!mInteractive) {
2321 // Durations
Yi Jin2b30f322018-02-20 15:41:47 -08002322 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_NON_INTERACTIVE_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002323 nowElapsed - mNonInteractiveStartTime);
Yi Jin2b30f322018-02-20 15:41:47 -08002324 proto.write(AlarmManagerServiceDumpProto.MAX_WAKEUP_DELAY_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002325 currentNonWakeupFuzzLocked(nowElapsed));
Yi Jin2b30f322018-02-20 15:41:47 -08002326 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_DISPATCH_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002327 nowElapsed - mLastAlarmDeliveryTime);
Yi Jin2b30f322018-02-20 15:41:47 -08002328 proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_NON_WAKEUP_DELIVERY_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002329 nowElapsed - mNextNonWakeupDeliveryTime);
2330 }
2331
Yi Jin2b30f322018-02-20 15:41:47 -08002332 proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_NON_WAKEUP_ALARM_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002333 mNextNonWakeup - nowElapsed);
Yi Jin2b30f322018-02-20 15:41:47 -08002334 proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_WAKEUP_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002335 mNextWakeup - nowElapsed);
Yi Jin2b30f322018-02-20 15:41:47 -08002336 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_WAKEUP_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002337 nowElapsed - mLastWakeup);
Yi Jin2b30f322018-02-20 15:41:47 -08002338 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_WAKEUP_SET_MS,
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002339 nowElapsed - mNextWakeUpSetAt);
Yi Jin2b30f322018-02-20 15:41:47 -08002340 proto.write(AlarmManagerServiceDumpProto.TIME_CHANGE_EVENT_COUNT, mNumTimeChanged);
Kweku Adams61e03292017-10-19 14:27:12 -07002341
2342 final TreeSet<Integer> users = new TreeSet<>();
2343 final int nextAlarmClockForUserSize = mNextAlarmClockForUser.size();
2344 for (int i = 0; i < nextAlarmClockForUserSize; i++) {
2345 users.add(mNextAlarmClockForUser.keyAt(i));
2346 }
2347 final int pendingSendNextAlarmClockChangedForUserSize =
2348 mPendingSendNextAlarmClockChangedForUser.size();
2349 for (int i = 0; i < pendingSendNextAlarmClockChangedForUserSize; i++) {
2350 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
2351 }
2352 for (int user : users) {
2353 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
2354 final long time = next != null ? next.getTriggerTime() : 0;
2355 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
Yi Jin2b30f322018-02-20 15:41:47 -08002356 final long aToken = proto.start(AlarmManagerServiceDumpProto.NEXT_ALARM_CLOCK_METADATA);
Kweku Adams61e03292017-10-19 14:27:12 -07002357 proto.write(AlarmClockMetadataProto.USER, user);
2358 proto.write(AlarmClockMetadataProto.IS_PENDING_SEND, pendingSend);
2359 proto.write(AlarmClockMetadataProto.TRIGGER_TIME_MS, time);
2360 proto.end(aToken);
2361 }
2362 for (Batch b : mAlarmBatches) {
Yi Jin2b30f322018-02-20 15:41:47 -08002363 b.writeToProto(proto, AlarmManagerServiceDumpProto.PENDING_ALARM_BATCHES,
Kweku Adams61e03292017-10-19 14:27:12 -07002364 nowElapsed, nowRTC);
2365 }
2366 for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
2367 final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
2368 if (blockedAlarms != null) {
2369 for (Alarm a : blockedAlarms) {
2370 a.writeToProto(proto,
Yi Jin2b30f322018-02-20 15:41:47 -08002371 AlarmManagerServiceDumpProto.PENDING_USER_BLOCKED_BACKGROUND_ALARMS,
Kweku Adams61e03292017-10-19 14:27:12 -07002372 nowElapsed, nowRTC);
2373 }
2374 }
2375 }
2376 if (mPendingIdleUntil != null) {
2377 mPendingIdleUntil.writeToProto(
Yi Jin2b30f322018-02-20 15:41:47 -08002378 proto, AlarmManagerServiceDumpProto.PENDING_IDLE_UNTIL, nowElapsed, nowRTC);
Kweku Adams61e03292017-10-19 14:27:12 -07002379 }
2380 for (Alarm a : mPendingWhileIdleAlarms) {
Yi Jin2b30f322018-02-20 15:41:47 -08002381 a.writeToProto(proto, AlarmManagerServiceDumpProto.PENDING_WHILE_IDLE_ALARMS,
Kweku Adams61e03292017-10-19 14:27:12 -07002382 nowElapsed, nowRTC);
2383 }
2384 if (mNextWakeFromIdle != null) {
Yi Jin2b30f322018-02-20 15:41:47 -08002385 mNextWakeFromIdle.writeToProto(proto, AlarmManagerServiceDumpProto.NEXT_WAKE_FROM_IDLE,
Kweku Adams61e03292017-10-19 14:27:12 -07002386 nowElapsed, nowRTC);
2387 }
2388
2389 for (Alarm a : mPendingNonWakeupAlarms) {
Yi Jin2b30f322018-02-20 15:41:47 -08002390 a.writeToProto(proto, AlarmManagerServiceDumpProto.PAST_DUE_NON_WAKEUP_ALARMS,
Kweku Adams61e03292017-10-19 14:27:12 -07002391 nowElapsed, nowRTC);
2392 }
2393
Yi Jin2b30f322018-02-20 15:41:47 -08002394 proto.write(AlarmManagerServiceDumpProto.DELAYED_ALARM_COUNT, mNumDelayedAlarms);
2395 proto.write(AlarmManagerServiceDumpProto.TOTAL_DELAY_TIME_MS, mTotalDelayTime);
2396 proto.write(AlarmManagerServiceDumpProto.MAX_DELAY_DURATION_MS, mMaxDelayTime);
2397 proto.write(AlarmManagerServiceDumpProto.MAX_NON_INTERACTIVE_DURATION_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002398 mNonInteractiveTime);
2399
Yi Jin2b30f322018-02-20 15:41:47 -08002400 proto.write(AlarmManagerServiceDumpProto.BROADCAST_REF_COUNT, mBroadcastRefCount);
2401 proto.write(AlarmManagerServiceDumpProto.PENDING_INTENT_SEND_COUNT, mSendCount);
2402 proto.write(AlarmManagerServiceDumpProto.PENDING_INTENT_FINISH_COUNT, mSendFinishCount);
2403 proto.write(AlarmManagerServiceDumpProto.LISTENER_SEND_COUNT, mListenerCount);
2404 proto.write(AlarmManagerServiceDumpProto.LISTENER_FINISH_COUNT, mListenerFinishCount);
Kweku Adams61e03292017-10-19 14:27:12 -07002405
2406 for (InFlight f : mInFlight) {
Yi Jin2b30f322018-02-20 15:41:47 -08002407 f.writeToProto(proto, AlarmManagerServiceDumpProto.OUTSTANDING_DELIVERIES);
Kweku Adams61e03292017-10-19 14:27:12 -07002408 }
2409
Kweku Adams61e03292017-10-19 14:27:12 -07002410 for (int i = 0; i < mLastAllowWhileIdleDispatch.size(); ++i) {
2411 final long token = proto.start(
Yi Jin2b30f322018-02-20 15:41:47 -08002412 AlarmManagerServiceDumpProto.LAST_ALLOW_WHILE_IDLE_DISPATCH_TIMES);
Makoto Onukiadb50d82018-01-29 16:20:30 -08002413 final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
2414 final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
2415
Yi Jin2b30f322018-02-20 15:41:47 -08002416 proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.UID, uid);
2417 proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.TIME_MS, lastTime);
2418 proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.NEXT_ALLOWED_MS,
Makoto Onukiadb50d82018-01-29 16:20:30 -08002419 lastTime + getWhileIdleMinIntervalLocked(uid));
Kweku Adams61e03292017-10-19 14:27:12 -07002420 proto.end(token);
2421 }
2422
Makoto Onukiadb50d82018-01-29 16:20:30 -08002423 for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
2424 if (mUseAllowWhileIdleShortTime.valueAt(i)) {
Yi Jin2b30f322018-02-20 15:41:47 -08002425 proto.write(AlarmManagerServiceDumpProto.USE_ALLOW_WHILE_IDLE_SHORT_TIME,
Makoto Onukiadb50d82018-01-29 16:20:30 -08002426 mUseAllowWhileIdleShortTime.keyAt(i));
2427 }
2428 }
2429
Yi Jin2b30f322018-02-20 15:41:47 -08002430 mLog.writeToProto(proto, AlarmManagerServiceDumpProto.RECENT_PROBLEMS);
Kweku Adams61e03292017-10-19 14:27:12 -07002431
2432 final FilterStats[] topFilters = new FilterStats[10];
2433 final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
2434 @Override
2435 public int compare(FilterStats lhs, FilterStats rhs) {
2436 if (lhs.aggregateTime < rhs.aggregateTime) {
2437 return 1;
2438 } else if (lhs.aggregateTime > rhs.aggregateTime) {
2439 return -1;
2440 }
2441 return 0;
2442 }
2443 };
2444 int len = 0;
2445 // Get the top 10 FilterStats, ordered by aggregateTime.
2446 for (int iu = 0; iu < mBroadcastStats.size(); ++iu) {
2447 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2448 for (int ip = 0; ip < uidStats.size(); ++ip) {
2449 BroadcastStats bs = uidStats.valueAt(ip);
2450 for (int is = 0; is < bs.filterStats.size(); ++is) {
2451 FilterStats fs = bs.filterStats.valueAt(is);
2452 int pos = len > 0
2453 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
2454 if (pos < 0) {
2455 pos = -pos - 1;
2456 }
2457 if (pos < topFilters.length) {
2458 int copylen = topFilters.length - pos - 1;
2459 if (copylen > 0) {
2460 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
2461 }
2462 topFilters[pos] = fs;
2463 if (len < topFilters.length) {
2464 len++;
2465 }
2466 }
2467 }
2468 }
2469 }
2470 for (int i = 0; i < len; ++i) {
Yi Jin2b30f322018-02-20 15:41:47 -08002471 final long token = proto.start(AlarmManagerServiceDumpProto.TOP_ALARMS);
Kweku Adams61e03292017-10-19 14:27:12 -07002472 FilterStats fs = topFilters[i];
2473
Yi Jin2b30f322018-02-20 15:41:47 -08002474 proto.write(AlarmManagerServiceDumpProto.TopAlarm.UID, fs.mBroadcastStats.mUid);
2475 proto.write(AlarmManagerServiceDumpProto.TopAlarm.PACKAGE_NAME,
Kweku Adams61e03292017-10-19 14:27:12 -07002476 fs.mBroadcastStats.mPackageName);
Yi Jin2b30f322018-02-20 15:41:47 -08002477 fs.writeToProto(proto, AlarmManagerServiceDumpProto.TopAlarm.FILTER);
Kweku Adams61e03292017-10-19 14:27:12 -07002478
2479 proto.end(token);
2480 }
2481
2482 final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
2483 for (int iu = 0; iu < mBroadcastStats.size(); ++iu) {
2484 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2485 for (int ip = 0; ip < uidStats.size(); ++ip) {
Yi Jin2b30f322018-02-20 15:41:47 -08002486 final long token = proto.start(AlarmManagerServiceDumpProto.ALARM_STATS);
Kweku Adams61e03292017-10-19 14:27:12 -07002487
2488 BroadcastStats bs = uidStats.valueAt(ip);
Yi Jin2b30f322018-02-20 15:41:47 -08002489 bs.writeToProto(proto, AlarmManagerServiceDumpProto.AlarmStat.BROADCAST);
Kweku Adams61e03292017-10-19 14:27:12 -07002490
2491 // uidStats is an ArrayMap, which we can't sort.
2492 tmpFilters.clear();
2493 for (int is = 0; is < bs.filterStats.size(); ++is) {
2494 tmpFilters.add(bs.filterStats.valueAt(is));
2495 }
2496 Collections.sort(tmpFilters, comparator);
2497 for (FilterStats fs : tmpFilters) {
Yi Jin2b30f322018-02-20 15:41:47 -08002498 fs.writeToProto(proto, AlarmManagerServiceDumpProto.AlarmStat.FILTERS);
Kweku Adams61e03292017-10-19 14:27:12 -07002499 }
2500
2501 proto.end(token);
2502 }
2503 }
2504
2505 if (RECORD_DEVICE_IDLE_ALARMS) {
2506 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
2507 IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
2508 final long token = proto.start(
Yi Jin2b30f322018-02-20 15:41:47 -08002509 AlarmManagerServiceDumpProto.ALLOW_WHILE_IDLE_DISPATCHES);
Kweku Adams61e03292017-10-19 14:27:12 -07002510
2511 proto.write(IdleDispatchEntryProto.UID, ent.uid);
2512 proto.write(IdleDispatchEntryProto.PKG, ent.pkg);
2513 proto.write(IdleDispatchEntryProto.TAG, ent.tag);
2514 proto.write(IdleDispatchEntryProto.OP, ent.op);
2515 proto.write(IdleDispatchEntryProto.ENTRY_CREATION_REALTIME,
2516 ent.elapsedRealtime);
2517 proto.write(IdleDispatchEntryProto.ARG_REALTIME, ent.argRealtime);
2518
2519 proto.end(token);
2520 }
2521 }
2522
2523 if (WAKEUP_STATS) {
2524 for (WakeupEvent event : mRecentWakeups) {
Yi Jin2b30f322018-02-20 15:41:47 -08002525 final long token = proto.start(AlarmManagerServiceDumpProto.RECENT_WAKEUP_HISTORY);
Kweku Adams61e03292017-10-19 14:27:12 -07002526 proto.write(WakeupEventProto.UID, event.uid);
2527 proto.write(WakeupEventProto.ACTION, event.action);
2528 proto.write(WakeupEventProto.WHEN, event.when);
2529 proto.end(token);
2530 }
2531 }
2532 }
2533
2534 proto.flush();
2535 }
2536
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002537 private void logBatchesLocked(SimpleDateFormat sdf) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08002538 ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
2539 PrintWriter pw = new PrintWriter(bs);
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002540 final long nowRTC = mInjector.getCurrentTimeMillis();
2541 final long nowELAPSED = mInjector.getElapsedRealtime();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002542 final int NZ = mAlarmBatches.size();
2543 for (int iz = 0; iz < NZ; iz++) {
2544 Batch bz = mAlarmBatches.get(iz);
2545 pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002546 dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC, sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002547 pw.flush();
2548 Slog.v(TAG, bs.toString());
2549 bs.reset();
2550 }
2551 }
2552
2553 private boolean validateConsistencyLocked() {
2554 if (DEBUG_VALIDATE) {
2555 long lastTime = Long.MIN_VALUE;
2556 final int N = mAlarmBatches.size();
2557 for (int i = 0; i < N; i++) {
2558 Batch b = mAlarmBatches.get(i);
2559 if (b.start >= lastTime) {
2560 // duplicate start times are okay because of standalone batches
2561 lastTime = b.start;
2562 } else {
2563 Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002564 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2565 logBatchesLocked(sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002566 return false;
2567 }
2568 }
2569 }
2570 return true;
2571 }
2572
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002573 private Batch findFirstWakeupBatchLocked() {
2574 final int N = mAlarmBatches.size();
2575 for (int i = 0; i < N; i++) {
2576 Batch b = mAlarmBatches.get(i);
2577 if (b.hasWakeups()) {
2578 return b;
2579 }
2580 }
2581 return null;
2582 }
2583
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002584 long getNextWakeFromIdleTimeImpl() {
2585 synchronized (mLock) {
2586 return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE;
2587 }
2588 }
2589
2590 AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02002591 synchronized (mLock) {
2592 return mNextAlarmClockForUser.get(userId);
2593 }
2594 }
2595
2596 /**
2597 * Recomputes the next alarm clock for all users.
2598 */
2599 private void updateNextAlarmClockLocked() {
2600 if (!mNextAlarmClockMayChange) {
2601 return;
2602 }
2603 mNextAlarmClockMayChange = false;
2604
Jose Lima235510e2014-08-13 12:50:01 -07002605 SparseArray<AlarmManager.AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02002606 nextForUser.clear();
2607
2608 final int N = mAlarmBatches.size();
2609 for (int i = 0; i < N; i++) {
2610 ArrayList<Alarm> alarms = mAlarmBatches.get(i).alarms;
2611 final int M = alarms.size();
2612
2613 for (int j = 0; j < M; j++) {
2614 Alarm a = alarms.get(j);
2615 if (a.alarmClock != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002616 final int userId = UserHandle.getUserId(a.uid);
Christopher Tate76389c02016-08-03 14:57:47 -07002617 AlarmManager.AlarmClockInfo current = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002618
2619 if (DEBUG_ALARM_CLOCK) {
Christopher Tate76389c02016-08-03 14:57:47 -07002620 Log.v(TAG, "Found AlarmClockInfo " + a.alarmClock + " at " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01002621 formatNextAlarm(getContext(), a.alarmClock, userId) +
Adrian Roosc42a1e12014-07-07 23:35:53 +02002622 " for user " + userId);
2623 }
2624
2625 // Alarms and batches are sorted by time, no need to compare times here.
2626 if (nextForUser.get(userId) == null) {
2627 nextForUser.put(userId, a.alarmClock);
Christopher Tate76389c02016-08-03 14:57:47 -07002628 } else if (a.alarmClock.equals(current)
2629 && current.getTriggerTime() <= nextForUser.get(userId).getTriggerTime()) {
2630 // same/earlier time and it's the one we cited before, so stick with it
2631 nextForUser.put(userId, current);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002632 }
2633 }
2634 }
2635 }
2636
2637 // Update mNextAlarmForUser with new values.
2638 final int NN = nextForUser.size();
2639 for (int i = 0; i < NN; i++) {
Jose Lima235510e2014-08-13 12:50:01 -07002640 AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002641 int userId = nextForUser.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07002642 AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002643 if (!newAlarm.equals(currentAlarm)) {
2644 updateNextAlarmInfoForUserLocked(userId, newAlarm);
2645 }
2646 }
2647
2648 // Remove users without any alarm clocks scheduled.
2649 final int NNN = mNextAlarmClockForUser.size();
2650 for (int i = NNN - 1; i >= 0; i--) {
2651 int userId = mNextAlarmClockForUser.keyAt(i);
2652 if (nextForUser.get(userId) == null) {
2653 updateNextAlarmInfoForUserLocked(userId, null);
2654 }
2655 }
2656 }
2657
Jose Lima235510e2014-08-13 12:50:01 -07002658 private void updateNextAlarmInfoForUserLocked(int userId,
2659 AlarmManager.AlarmClockInfo alarmClock) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02002660 if (alarmClock != null) {
2661 if (DEBUG_ALARM_CLOCK) {
2662 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01002663 formatNextAlarm(getContext(), alarmClock, userId));
Adrian Roosc42a1e12014-07-07 23:35:53 +02002664 }
2665 mNextAlarmClockForUser.put(userId, alarmClock);
2666 } else {
2667 if (DEBUG_ALARM_CLOCK) {
2668 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None");
2669 }
2670 mNextAlarmClockForUser.remove(userId);
2671 }
2672
2673 mPendingSendNextAlarmClockChangedForUser.put(userId, true);
2674 mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
2675 mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
2676 }
2677
2678 /**
2679 * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
2680 * for which alarm clocks have changed since the last call to this.
2681 *
2682 * Do not call with a lock held. Only call from mHandler's thread.
2683 *
2684 * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
2685 */
2686 private void sendNextAlarmClockChanged() {
Jose Lima235510e2014-08-13 12:50:01 -07002687 SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02002688 pendingUsers.clear();
2689
2690 synchronized (mLock) {
2691 final int N = mPendingSendNextAlarmClockChangedForUser.size();
2692 for (int i = 0; i < N; i++) {
2693 int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i);
2694 pendingUsers.append(userId, mNextAlarmClockForUser.get(userId));
2695 }
2696 mPendingSendNextAlarmClockChangedForUser.clear();
2697 }
2698
2699 final int N = pendingUsers.size();
2700 for (int i = 0; i < N; i++) {
2701 int userId = pendingUsers.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07002702 AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002703 Settings.System.putStringForUser(getContext().getContentResolver(),
2704 Settings.System.NEXT_ALARM_FORMATTED,
Selim Cinek9c4a7072014-11-21 17:44:34 +01002705 formatNextAlarm(getContext(), alarmClock, userId),
Adrian Roosc42a1e12014-07-07 23:35:53 +02002706 userId);
2707
2708 getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT,
2709 new UserHandle(userId));
2710 }
2711 }
2712
2713 /**
2714 * Formats an alarm like platform/packages/apps/DeskClock used to.
2715 */
Selim Cinek9c4a7072014-11-21 17:44:34 +01002716 private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info,
2717 int userId) {
2718 String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma";
Adrian Roosc42a1e12014-07-07 23:35:53 +02002719 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
2720 return (info == null) ? "" :
2721 DateFormat.format(pattern, info.getTriggerTime()).toString();
2722 }
2723
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002724 /**
2725 * If the last time AlarmThread woke up precedes any due wakeup or non-wakeup alarm that we set
2726 * by more than half a minute, log a wtf.
2727 */
2728 private void validateLastAlarmExpiredLocked(long nowElapsed) {
2729 final StringBuilder errorMsg = new StringBuilder();
2730 boolean stuck = false;
Suprabh Shuklab50f43f2018-06-27 16:40:55 -07002731 if (mNextNonWakeup < (nowElapsed - 10_000) && mLastWakeup < mNextNonWakeup) {
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002732 stuck = true;
2733 errorMsg.append("[mNextNonWakeup=");
2734 TimeUtils.formatDuration(mNextNonWakeup - nowElapsed, errorMsg);
Suprabh Shuklab50f43f2018-06-27 16:40:55 -07002735 errorMsg.append(" set at ");
Suprabh Shukla673d34b2018-07-03 14:00:29 -07002736 TimeUtils.formatDuration(mNextNonWakeUpSetAt - nowElapsed, errorMsg);
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002737 errorMsg.append(", mLastWakeup=");
2738 TimeUtils.formatDuration(mLastWakeup - nowElapsed, errorMsg);
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002739 errorMsg.append(", timerfd_gettime=" + mInjector.getNextAlarm(ELAPSED_REALTIME));
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002740 errorMsg.append("];");
2741 }
Suprabh Shuklab50f43f2018-06-27 16:40:55 -07002742 if (mNextWakeup < (nowElapsed - 10_000) && mLastWakeup < mNextWakeup) {
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002743 stuck = true;
2744 errorMsg.append("[mNextWakeup=");
2745 TimeUtils.formatDuration(mNextWakeup - nowElapsed, errorMsg);
Suprabh Shuklab50f43f2018-06-27 16:40:55 -07002746 errorMsg.append(" set at ");
Suprabh Shukla673d34b2018-07-03 14:00:29 -07002747 TimeUtils.formatDuration(mNextWakeUpSetAt - nowElapsed, errorMsg);
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002748 errorMsg.append(", mLastWakeup=");
2749 TimeUtils.formatDuration(mLastWakeup - nowElapsed, errorMsg);
2750 errorMsg.append(", timerfd_gettime="
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002751 + mInjector.getNextAlarm(ELAPSED_REALTIME_WAKEUP));
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002752 errorMsg.append("];");
2753 }
2754 if (stuck) {
2755 Slog.wtf(TAG, "Alarm delivery stuck: " + errorMsg.toString());
2756 }
2757 }
2758
Adam Lesinski182f73f2013-12-05 16:48:06 -08002759 void rescheduleKernelAlarmsLocked() {
2760 // Schedule the next upcoming wakeup alarm. If there is a deliverable batch
2761 // prior to that which contains no wakeups, we schedule that as well.
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002762 final long nowElapsed = mInjector.getElapsedRealtime();
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002763 validateLastAlarmExpiredLocked(nowElapsed);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002764 long nextNonWakeup = 0;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002765 if (mAlarmBatches.size() > 0) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002766 final Batch firstWakeup = findFirstWakeupBatchLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002767 final Batch firstBatch = mAlarmBatches.get(0);
Suprabh Shukla2fa95452018-02-12 12:53:23 -08002768 if (firstWakeup != null) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002769 mNextWakeup = firstWakeup.start;
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002770 mNextWakeUpSetAt = nowElapsed;
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002771 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002772 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002773 if (firstBatch != firstWakeup) {
2774 nextNonWakeup = firstBatch.start;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002775 }
2776 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002777 if (mPendingNonWakeupAlarms.size() > 0) {
2778 if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
2779 nextNonWakeup = mNextNonWakeupDeliveryTime;
2780 }
2781 }
Suprabh Shukla2fa95452018-02-12 12:53:23 -08002782 if (nextNonWakeup != 0) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002783 mNextNonWakeup = nextNonWakeup;
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002784 mNextNonWakeUpSetAt = nowElapsed;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002785 setLocked(ELAPSED_REALTIME, nextNonWakeup);
2786 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002787 }
2788
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002789 void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
Christopher Tate1d99c392017-12-07 16:54:04 -08002790 if (operation == null && directReceiver == null) {
2791 if (localLOGV) {
2792 Slog.w(TAG, "requested remove() of null operation",
2793 new RuntimeException("here"));
2794 }
2795 return;
2796 }
2797
Adam Lesinski182f73f2013-12-05 16:48:06 -08002798 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002799 final Predicate<Alarm> whichAlarms = (Alarm a) -> a.matches(operation, directReceiver);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002800 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2801 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002802 didRemove |= b.remove(whichAlarms);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002803 if (b.size() == 0) {
2804 mAlarmBatches.remove(i);
2805 }
2806 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002807 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002808 if (mPendingWhileIdleAlarms.get(i).matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002809 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2810 mPendingWhileIdleAlarms.remove(i);
2811 }
2812 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002813 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
2814 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
2815 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
2816 if (alarmsForUid.get(j).matches(operation, directReceiver)) {
2817 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2818 alarmsForUid.remove(j);
2819 }
2820 }
2821 if (alarmsForUid.size() == 0) {
2822 mPendingBackgroundAlarms.removeAt(i);
2823 }
2824 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002825 if (didRemove) {
2826 if (DEBUG_BATCH) {
2827 Slog.v(TAG, "remove(operation) changed bounds; rebatching");
2828 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002829 boolean restorePending = false;
Christopher Tate14a7bb02015-10-01 10:24:31 -07002830 if (mPendingIdleUntil != null && mPendingIdleUntil.matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002831 mPendingIdleUntil = null;
2832 restorePending = true;
2833 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002834 if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002835 mNextWakeFromIdle = null;
2836 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002837 rebatchAllAlarmsLocked(true);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002838 if (restorePending) {
2839 restorePendingWhileIdleAlarmsLocked();
2840 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02002841 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002842 }
2843 }
2844
Christopher Tate1d99c392017-12-07 16:54:04 -08002845 void removeLocked(final int uid) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08002846 if (uid == Process.SYSTEM_UID) {
2847 Slog.wtf(TAG, "removeLocked: Shouldn't for UID=" + uid);
2848 return;
2849 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002850 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002851 final Predicate<Alarm> whichAlarms = (Alarm a) -> a.uid == uid;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002852 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2853 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002854 didRemove |= b.remove(whichAlarms);
2855 if (b.size() == 0) {
2856 mAlarmBatches.remove(i);
2857 }
2858 }
2859 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
2860 final Alarm a = mPendingWhileIdleAlarms.get(i);
2861 if (a.uid == uid) {
2862 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2863 mPendingWhileIdleAlarms.remove(i);
2864 }
2865 }
2866 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i --) {
2867 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
2868 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
2869 if (alarmsForUid.get(j).uid == uid) {
2870 alarmsForUid.remove(j);
2871 }
2872 }
2873 if (alarmsForUid.size() == 0) {
2874 mPendingBackgroundAlarms.removeAt(i);
2875 }
2876 }
2877 if (didRemove) {
2878 if (DEBUG_BATCH) {
2879 Slog.v(TAG, "remove(uid) changed bounds; rebatching");
2880 }
2881 rebatchAllAlarmsLocked(true);
2882 rescheduleKernelAlarmsLocked();
2883 updateNextAlarmClockLocked();
2884 }
2885 }
2886
2887 void removeLocked(final String packageName) {
2888 if (packageName == null) {
2889 if (localLOGV) {
2890 Slog.w(TAG, "requested remove() of null packageName",
2891 new RuntimeException("here"));
2892 }
2893 return;
2894 }
2895
2896 boolean didRemove = false;
2897 final Predicate<Alarm> whichAlarms = (Alarm a) -> a.matches(packageName);
Makoto Onuki5d93b832018-01-10 16:12:39 -08002898 final boolean oldHasTick = haveBatchesTimeTickAlarm(mAlarmBatches);
Christopher Tate1d99c392017-12-07 16:54:04 -08002899 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2900 Batch b = mAlarmBatches.get(i);
2901 didRemove |= b.remove(whichAlarms);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002902 if (b.size() == 0) {
2903 mAlarmBatches.remove(i);
2904 }
2905 }
Makoto Onuki5d93b832018-01-10 16:12:39 -08002906 final boolean newHasTick = haveBatchesTimeTickAlarm(mAlarmBatches);
2907 if (oldHasTick != newHasTick) {
2908 Slog.wtf(TAG, "removeLocked: hasTick changed from " + oldHasTick + " to " + newHasTick);
2909 }
2910
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002911 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002912 final Alarm a = mPendingWhileIdleAlarms.get(i);
2913 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002914 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2915 mPendingWhileIdleAlarms.remove(i);
2916 }
2917 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002918 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i --) {
2919 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
2920 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
2921 if (alarmsForUid.get(j).matches(packageName)) {
2922 alarmsForUid.remove(j);
2923 }
2924 }
2925 if (alarmsForUid.size() == 0) {
2926 mPendingBackgroundAlarms.removeAt(i);
2927 }
2928 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002929 if (didRemove) {
2930 if (DEBUG_BATCH) {
2931 Slog.v(TAG, "remove(package) changed bounds; rebatching");
2932 }
2933 rebatchAllAlarmsLocked(true);
2934 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02002935 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002936 }
2937 }
2938
Christopher Tate1d99c392017-12-07 16:54:04 -08002939 void removeForStoppedLocked(final int uid) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08002940 if (uid == Process.SYSTEM_UID) {
2941 Slog.wtf(TAG, "removeForStoppedLocked: Shouldn't for UID=" + uid);
2942 return;
2943 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002944 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002945 final Predicate<Alarm> whichAlarms = (Alarm a) -> {
2946 try {
2947 if (a.uid == uid && ActivityManager.getService().isAppStartModeDisabled(
2948 uid, a.packageName)) {
2949 return true;
2950 }
2951 } catch (RemoteException e) { /* fall through */}
2952 return false;
2953 };
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002954 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2955 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002956 didRemove |= b.remove(whichAlarms);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002957 if (b.size() == 0) {
2958 mAlarmBatches.remove(i);
2959 }
2960 }
2961 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
2962 final Alarm a = mPendingWhileIdleAlarms.get(i);
Dianne Hackborne07641d2016-11-09 15:07:23 -08002963 if (a.uid == uid) {
2964 // Don't set didRemove, since this doesn't impact the scheduled alarms.
2965 mPendingWhileIdleAlarms.remove(i);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002966 }
2967 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002968 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
2969 if (mPendingBackgroundAlarms.keyAt(i) == uid) {
2970 mPendingBackgroundAlarms.removeAt(i);
2971 }
2972 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07002973 if (didRemove) {
2974 if (DEBUG_BATCH) {
2975 Slog.v(TAG, "remove(package) changed bounds; rebatching");
2976 }
2977 rebatchAllAlarmsLocked(true);
2978 rescheduleKernelAlarmsLocked();
2979 updateNextAlarmClockLocked();
2980 }
2981 }
2982
Adam Lesinski182f73f2013-12-05 16:48:06 -08002983 void removeUserLocked(int userHandle) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08002984 if (userHandle == UserHandle.USER_SYSTEM) {
2985 Slog.wtf(TAG, "removeForStoppedLocked: Shouldn't for user=" + userHandle);
2986 return;
2987 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002988 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08002989 final Predicate<Alarm> whichAlarms =
2990 (Alarm a) -> UserHandle.getUserId(a.creatorUid) == userHandle;
Adam Lesinski182f73f2013-12-05 16:48:06 -08002991 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
2992 Batch b = mAlarmBatches.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -08002993 didRemove |= b.remove(whichAlarms);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002994 if (b.size() == 0) {
2995 mAlarmBatches.remove(i);
2996 }
2997 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002998 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07002999 if (UserHandle.getUserId(mPendingWhileIdleAlarms.get(i).creatorUid)
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003000 == userHandle) {
3001 // Don't set didRemove, since this doesn't impact the scheduled alarms.
3002 mPendingWhileIdleAlarms.remove(i);
3003 }
3004 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003005 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
3006 if (UserHandle.getUserId(mPendingBackgroundAlarms.keyAt(i)) == userHandle) {
3007 mPendingBackgroundAlarms.removeAt(i);
3008 }
3009 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003010 for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
3011 if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
3012 mLastAllowWhileIdleDispatch.removeAt(i);
3013 }
3014 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08003015
3016 if (didRemove) {
3017 if (DEBUG_BATCH) {
3018 Slog.v(TAG, "remove(user) changed bounds; rebatching");
3019 }
3020 rebatchAllAlarmsLocked(true);
3021 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02003022 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08003023 }
3024 }
3025
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003026 void interactiveStateChangedLocked(boolean interactive) {
3027 if (mInteractive != interactive) {
3028 mInteractive = interactive;
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003029 final long nowELAPSED = mInjector.getElapsedRealtime();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003030 if (interactive) {
3031 if (mPendingNonWakeupAlarms.size() > 0) {
3032 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
3033 mTotalDelayTime += thisDelayTime;
3034 if (mMaxDelayTime < thisDelayTime) {
3035 mMaxDelayTime = thisDelayTime;
3036 }
3037 deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
3038 mPendingNonWakeupAlarms.clear();
3039 }
3040 if (mNonInteractiveStartTime > 0) {
3041 long dur = nowELAPSED - mNonInteractiveStartTime;
3042 if (dur > mNonInteractiveTime) {
3043 mNonInteractiveTime = dur;
3044 }
3045 }
Suprabh Shukla12bd0162018-11-12 18:00:18 -08003046 // And send a TIME_TICK right now, since it is important to get the UI updated.
3047 mHandler.post(() ->
3048 getContext().sendBroadcastAsUser(mTimeTickIntent, UserHandle.ALL));
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003049 } else {
3050 mNonInteractiveStartTime = nowELAPSED;
3051 }
3052 }
3053 }
3054
Adam Lesinski182f73f2013-12-05 16:48:06 -08003055 boolean lookForPackageLocked(String packageName) {
3056 for (int i = 0; i < mAlarmBatches.size(); i++) {
3057 Batch b = mAlarmBatches.get(i);
3058 if (b.hasPackage(packageName)) {
3059 return true;
3060 }
3061 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003062 for (int i = 0; i < mPendingWhileIdleAlarms.size(); i++) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003063 final Alarm a = mPendingWhileIdleAlarms.get(i);
3064 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003065 return true;
3066 }
3067 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08003068 return false;
3069 }
3070
3071 private void setLocked(int type, long when) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003072 if (mInjector.isAlarmDriverPresent()) {
3073 mInjector.setAlarm(type, when);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003074 } else {
3075 Message msg = Message.obtain();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003076 msg.what = AlarmHandler.ALARM_EVENT;
Kweku Adams61e03292017-10-19 14:27:12 -07003077
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003078 mHandler.removeMessages(msg.what);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003079 mHandler.sendMessageAtTime(msg, when);
3080 }
3081 }
3082
Dianne Hackborn043fcd92010-10-06 14:27:34 -07003083 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Kweku Adams61e03292017-10-19 14:27:12 -07003084 String prefix, String label, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003085 for (int i=list.size()-1; i>=0; i--) {
3086 Alarm a = list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003087 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
3088 pw.print(": "); pw.println(a);
Kweku Adams61e03292017-10-19 14:27:12 -07003089 a.dump(pw, prefix + " ", nowELAPSED, nowRTC, sdf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 }
3091 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003092
3093 private static final String labelForType(int type) {
3094 switch (type) {
3095 case RTC: return "RTC";
3096 case RTC_WAKEUP : return "RTC_WAKEUP";
3097 case ELAPSED_REALTIME : return "ELAPSED";
3098 case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP";
Christopher Tatee0a22b32013-07-11 14:43:13 -07003099 }
3100 return "--unknown--";
3101 }
3102
3103 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003104 String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07003105 for (int i=list.size()-1; i>=0; i--) {
3106 Alarm a = list.get(i);
3107 final String label = labelForType(a.type);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003108 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
3109 pw.print(": "); pw.println(a);
Kweku Adams61e03292017-10-19 14:27:12 -07003110 a.dump(pw, prefix + " ", nowELAPSED, nowRTC, sdf);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003111 }
3112 }
3113
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003114 private boolean isBackgroundRestricted(Alarm alarm) {
Christopher Tateda3dc922018-05-09 13:49:41 -07003115 boolean exemptOnBatterySaver = (alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003116 if (alarm.alarmClock != null) {
Christopher Tateda3dc922018-05-09 13:49:41 -07003117 // Don't defer alarm clocks
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003118 return false;
3119 }
Christopher Tateda3dc922018-05-09 13:49:41 -07003120 if (alarm.operation != null) {
3121 if (alarm.operation.isActivity()) {
3122 // Don't defer starting actual UI
3123 return false;
3124 }
3125 if (alarm.operation.isForegroundService()) {
3126 // FG service alarms are nearly as important; consult AST policy
3127 exemptOnBatterySaver = true;
3128 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003129 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08003130 final String sourcePackage = alarm.sourcePackage;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003131 final int sourceUid = alarm.creatorUid;
Makoto Onukie4918212018-02-06 11:30:15 -08003132 return (mAppStateTracker != null) &&
Christopher Tateda3dc922018-05-09 13:49:41 -07003133 mAppStateTracker.areAlarmsRestricted(sourceUid, sourcePackage,
3134 exemptOnBatterySaver);
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003135 }
3136
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003137 private static native long init();
3138 private static native void close(long nativeData);
3139 private static native int set(long nativeData, int type, long seconds, long nanoseconds);
3140 private static native int waitForAlarm(long nativeData);
3141 private static native int setKernelTime(long nativeData, long millis);
3142 private static native int setKernelTimezone(long nativeData, int minuteswest);
3143 private static native long getNextAlarm(long nativeData, int type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144
Makoto Onukiadb50d82018-01-29 16:20:30 -08003145 private long getWhileIdleMinIntervalLocked(int uid) {
3146 final boolean dozing = mPendingIdleUntil != null;
Makoto Onukie4918212018-02-06 11:30:15 -08003147 final boolean ebs = (mAppStateTracker != null)
3148 && mAppStateTracker.isForceAllAppsStandbyEnabled();
Makoto Onukiadb50d82018-01-29 16:20:30 -08003149 if (!dozing && !ebs) {
3150 return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
3151 }
3152 if (dozing) {
3153 return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
3154 }
3155 if (mUseAllowWhileIdleShortTime.get(uid)) {
3156 // if the last allow-while-idle went off while uid was fg, or the uid
3157 // recently came into fg, don't block the alarm for long.
3158 return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
3159 }
3160 return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
3161 }
3162
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003163 boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003164 final long nowRTC) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003165 boolean hasWakeup = false;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003166 // batches are temporally sorted, so we need only pull from the
3167 // start of the list until we either empty it or hit a batch
3168 // that is not yet deliverable
Christopher Tate6578ad12013-09-24 17:12:46 -07003169 while (mAlarmBatches.size() > 0) {
3170 Batch batch = mAlarmBatches.get(0);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003171 if (batch.start > nowELAPSED) {
3172 // Everything else is scheduled for the future
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003173 break;
3174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175
Christopher Tatee0a22b32013-07-11 14:43:13 -07003176 // We will (re)schedule some alarms now; don't let that interfere
3177 // with delivery of this current batch
3178 mAlarmBatches.remove(0);
Dianne Hackborn390517b2013-05-30 15:03:32 -07003179
Christopher Tatee0a22b32013-07-11 14:43:13 -07003180 final int N = batch.size();
3181 for (int i = 0; i < N; i++) {
3182 Alarm alarm = batch.get(i);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003183
3184 if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
3185 // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
Christopher Tateddd1da142018-04-13 13:41:51 -07003186 // schedule such alarms. The first such alarm from an app is always delivered.
3187 final long lastTime = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, -1);
Makoto Onukiadb50d82018-01-29 16:20:30 -08003188 final long minTime = lastTime + getWhileIdleMinIntervalLocked(alarm.creatorUid);
Christopher Tateddd1da142018-04-13 13:41:51 -07003189 if (lastTime >= 0 && nowELAPSED < minTime) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003190 // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
3191 // alarm went off for this app. Reschedule the alarm to be in the
3192 // correct time period.
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003193 alarm.expectedWhenElapsed = alarm.whenElapsed = minTime;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003194 if (alarm.maxWhenElapsed < minTime) {
3195 alarm.maxWhenElapsed = minTime;
3196 }
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003197 alarm.expectedMaxWhenElapsed = alarm.maxWhenElapsed;
Dianne Hackbornae78bf82015-10-26 13:33:20 -07003198 if (RECORD_DEVICE_IDLE_ALARMS) {
3199 IdleDispatchEntry ent = new IdleDispatchEntry();
3200 ent.uid = alarm.uid;
3201 ent.pkg = alarm.operation.getCreatorPackage();
3202 ent.tag = alarm.operation.getTag("");
3203 ent.op = "RESCHEDULE";
3204 ent.elapsedRealtime = nowELAPSED;
3205 ent.argRealtime = lastTime;
3206 mAllowWhileIdleDispatches.add(ent);
3207 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003208 setImplLocked(alarm, true, false);
3209 continue;
3210 }
3211 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003212 if (isBackgroundRestricted(alarm)) {
3213 // Alarms with FLAG_WAKE_FROM_IDLE or mPendingIdleUntil alarm are not deferred
3214 if (DEBUG_BG_LIMIT) {
3215 Slog.d(TAG, "Deferring alarm " + alarm + " due to user forced app standby");
3216 }
3217 ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(alarm.creatorUid);
3218 if (alarmsForUid == null) {
3219 alarmsForUid = new ArrayList<>();
3220 mPendingBackgroundAlarms.put(alarm.creatorUid, alarmsForUid);
3221 }
3222 alarmsForUid.add(alarm);
3223 continue;
3224 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003225
Christopher Tatee0a22b32013-07-11 14:43:13 -07003226 alarm.count = 1;
3227 triggerList.add(alarm);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003228 if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
3229 EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003230 alarm.statsTag);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003231 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003232 if (mPendingIdleUntil == alarm) {
3233 mPendingIdleUntil = null;
3234 rebatchAllAlarmsLocked(false);
3235 restorePendingWhileIdleAlarmsLocked();
3236 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003237 if (mNextWakeFromIdle == alarm) {
3238 mNextWakeFromIdle = null;
3239 rebatchAllAlarmsLocked(false);
3240 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003241
3242 // Recurring alarms may have passed several alarm intervals while the
3243 // phone was asleep or off, so pass a trigger count when sending them.
3244 if (alarm.repeatInterval > 0) {
3245 // this adjustment will be zero if we're late by
3246 // less than one full repeat interval
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003247 alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003248
3249 // Also schedule its next recurrence
3250 final long delta = alarm.count * alarm.repeatInterval;
3251 final long nextElapsed = alarm.whenElapsed + delta;
Christopher Tate3e04b472013-10-21 17:51:31 -07003252 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
Christopher Tatee0a22b32013-07-11 14:43:13 -07003253 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
Christopher Tate14a7bb02015-10-01 10:24:31 -07003254 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
3255 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
Christopher Tate864d42e2014-12-02 11:48:53 -08003256 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003257
Christopher Tate864d42e2014-12-02 11:48:53 -08003258 if (alarm.wakeup) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003259 hasWakeup = true;
3260 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02003261
3262 // We removed an alarm clock. Let the caller recompute the next alarm clock.
3263 if (alarm.alarmClock != null) {
3264 mNextAlarmClockMayChange = true;
3265 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07003266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003268
Christopher Tate1590f1e2014-10-02 17:27:57 -07003269 // This is a new alarm delivery set; bump the sequence number to indicate that
3270 // all apps' alarm delivery classes should be recalculated.
3271 mCurrentSeq++;
3272 calculateDeliveryPriorities(triggerList);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003273 Collections.sort(triggerList, mAlarmDispatchComparator);
3274
3275 if (localLOGV) {
3276 for (int i=0; i<triggerList.size(); i++) {
3277 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
3278 }
3279 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003280
3281 return hasWakeup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003282 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003284 /**
3285 * This Comparator sorts Alarms into increasing time order.
3286 */
3287 public static class IncreasingTimeOrder implements Comparator<Alarm> {
3288 public int compare(Alarm a1, Alarm a2) {
jinho.park1acd32a2015-05-27 14:44:18 +09003289 long when1 = a1.whenElapsed;
3290 long when2 = a2.whenElapsed;
Charles Tsaicdaaeee2015-05-20 18:16:48 +08003291 if (when1 > when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003292 return 1;
3293 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +08003294 if (when1 < when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 return -1;
3296 }
3297 return 0;
3298 }
3299 }
Kweku Adams61e03292017-10-19 14:27:12 -07003300
Makoto Onuki2206af32017-11-21 16:25:35 -08003301 @VisibleForTesting
3302 static class Alarm {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003303 public final int type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003304 public final long origWhen;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003305 public final boolean wakeup;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003306 public final PendingIntent operation;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003307 public final IAlarmListener listener;
3308 public final String listenerTag;
3309 public final String statsTag;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003310 public final WorkSource workSource;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003311 public final int flags;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003312 public final AlarmManager.AlarmClockInfo alarmClock;
3313 public final int uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003314 public final int creatorUid;
3315 public final String packageName;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003316 public final String sourcePackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 public int count;
3318 public long when;
Christopher Tate3e04b472013-10-21 17:51:31 -07003319 public long windowLength;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003320 public long whenElapsed; // 'when' in the elapsed time base
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003321 public long maxWhenElapsed; // also in the elapsed time base
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003322 // Expected alarm expiry time before app standby deferring is applied.
3323 public long expectedWhenElapsed;
3324 public long expectedMaxWhenElapsed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325 public long repeatInterval;
Christopher Tate1590f1e2014-10-02 17:27:57 -07003326 public PriorityClass priorityClass;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003327
Christopher Tate3e04b472013-10-21 17:51:31 -07003328 public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003329 long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag,
3330 WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info,
3331 int _uid, String _pkgName) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07003332 type = _type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003333 origWhen = _when;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003334 wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
3335 || _type == AlarmManager.RTC_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003336 when = _when;
3337 whenElapsed = _whenElapsed;
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003338 expectedWhenElapsed = _whenElapsed;
Christopher Tate3e04b472013-10-21 17:51:31 -07003339 windowLength = _windowLength;
Christopher Tate22e919d2018-02-16 16:16:50 -08003340 maxWhenElapsed = expectedMaxWhenElapsed = clampPositive(_maxWhen);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003341 repeatInterval = _interval;
3342 operation = _op;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003343 listener = _rec;
3344 listenerTag = _listenerTag;
3345 statsTag = makeTag(_op, _listenerTag, _type);
David Christieebe51fc2013-07-26 13:23:29 -07003346 workSource = _ws;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003347 flags = _flags;
Adrian Roosc42a1e12014-07-07 23:35:53 +02003348 alarmClock = _info;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003349 uid = _uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003350 packageName = _pkgName;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003351 sourcePackage = (operation != null) ? operation.getCreatorPackage() : packageName;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003352 creatorUid = (operation != null) ? operation.getCreatorUid() : uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003354
Christopher Tate14a7bb02015-10-01 10:24:31 -07003355 public static String makeTag(PendingIntent pi, String tag, int type) {
3356 final String alarmString = type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
3357 ? "*walarm*:" : "*alarm*:";
3358 return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag);
3359 }
3360
3361 public WakeupEvent makeWakeupEvent(long nowRTC) {
3362 return new WakeupEvent(nowRTC, creatorUid,
3363 (operation != null)
3364 ? operation.getIntent().getAction()
3365 : ("<listener>:" + listenerTag));
3366 }
3367
3368 // Returns true if either matches
3369 public boolean matches(PendingIntent pi, IAlarmListener rec) {
3370 return (operation != null)
3371 ? operation.equals(pi)
Lorenzo Colitti9b43ce02015-11-22 22:00:08 +09003372 : rec != null && listener.asBinder().equals(rec.asBinder());
Christopher Tate14a7bb02015-10-01 10:24:31 -07003373 }
3374
3375 public boolean matches(String packageName) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08003376 return packageName.equals(sourcePackage);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003377 }
3378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379 @Override
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003380 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003381 StringBuilder sb = new StringBuilder(128);
3382 sb.append("Alarm{");
3383 sb.append(Integer.toHexString(System.identityHashCode(this)));
3384 sb.append(" type ");
3385 sb.append(type);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003386 sb.append(" when ");
3387 sb.append(when);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003388 sb.append(" ");
Suprabh Shukla75edab12018-01-29 14:09:06 -08003389 sb.append(sourcePackage);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003390 sb.append('}');
3391 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 }
3393
Kweku Adams61e03292017-10-19 14:27:12 -07003394 public void dump(PrintWriter pw, String prefix, long nowELAPSED, long nowRTC,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003395 SimpleDateFormat sdf) {
3396 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003397 pw.print(prefix); pw.print("tag="); pw.println(statsTag);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003398 pw.print(prefix); pw.print("type="); pw.print(type);
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003399 pw.print(" expectedWhenElapsed="); TimeUtils.formatDuration(
3400 expectedWhenElapsed, nowELAPSED, pw);
3401 pw.print(" expectedMaxWhenElapsed="); TimeUtils.formatDuration(
3402 expectedMaxWhenElapsed, nowELAPSED, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003403 pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
3404 nowELAPSED, pw);
Suprabh Shukla2fa95452018-02-12 12:53:23 -08003405 pw.print(" maxWhenElapsed="); TimeUtils.formatDuration(maxWhenElapsed,
3406 nowELAPSED, pw);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003407 pw.print(" when=");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003408 if (isRtc) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003409 pw.print(sdf.format(new Date(when)));
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003410 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003411 TimeUtils.formatDuration(when, nowELAPSED, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003412 }
3413 pw.println();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003414 pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003415 pw.print(" repeatInterval="); pw.print(repeatInterval);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003416 pw.print(" count="); pw.print(count);
3417 pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003418 if (alarmClock != null) {
3419 pw.print(prefix); pw.println("Alarm clock:");
3420 pw.print(prefix); pw.print(" triggerTime=");
3421 pw.println(sdf.format(new Date(alarmClock.getTriggerTime())));
3422 pw.print(prefix); pw.print(" showIntent="); pw.println(alarmClock.getShowIntent());
3423 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003424 pw.print(prefix); pw.print("operation="); pw.println(operation);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003425 if (listener != null) {
3426 pw.print(prefix); pw.print("listener="); pw.println(listener.asBinder());
3427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003428 }
Kweku Adams61e03292017-10-19 14:27:12 -07003429
3430 public void writeToProto(ProtoOutputStream proto, long fieldId, long nowElapsed,
3431 long nowRTC) {
3432 final long token = proto.start(fieldId);
3433
3434 proto.write(AlarmProto.TAG, statsTag);
3435 proto.write(AlarmProto.TYPE, type);
Kweku Adams923ec432017-12-11 18:05:38 -08003436 proto.write(AlarmProto.TIME_UNTIL_WHEN_ELAPSED_MS, whenElapsed - nowElapsed);
Kweku Adams61e03292017-10-19 14:27:12 -07003437 proto.write(AlarmProto.WINDOW_LENGTH_MS, windowLength);
3438 proto.write(AlarmProto.REPEAT_INTERVAL_MS, repeatInterval);
3439 proto.write(AlarmProto.COUNT, count);
3440 proto.write(AlarmProto.FLAGS, flags);
3441 if (alarmClock != null) {
3442 alarmClock.writeToProto(proto, AlarmProto.ALARM_CLOCK);
3443 }
3444 if (operation != null) {
3445 operation.writeToProto(proto, AlarmProto.OPERATION);
3446 }
3447 if (listener != null) {
3448 proto.write(AlarmProto.LISTENER, listener.asBinder().toString());
3449 }
3450
3451 proto.end(token);
3452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 }
Christopher Tate18a75f12013-07-01 18:18:59 -07003454
Christopher Tatee0a22b32013-07-11 14:43:13 -07003455 void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) {
3456 final int numBatches = batches.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07003457 for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) {
3458 Batch b = batches.get(nextBatch);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003459 if (b.start > nowELAPSED) {
Christopher Tate18a75f12013-07-01 18:18:59 -07003460 break;
3461 }
3462
Christopher Tatee0a22b32013-07-11 14:43:13 -07003463 final int numAlarms = b.alarms.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07003464 for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) {
3465 Alarm a = b.alarms.get(nextAlarm);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003466 mRecentWakeups.add(a.makeWakeupEvent(nowRTC));
Christopher Tatee0a22b32013-07-11 14:43:13 -07003467 }
Christopher Tate18a75f12013-07-01 18:18:59 -07003468 }
3469 }
3470
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003471 long currentNonWakeupFuzzLocked(long nowELAPSED) {
3472 long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
3473 if (timeSinceOn < 5*60*1000) {
3474 // If the screen has been off for 5 minutes, only delay by at most two minutes.
3475 return 2*60*1000;
3476 } else if (timeSinceOn < 30*60*1000) {
3477 // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
3478 return 15*60*1000;
3479 } else {
3480 // Otherwise, we will delay by at most an hour.
3481 return 60*60*1000;
3482 }
3483 }
3484
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003485 static int fuzzForDuration(long duration) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003486 if (duration < 15*60*1000) {
3487 // If the duration until the time is less than 15 minutes, the maximum fuzz
3488 // is the duration.
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003489 return (int)duration;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003490 } else if (duration < 90*60*1000) {
3491 // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes,
3492 return 15*60*1000;
3493 } else {
3494 // Otherwise, we will fuzz by at most half an hour.
3495 return 30*60*1000;
3496 }
3497 }
3498
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003499 boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
3500 if (mInteractive) {
3501 return false;
3502 }
3503 if (mLastAlarmDeliveryTime <= 0) {
3504 return false;
3505 }
minho.choo649acab2014-12-12 16:13:55 +09003506 if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003507 // This is just a little paranoia, if somehow we have pending non-wakeup alarms
3508 // and the next delivery time is in the past, then just deliver them all. This
3509 // avoids bugs where we get stuck in a loop trying to poll for alarms.
3510 return false;
3511 }
3512 long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
3513 return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
3514 }
3515
3516 void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
3517 mLastAlarmDeliveryTime = nowELAPSED;
3518 for (int i=0; i<triggerList.size(); i++) {
3519 Alarm alarm = triggerList.get(i);
Dianne Hackborna750a632015-06-16 17:18:23 -07003520 final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
Tim Murray175c0f92017-11-28 15:01:04 -08003521 if (alarm.wakeup) {
3522 Trace.traceBegin(Trace.TRACE_TAG_POWER, "Dispatch wakeup alarm to " + alarm.packageName);
3523 } else {
3524 Trace.traceBegin(Trace.TRACE_TAG_POWER, "Dispatch non-wakeup alarm to " + alarm.packageName);
3525 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003526 try {
Christopher Tate2ff5a732014-09-18 13:47:57 -07003527 if (localLOGV) {
3528 Slog.v(TAG, "sending alarm " + alarm);
3529 }
Dianne Hackborn1e383822015-04-10 14:02:33 -07003530 if (RECORD_ALARMS_IN_HISTORY) {
Narayan Kamath695cf722017-12-21 18:32:47 +00003531 ActivityManager.noteAlarmStart(alarm.operation, alarm.workSource, alarm.uid,
3532 alarm.statsTag);
Dianne Hackborn1e383822015-04-10 14:02:33 -07003533 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003534 mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003535 } catch (RuntimeException e) {
3536 Slog.w(TAG, "Failure sending alarm.", e);
3537 }
Tim Murray175c0f92017-11-28 15:01:04 -08003538 Trace.traceEnd(Trace.TRACE_TAG_POWER);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003539 }
3540 }
3541
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003542 private boolean isExemptFromAppStandby(Alarm a) {
3543 return a.alarmClock != null || UserHandle.isCore(a.creatorUid)
3544 || (a.flags & FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED) != 0;
3545 }
3546
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003547 @VisibleForTesting
3548 static class Injector {
3549 private long mNativeData;
3550 private Context mContext;
3551
3552 Injector(Context context) {
3553 mContext = context;
3554 }
3555
3556 void init() {
3557 mNativeData = AlarmManagerService.init();
3558 }
3559
3560 int waitForAlarm() {
3561 return AlarmManagerService.waitForAlarm(mNativeData);
3562 }
3563
3564 boolean isAlarmDriverPresent() {
3565 return mNativeData != 0;
3566 }
3567
3568 void setAlarm(int type, long millis) {
3569 // The kernel never triggers alarms with negative wakeup times
3570 // so we ensure they are positive.
3571 final long alarmSeconds, alarmNanoseconds;
3572 if (millis < 0) {
3573 alarmSeconds = 0;
3574 alarmNanoseconds = 0;
3575 } else {
3576 alarmSeconds = millis / 1000;
3577 alarmNanoseconds = (millis % 1000) * 1000 * 1000;
3578 }
3579
3580 final int result = AlarmManagerService.set(mNativeData, type, alarmSeconds,
3581 alarmNanoseconds);
3582 if (result != 0) {
3583 final long nowElapsed = SystemClock.elapsedRealtime();
3584 Slog.wtf(TAG, "Unable to set kernel alarm, now=" + nowElapsed
3585 + " type=" + type + " @ (" + alarmSeconds + "," + alarmNanoseconds
3586 + "), ret = " + result + " = " + Os.strerror(result));
3587 }
3588 }
3589
3590 long getNextAlarm(int type) {
3591 return AlarmManagerService.getNextAlarm(mNativeData, type);
3592 }
3593
3594 void setKernelTimezone(int minutesWest) {
3595 AlarmManagerService.setKernelTimezone(mNativeData, minutesWest);
3596 }
3597
3598 void setKernelTime(long millis) {
3599 if (mNativeData != 0) {
3600 AlarmManagerService.setKernelTime(mNativeData, millis);
3601 }
3602 }
3603
3604 void close() {
3605 AlarmManagerService.close(mNativeData);
3606 }
3607
3608 long getElapsedRealtime() {
3609 return SystemClock.elapsedRealtime();
3610 }
3611
3612 long getCurrentTimeMillis() {
3613 return System.currentTimeMillis();
3614 }
3615
3616 PowerManager.WakeLock getAlarmWakeLock() {
3617 final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
3618 return pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
3619 }
3620
3621 int getSystemUiUid() {
3622 int sysUiUid = -1;
3623 final PackageManager pm = mContext.getPackageManager();
3624 try {
3625 PermissionInfo sysUiPerm = pm.getPermissionInfo(SYSTEM_UI_SELF_PERMISSION, 0);
3626 ApplicationInfo sysUi = pm.getApplicationInfo(sysUiPerm.packageName, 0);
3627 if ((sysUi.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
3628 sysUiUid = sysUi.uid;
3629 } else {
3630 Slog.e(TAG, "SysUI permission " + SYSTEM_UI_SELF_PERMISSION
3631 + " defined by non-privileged app " + sysUi.packageName
3632 + " - ignoring");
3633 }
3634 } catch (NameNotFoundException e) {
3635 }
3636 return sysUiUid;
3637 }
3638
3639 ClockReceiver getClockReceiver(AlarmManagerService service) {
3640 return service.new ClockReceiver();
3641 }
3642 }
3643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644 private class AlarmThread extends Thread
3645 {
Suprabh Shukla1d6a4032018-07-09 16:59:27 -07003646 private int mFalseWakeups;
3647 private int mWtfThreshold;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003648 public AlarmThread()
3649 {
3650 super("AlarmManager");
Suprabh Shukla1d6a4032018-07-09 16:59:27 -07003651 mFalseWakeups = 0;
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003652 mWtfThreshold = 100;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003653 }
Kweku Adams61e03292017-10-19 14:27:12 -07003654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003655 public void run()
3656 {
Dianne Hackborn390517b2013-05-30 15:03:32 -07003657 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
3658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 while (true)
3660 {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003661 int result = mInjector.waitForAlarm();
3662 final long nowRTC = mInjector.getCurrentTimeMillis();
3663 final long nowELAPSED = mInjector.getElapsedRealtime();
Christopher Tate8b98ade2018-02-09 11:13:19 -08003664 synchronized (mLock) {
3665 mLastWakeup = nowELAPSED;
3666 }
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003667 if (result == 0) {
3668 Slog.wtf(TAG, "waitForAlarm returned 0, nowRTC = " + nowRTC
3669 + ", nowElapsed = " + nowELAPSED);
3670 }
Christopher Tate8b98ade2018-02-09 11:13:19 -08003671 triggerList.clear();
Dianne Hackbornc3527222015-05-13 14:03:20 -07003672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003673 if ((result & TIME_CHANGED_MASK) != 0) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07003674 // The kernel can give us spurious time change notifications due to
3675 // small adjustments it makes internally; we want to filter those out.
3676 final long lastTimeChangeClockTime;
3677 final long expectedClockTime;
Dianne Hackborn998e6082014-09-11 19:13:23 -07003678 synchronized (mLock) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07003679 lastTimeChangeClockTime = mLastTimeChangeClockTime;
3680 expectedClockTime = lastTimeChangeClockTime
3681 + (nowELAPSED - mLastTimeChangeRealtime);
Dianne Hackborn998e6082014-09-11 19:13:23 -07003682 }
Christopher Tate2b6e459e2017-02-17 14:33:52 -08003683 if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-1000)
3684 || nowRTC > (expectedClockTime+1000)) {
3685 // The change is by at least +/- 1000 ms (or this is the first change),
Dianne Hackbornc3527222015-05-13 14:03:20 -07003686 // let's do it!
3687 if (DEBUG_BATCH) {
3688 Slog.v(TAG, "Time changed notification from kernel; rebatching");
3689 }
Bookatz7948c872018-09-04 12:58:33 -07003690 // StatsLog requires currentTimeMillis(), which == nowRTC to within usecs.
3691 StatsLog.write(StatsLog.WALL_CLOCK_TIME_SHIFTED, nowRTC);
Christopher Tatec8b7f432018-09-28 16:23:10 -07003692 removeImpl(null, mTimeTickTrigger);
3693 removeImpl(mDateChangeSender, null);
Dianne Hackbornc3527222015-05-13 14:03:20 -07003694 rebatchAllAlarms();
3695 mClockReceiver.scheduleTimeTickEvent();
Christopher Tatecf024712016-08-05 13:21:45 -07003696 mClockReceiver.scheduleDateChangedEvent();
Dianne Hackbornc3527222015-05-13 14:03:20 -07003697 synchronized (mLock) {
3698 mNumTimeChanged++;
3699 mLastTimeChangeClockTime = nowRTC;
3700 mLastTimeChangeRealtime = nowELAPSED;
3701 }
3702 Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
3703 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
Christopher Tate2b6e459e2017-02-17 14:33:52 -08003704 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
Chad Brubaker291df4f2017-03-14 10:23:02 -07003705 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
3706 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Dianne Hackbornc3527222015-05-13 14:03:20 -07003707 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
3708
3709 // The world has changed on us, so we need to re-evaluate alarms
3710 // regardless of whether the kernel has told us one went off.
3711 result |= IS_WAKEUP_MASK;
3712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714
Dianne Hackbornc3527222015-05-13 14:03:20 -07003715 if (result != TIME_CHANGED_MASK) {
3716 // If this was anything besides just a time change, then figure what if
3717 // anything to do about alarms.
3718 synchronized (mLock) {
3719 if (localLOGV) Slog.v(
3720 TAG, "Checking for alarms... rtc=" + nowRTC
3721 + ", elapsed=" + nowELAPSED);
Christopher Tate18a75f12013-07-01 18:18:59 -07003722
Dianne Hackbornc3527222015-05-13 14:03:20 -07003723 if (WAKEUP_STATS) {
3724 if ((result & IS_WAKEUP_MASK) != 0) {
3725 long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
3726 int n = 0;
3727 for (WakeupEvent event : mRecentWakeups) {
3728 if (event.when > newEarliest) break;
3729 n++; // number of now-stale entries at the list head
3730 }
3731 for (int i = 0; i < n; i++) {
3732 mRecentWakeups.remove();
3733 }
Christopher Tate18a75f12013-07-01 18:18:59 -07003734
Dianne Hackbornc3527222015-05-13 14:03:20 -07003735 recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003736 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003737 }
Dianne Hackbornc3527222015-05-13 14:03:20 -07003738
Christopher Tate8b98ade2018-02-09 11:13:19 -08003739 mLastTrigger = nowELAPSED;
Dianne Hackbornc3527222015-05-13 14:03:20 -07003740 boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
3741 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
3742 // if there are no wakeup alarms and the screen is off, we can
3743 // delay what we have so far until the future.
3744 if (mPendingNonWakeupAlarms.size() == 0) {
3745 mStartCurrentDelayTime = nowELAPSED;
3746 mNextNonWakeupDeliveryTime = nowELAPSED
3747 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
3748 }
3749 mPendingNonWakeupAlarms.addAll(triggerList);
3750 mNumDelayedAlarms += triggerList.size();
3751 rescheduleKernelAlarmsLocked();
3752 updateNextAlarmClockLocked();
3753 } else {
3754 // now deliver the alarm intents; if there are pending non-wakeup
3755 // alarms, we need to merge them in to the list. note we don't
3756 // just deliver them first because we generally want non-wakeup
3757 // alarms delivered after wakeup alarms.
Dianne Hackbornc3527222015-05-13 14:03:20 -07003758 if (mPendingNonWakeupAlarms.size() > 0) {
3759 calculateDeliveryPriorities(mPendingNonWakeupAlarms);
3760 triggerList.addAll(mPendingNonWakeupAlarms);
3761 Collections.sort(triggerList, mAlarmDispatchComparator);
3762 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
3763 mTotalDelayTime += thisDelayTime;
3764 if (mMaxDelayTime < thisDelayTime) {
3765 mMaxDelayTime = thisDelayTime;
3766 }
3767 mPendingNonWakeupAlarms.clear();
3768 }
Suprabh Shukla1d6a4032018-07-09 16:59:27 -07003769 if (mLastTimeChangeRealtime != nowELAPSED && triggerList.isEmpty()) {
3770 if (++mFalseWakeups >= mWtfThreshold) {
3771 Slog.wtf(TAG, "Too many (" + mFalseWakeups
3772 + ") false wakeups, nowElapsed=" + nowELAPSED);
3773 if (mWtfThreshold < 100_000) {
3774 mWtfThreshold *= 10;
3775 } else {
3776 mFalseWakeups = 0;
3777 }
3778 }
3779 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003780 final ArraySet<Pair<String, Integer>> triggerPackages =
3781 new ArraySet<>();
3782 for (int i = 0; i < triggerList.size(); i++) {
3783 final Alarm a = triggerList.get(i);
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003784 if (!isExemptFromAppStandby(a)) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003785 triggerPackages.add(Pair.create(
3786 a.sourcePackage, UserHandle.getUserId(a.creatorUid)));
Suprabh Shukla75edab12018-01-29 14:09:06 -08003787 }
3788 }
Dianne Hackbornc3527222015-05-13 14:03:20 -07003789 deliverAlarmsLocked(triggerList, nowELAPSED);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003790 reorderAlarmsBasedOnStandbyBuckets(triggerPackages);
3791 rescheduleKernelAlarmsLocked();
3792 updateNextAlarmClockLocked();
Dianne Hackbornc3527222015-05-13 14:03:20 -07003793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 }
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07003795
3796 } else {
3797 // Just in case -- even though no wakeup flag was set, make sure
3798 // we have updated the kernel to the next alarm time.
Christopher Tate7b5b7cb2016-07-07 14:41:36 -07003799 synchronized (mLock) {
3800 rescheduleKernelAlarmsLocked();
3801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003802 }
3803 }
3804 }
3805 }
Christopher Tatec4a07d12012-04-06 14:19:13 -07003806
David Christieebe51fc2013-07-26 13:23:29 -07003807 /**
3808 * Attribute blame for a WakeLock.
3809 * @param pi PendingIntent to attribute blame to if ws is null.
3810 * @param ws WorkSource to attribute blame.
Christopher Tate14a7bb02015-10-01 10:24:31 -07003811 * @param knownUid attribution uid; < 0 if we need to derive it from the PendingIntent sender
David Christieebe51fc2013-07-26 13:23:29 -07003812 */
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003813 void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003814 int knownUid, boolean first) {
Christopher Tatec4a07d12012-04-06 14:19:13 -07003815 try {
Christopher Tatec8b7f432018-09-28 16:23:10 -07003816 mWakeLock.setHistoryTag(first ? tag : null);
3817
David Christieebe51fc2013-07-26 13:23:29 -07003818 if (ws != null) {
3819 mWakeLock.setWorkSource(ws);
3820 return;
3821 }
3822
Christopher Tate14a7bb02015-10-01 10:24:31 -07003823 final int uid = (knownUid >= 0)
3824 ? knownUid
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003825 : ActivityManager.getService().getUidForIntentSender(pi.getTarget());
Christopher Tatec4a07d12012-04-06 14:19:13 -07003826 if (uid >= 0) {
3827 mWakeLock.setWorkSource(new WorkSource(uid));
3828 return;
3829 }
3830 } catch (Exception e) {
3831 }
3832
3833 // Something went wrong; fall back to attributing the lock to the OS
3834 mWakeLock.setWorkSource(null);
3835 }
3836
Suprabh Shukla12bd0162018-11-12 18:00:18 -08003837 @VisibleForTesting
3838 class AlarmHandler extends Handler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 public static final int ALARM_EVENT = 1;
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003840 public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2;
3841 public static final int LISTENER_TIMEOUT = 3;
3842 public static final int REPORT_ALARMS_ACTIVE = 4;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003843 public static final int APP_STANDBY_BUCKET_CHANGED = 5;
3844 public static final int APP_STANDBY_PAROLE_CHANGED = 6;
Makoto Onuki4d298b52018-02-05 10:54:58 -08003845 public static final int REMOVE_FOR_STOPPED = 7;
Kweku Adams61e03292017-10-19 14:27:12 -07003846
Suprabh Shukla12bd0162018-11-12 18:00:18 -08003847 AlarmHandler() {
3848 super(Looper.myLooper());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003849 }
Kweku Adams61e03292017-10-19 14:27:12 -07003850
Makoto Onuki4d298b52018-02-05 10:54:58 -08003851 public void postRemoveForStopped(int uid) {
3852 obtainMessage(REMOVE_FOR_STOPPED, uid, 0).sendToTarget();
3853 }
3854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003855 public void handleMessage(Message msg) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003856 switch (msg.what) {
3857 case ALARM_EVENT: {
3858 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
3859 synchronized (mLock) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003860 final long nowRTC = mInjector.getCurrentTimeMillis();
3861 final long nowELAPSED = mInjector.getElapsedRealtime();
Christopher Tate14a7bb02015-10-01 10:24:31 -07003862 triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
3863 updateNextAlarmClockLocked();
3864 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02003865
Christopher Tate14a7bb02015-10-01 10:24:31 -07003866 // now trigger the alarms without the lock held
3867 for (int i=0; i<triggerList.size(); i++) {
3868 Alarm alarm = triggerList.get(i);
3869 try {
3870 alarm.operation.send();
3871 } catch (PendingIntent.CanceledException e) {
3872 if (alarm.repeatInterval > 0) {
3873 // This IntentSender is no longer valid, but this
3874 // is a repeating alarm, so toss the hoser.
Christopher Tatec8b7f432018-09-28 16:23:10 -07003875 removeImpl(alarm.operation, null);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003876 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 }
3878 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003879 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003880 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003881
3882 case SEND_NEXT_ALARM_CLOCK_CHANGED:
3883 sendNextAlarmClockChanged();
3884 break;
3885
3886 case LISTENER_TIMEOUT:
3887 mDeliveryTracker.alarmTimedOut((IBinder) msg.obj);
3888 break;
3889
Dianne Hackborn627dfa12015-11-11 18:10:30 -08003890 case REPORT_ALARMS_ACTIVE:
3891 if (mLocalDeviceIdleController != null) {
3892 mLocalDeviceIdleController.setAlarmsActive(msg.arg1 != 0);
3893 }
3894 break;
3895
Suprabh Shukla75edab12018-01-29 14:09:06 -08003896 case APP_STANDBY_PAROLE_CHANGED:
3897 synchronized (mLock) {
3898 mAppStandbyParole = (Boolean) msg.obj;
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003899 if (reorderAlarmsBasedOnStandbyBuckets(null)) {
3900 rescheduleKernelAlarmsLocked();
3901 updateNextAlarmClockLocked();
3902 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08003903 }
3904 break;
3905
3906 case APP_STANDBY_BUCKET_CHANGED:
3907 synchronized (mLock) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08003908 final ArraySet<Pair<String, Integer>> filterPackages = new ArraySet<>();
3909 filterPackages.add(Pair.create((String) msg.obj, msg.arg1));
3910 if (reorderAlarmsBasedOnStandbyBuckets(filterPackages)) {
3911 rescheduleKernelAlarmsLocked();
3912 updateNextAlarmClockLocked();
3913 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08003914 }
3915 break;
3916
Makoto Onuki4d298b52018-02-05 10:54:58 -08003917 case REMOVE_FOR_STOPPED:
3918 synchronized (mLock) {
3919 removeForStoppedLocked(msg.arg1);
3920 }
3921 break;
3922
Christopher Tate14a7bb02015-10-01 10:24:31 -07003923 default:
3924 // nope, just ignore it
3925 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 }
3927 }
3928 }
Kweku Adams61e03292017-10-19 14:27:12 -07003929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930 class ClockReceiver extends BroadcastReceiver {
3931 public ClockReceiver() {
3932 IntentFilter filter = new IntentFilter();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003933 filter.addAction(Intent.ACTION_DATE_CHANGED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003934 getContext().registerReceiver(this, filter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 }
Kweku Adams61e03292017-10-19 14:27:12 -07003936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 @Override
3938 public void onReceive(Context context, Intent intent) {
Christopher Tatec8b7f432018-09-28 16:23:10 -07003939 if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003940 // Since the kernel does not keep track of DST, we need to
3941 // reset the TZ information at the beginning of each day
3942 // based off of the current Zone gmt offset + userspace tracked
3943 // daylight savings information.
3944 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003945 int gmtOffset = zone.getOffset(mInjector.getCurrentTimeMillis());
3946 mInjector.setKernelTimezone(-(gmtOffset / 60000));
Christopher Tate385e4982013-07-23 18:22:29 -07003947 scheduleDateChangedEvent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003948 }
3949 }
Kweku Adams61e03292017-10-19 14:27:12 -07003950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 public void scheduleTimeTickEvent() {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003952 final long currentTime = mInjector.getCurrentTimeMillis();
Sungmin Choi563914a2013-01-10 17:28:40 +09003953 final long nextTime = 60000 * ((currentTime / 60000) + 1);
Paul Westbrook51608a52011-08-25 13:18:54 -07003954
3955 // Schedule this event for the amount of time that it would take to get to
3956 // the top of the next minute.
Sungmin Choi563914a2013-01-10 17:28:40 +09003957 final long tickEventDelay = nextTime - currentTime;
Paul Westbrook51608a52011-08-25 13:18:54 -07003958
David Christieebe51fc2013-07-26 13:23:29 -07003959 final WorkSource workSource = null; // Let system take blame for time tick events.
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003960 setImpl(ELAPSED_REALTIME, mInjector.getElapsedRealtime() + tickEventDelay, 0,
Suprabh Shukla12bd0162018-11-12 18:00:18 -08003961 0, null, mTimeTickTrigger, "TIME_TICK", AlarmManager.FLAG_STANDALONE,
3962 workSource, null, Process.myUid(), "android");
Christopher Tate12cf0b62018-01-05 18:40:14 -08003963
3964 // Finally, remember when we set the tick alarm
3965 synchronized (mLock) {
3966 mLastTickSet = currentTime;
3967 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 }
Christopher Tate385e4982013-07-23 18:22:29 -07003969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003970 public void scheduleDateChangedEvent() {
3971 Calendar calendar = Calendar.getInstance();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003972 calendar.setTimeInMillis(mInjector.getCurrentTimeMillis());
Christopher Tateafa8b982016-08-10 16:15:48 -07003973 calendar.set(Calendar.HOUR_OF_DAY, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003974 calendar.set(Calendar.MINUTE, 0);
3975 calendar.set(Calendar.SECOND, 0);
3976 calendar.set(Calendar.MILLISECOND, 0);
3977 calendar.add(Calendar.DAY_OF_MONTH, 1);
David Christieebe51fc2013-07-26 13:23:29 -07003978
3979 final WorkSource workSource = null; // Let system take blame for date change events.
Christopher Tate14a7bb02015-10-01 10:24:31 -07003980 setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
3981 AlarmManager.FLAG_STANDALONE, workSource, null,
3982 Process.myUid(), "android");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 }
3984 }
Kweku Adams61e03292017-10-19 14:27:12 -07003985
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003986 class InteractiveStateReceiver extends BroadcastReceiver {
3987 public InteractiveStateReceiver() {
3988 IntentFilter filter = new IntentFilter();
3989 filter.addAction(Intent.ACTION_SCREEN_OFF);
3990 filter.addAction(Intent.ACTION_SCREEN_ON);
3991 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
3992 getContext().registerReceiver(this, filter);
3993 }
3994
3995 @Override
3996 public void onReceive(Context context, Intent intent) {
3997 synchronized (mLock) {
3998 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
3999 }
4000 }
4001 }
4002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004003 class UninstallReceiver extends BroadcastReceiver {
4004 public UninstallReceiver() {
4005 IntentFilter filter = new IntentFilter();
4006 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
4007 filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004008 filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004009 filter.addDataScheme("package");
Adam Lesinski182f73f2013-12-05 16:48:06 -08004010 getContext().registerReceiver(this, filter);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004011 // Register for events related to sdcard installation.
4012 IntentFilter sdFilter = new IntentFilter();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08004013 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07004014 sdFilter.addAction(Intent.ACTION_USER_STOPPED);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07004015 sdFilter.addAction(Intent.ACTION_UID_REMOVED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08004016 getContext().registerReceiver(this, sdFilter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004017 }
Kweku Adams61e03292017-10-19 14:27:12 -07004018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 @Override
4020 public void onReceive(Context context, Intent intent) {
Christopher Tate1d99c392017-12-07 16:54:04 -08004021 final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004022 synchronized (mLock) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004023 String action = intent.getAction();
4024 String pkgList[] = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004025 if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
4026 pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
4027 for (String packageName : pkgList) {
4028 if (lookForPackageLocked(packageName)) {
4029 setResultCode(Activity.RESULT_OK);
4030 return;
4031 }
4032 }
4033 return;
4034 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004035 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07004036 } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
4037 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
4038 if (userHandle >= 0) {
4039 removeUserLocked(userHandle);
Suprabh Shukla75edab12018-01-29 14:09:06 -08004040 for (int i = mLastAlarmDeliveredForPackage.size() - 1; i >= 0; i--) {
4041 final Pair<String, Integer> packageUser =
4042 mLastAlarmDeliveredForPackage.keyAt(i);
4043 if (packageUser.second == userHandle) {
4044 mLastAlarmDeliveredForPackage.removeAt(i);
4045 }
4046 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07004047 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07004048 } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07004049 if (uid >= 0) {
4050 mLastAllowWhileIdleDispatch.delete(uid);
Makoto Onukiadb50d82018-01-29 16:20:30 -08004051 mUseAllowWhileIdleShortTime.delete(uid);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07004052 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004053 } else {
Dianne Hackborn409578f2010-03-10 17:23:43 -08004054 if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
4055 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
4056 // This package is being updated; don't kill its alarms.
4057 return;
4058 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004059 Uri data = intent.getData();
4060 if (data != null) {
4061 String pkg = data.getSchemeSpecificPart();
4062 if (pkg != null) {
4063 pkgList = new String[]{pkg};
4064 }
4065 }
4066 }
4067 if (pkgList != null && (pkgList.length > 0)) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08004068 for (int i = mLastAlarmDeliveredForPackage.size() - 1; i >= 0; i--) {
4069 Pair<String, Integer> packageUser = mLastAlarmDeliveredForPackage.keyAt(i);
4070 if (ArrayUtils.contains(pkgList, packageUser.first)
4071 && packageUser.second == UserHandle.getUserId(uid)) {
4072 mLastAlarmDeliveredForPackage.removeAt(i);
4073 }
4074 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004075 for (String pkg : pkgList) {
Christopher Tate1d99c392017-12-07 16:54:04 -08004076 if (uid >= 0) {
4077 // package-removed case
4078 removeLocked(uid);
4079 } else {
4080 // external-applications-unavailable etc case
4081 removeLocked(pkg);
4082 }
Christopher Tate1590f1e2014-10-02 17:27:57 -07004083 mPriorities.remove(pkg);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08004084 for (int i=mBroadcastStats.size()-1; i>=0; i--) {
4085 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
4086 if (uidStats.remove(pkg) != null) {
4087 if (uidStats.size() <= 0) {
4088 mBroadcastStats.removeAt(i);
4089 }
4090 }
4091 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093 }
4094 }
4095 }
4096 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004097
4098 final class UidObserver extends IUidObserver.Stub {
Dianne Hackborn3e99f652017-07-05 16:33:56 -07004099 @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004100 }
4101
Dianne Hackborn3e99f652017-07-05 16:33:56 -07004102 @Override public void onUidGone(int uid, boolean disabled) {
Makoto Onuki4d298b52018-02-05 10:54:58 -08004103 if (disabled) {
4104 mHandler.postRemoveForStopped(uid);
Dianne Hackborne07641d2016-11-09 15:07:23 -08004105 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004106 }
4107
Dianne Hackborn3e99f652017-07-05 16:33:56 -07004108 @Override public void onUidActive(int uid) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004109 }
4110
Dianne Hackborn3e99f652017-07-05 16:33:56 -07004111 @Override public void onUidIdle(int uid, boolean disabled) {
Makoto Onuki4d298b52018-02-05 10:54:58 -08004112 if (disabled) {
4113 mHandler.postRemoveForStopped(uid);
Dianne Hackbornde9c48b2015-11-20 14:49:59 -08004114 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004115 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -07004116
4117 @Override public void onUidCachedChanged(int uid, boolean cached) {
4118 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004119 };
4120
Suprabh Shukla75edab12018-01-29 14:09:06 -08004121 /**
4122 * Tracking of app assignments to standby buckets
4123 */
4124 final class AppStandbyTracker extends UsageStatsManagerInternal.AppIdleStateChangeListener {
4125 @Override
4126 public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
Amith Yamasani119be9a2018-02-18 22:23:00 -08004127 boolean idle, int bucket, int reason) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08004128 if (DEBUG_STANDBY) {
4129 Slog.d(TAG, "Package " + packageName + " for user " + userId + " now in bucket " +
4130 bucket);
4131 }
4132 mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08004133 mHandler.obtainMessage(AlarmHandler.APP_STANDBY_BUCKET_CHANGED, userId, -1, packageName)
4134 .sendToTarget();
Suprabh Shukla75edab12018-01-29 14:09:06 -08004135 }
4136
4137 @Override
4138 public void onParoleStateChanged(boolean isParoleOn) {
4139 if (DEBUG_STANDBY) {
4140 Slog.d(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
4141 }
4142 mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
4143 mHandler.removeMessages(AlarmHandler.APP_STANDBY_PAROLE_CHANGED);
4144 mHandler.obtainMessage(AlarmHandler.APP_STANDBY_PAROLE_CHANGED,
4145 Boolean.valueOf(isParoleOn)).sendToTarget();
4146 }
4147 };
4148
Makoto Onuki2206af32017-11-21 16:25:35 -08004149 private final Listener mForceAppStandbyListener = new Listener() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07004150 @Override
Makoto Onuki2206af32017-11-21 16:25:35 -08004151 public void unblockAllUnrestrictedAlarms() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07004152 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -08004153 sendAllUnrestrictedPendingBackgroundAlarmsLocked();
Suprabh Shukladb6bf662017-08-30 15:41:53 -07004154 }
4155 }
Makoto Onuki2206af32017-11-21 16:25:35 -08004156
4157 @Override
4158 public void unblockAlarmsForUid(int uid) {
4159 synchronized (mLock) {
4160 sendPendingBackgroundAlarmsLocked(uid, null);
4161 }
4162 }
4163
4164 @Override
4165 public void unblockAlarmsForUidPackage(int uid, String packageName) {
4166 synchronized (mLock) {
4167 sendPendingBackgroundAlarmsLocked(uid, packageName);
4168 }
4169 }
Makoto Onukiadb50d82018-01-29 16:20:30 -08004170
4171 @Override
4172 public void onUidForeground(int uid, boolean foreground) {
4173 synchronized (mLock) {
4174 if (foreground) {
4175 mUseAllowWhileIdleShortTime.put(uid, true);
4176
4177 // Note we don't have to drain the pending while-idle alarms here, because
4178 // this event should coincide with unblockAlarmsForUid().
4179 }
4180 }
4181 }
Makoto Onuki2206af32017-11-21 16:25:35 -08004182 };
Suprabh Shukladb6bf662017-08-30 15:41:53 -07004183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004184 private final BroadcastStats getStatsLocked(PendingIntent pi) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08004185 String pkg = pi.getCreatorPackage();
4186 int uid = pi.getCreatorUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07004187 return getStatsLocked(uid, pkg);
4188 }
4189
4190 private final BroadcastStats getStatsLocked(int uid, String pkgName) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08004191 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
4192 if (uidStats == null) {
4193 uidStats = new ArrayMap<String, BroadcastStats>();
4194 mBroadcastStats.put(uid, uidStats);
4195 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004196 BroadcastStats bs = uidStats.get(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 if (bs == null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004198 bs = new BroadcastStats(uid, pkgName);
4199 uidStats.put(pkgName, bs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200 }
4201 return bs;
4202 }
Dianne Hackborn81038902012-11-26 17:04:09 -08004203
Christopher Tate21e9f192017-08-08 13:49:11 -07004204 /**
4205 * Canonical count of (operation.send() - onSendFinished()) and
4206 * listener send/complete/timeout invocations.
4207 * Guarded by the usual lock.
4208 */
4209 @GuardedBy("mLock")
4210 private int mSendCount = 0;
4211 @GuardedBy("mLock")
Christopher Tateeabba732017-08-17 17:12:52 -07004212 private int mSendFinishCount = 0;
4213 @GuardedBy("mLock")
Christopher Tate21e9f192017-08-08 13:49:11 -07004214 private int mListenerCount = 0;
Christopher Tateeabba732017-08-17 17:12:52 -07004215 @GuardedBy("mLock")
4216 private int mListenerFinishCount = 0;
Christopher Tate21e9f192017-08-08 13:49:11 -07004217
Christopher Tate14a7bb02015-10-01 10:24:31 -07004218 class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished {
Christopher Tate21e9f192017-08-08 13:49:11 -07004219
Christopher Tate14a7bb02015-10-01 10:24:31 -07004220 private InFlight removeLocked(PendingIntent pi, Intent intent) {
4221 for (int i = 0; i < mInFlight.size(); i++) {
Christopher Tatedb9ae422017-08-21 11:24:30 -07004222 if (mInFlight.get(i).mPendingIntent == pi) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004223 return mInFlight.remove(i);
4224 }
4225 }
4226 mLog.w("No in-flight alarm for " + pi + " " + intent);
4227 return null;
4228 }
4229
4230 private InFlight removeLocked(IBinder listener) {
4231 for (int i = 0; i < mInFlight.size(); i++) {
4232 if (mInFlight.get(i).mListener == listener) {
4233 return mInFlight.remove(i);
4234 }
4235 }
4236 mLog.w("No in-flight alarm for listener " + listener);
4237 return null;
4238 }
4239
4240 private void updateStatsLocked(InFlight inflight) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07004241 final long nowELAPSED = mInjector.getElapsedRealtime();
Christopher Tate14a7bb02015-10-01 10:24:31 -07004242 BroadcastStats bs = inflight.mBroadcastStats;
4243 bs.nesting--;
4244 if (bs.nesting <= 0) {
4245 bs.nesting = 0;
4246 bs.aggregateTime += nowELAPSED - bs.startTime;
4247 }
4248 FilterStats fs = inflight.mFilterStats;
4249 fs.nesting--;
4250 if (fs.nesting <= 0) {
4251 fs.nesting = 0;
4252 fs.aggregateTime += nowELAPSED - fs.startTime;
4253 }
4254 if (RECORD_ALARMS_IN_HISTORY) {
Narayan Kamath695cf722017-12-21 18:32:47 +00004255 ActivityManager.noteAlarmFinish(inflight.mPendingIntent, inflight.mWorkSource,
4256 inflight.mUid, inflight.mTag);
Christopher Tate14a7bb02015-10-01 10:24:31 -07004257 }
4258 }
4259
4260 private void updateTrackingLocked(InFlight inflight) {
4261 if (inflight != null) {
4262 updateStatsLocked(inflight);
4263 }
4264 mBroadcastRefCount--;
Makoto Onuki3e7d8452017-03-02 15:33:17 -08004265 if (DEBUG_WAKELOCK) {
4266 Slog.d(TAG, "mBroadcastRefCount -> " + mBroadcastRefCount);
4267 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004268 if (mBroadcastRefCount == 0) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004269 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07004270 mWakeLock.release();
4271 if (mInFlight.size() > 0) {
4272 mLog.w("Finished all dispatches with " + mInFlight.size()
4273 + " remaining inflights");
4274 for (int i=0; i<mInFlight.size(); i++) {
4275 mLog.w(" Remaining #" + i + ": " + mInFlight.get(i));
4276 }
4277 mInFlight.clear();
4278 }
4279 } else {
4280 // the next of our alarms is now in flight. reattribute the wakelock.
4281 if (mInFlight.size() > 0) {
4282 InFlight inFlight = mInFlight.get(0);
4283 setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
4284 inFlight.mAlarmType, inFlight.mTag, -1, false);
4285 } else {
4286 // should never happen
4287 mLog.w("Alarm wakelock still held but sent queue empty");
4288 mWakeLock.setWorkSource(null);
4289 }
4290 }
4291 }
4292
4293 /**
4294 * Callback that arrives when a direct-call alarm reports that delivery has finished
4295 */
4296 @Override
4297 public void alarmComplete(IBinder who) {
4298 if (who == null) {
Christopher Tate21e9f192017-08-08 13:49:11 -07004299 mLog.w("Invalid alarmComplete: uid=" + Binder.getCallingUid()
Christopher Tate14a7bb02015-10-01 10:24:31 -07004300 + " pid=" + Binder.getCallingPid());
4301 return;
4302 }
4303
4304 final long ident = Binder.clearCallingIdentity();
4305 try {
4306 synchronized (mLock) {
4307 mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who);
4308 InFlight inflight = removeLocked(who);
4309 if (inflight != null) {
4310 if (DEBUG_LISTENER_CALLBACK) {
4311 Slog.i(TAG, "alarmComplete() from " + who);
4312 }
4313 updateTrackingLocked(inflight);
Christopher Tateeabba732017-08-17 17:12:52 -07004314 mListenerFinishCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004315 } else {
4316 // Delivery timed out, and the timeout handling already took care of
4317 // updating our tracking here, so we needn't do anything further.
4318 if (DEBUG_LISTENER_CALLBACK) {
4319 Slog.i(TAG, "Late alarmComplete() from " + who);
4320 }
4321 }
4322 }
4323 } finally {
4324 Binder.restoreCallingIdentity(ident);
4325 }
4326 }
4327
4328 /**
4329 * Callback that arrives when a PendingIntent alarm has finished delivery
4330 */
4331 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004332 public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
4333 String resultData, Bundle resultExtras) {
4334 synchronized (mLock) {
Christopher Tateeabba732017-08-17 17:12:52 -07004335 mSendFinishCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004336 updateTrackingLocked(removeLocked(pi, intent));
4337 }
4338 }
4339
4340 /**
4341 * Timeout of a direct-call alarm delivery
4342 */
4343 public void alarmTimedOut(IBinder who) {
4344 synchronized (mLock) {
4345 InFlight inflight = removeLocked(who);
Dianne Hackborn81038902012-11-26 17:04:09 -08004346 if (inflight != null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004347 // TODO: implement ANR policy for the target
4348 if (DEBUG_LISTENER_CALLBACK) {
4349 Slog.i(TAG, "Alarm listener " + who + " timed out in delivery");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004351 updateTrackingLocked(inflight);
Christopher Tateeabba732017-08-17 17:12:52 -07004352 mListenerFinishCount++;
Dianne Hackborn81038902012-11-26 17:04:09 -08004353 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004354 if (DEBUG_LISTENER_CALLBACK) {
4355 Slog.i(TAG, "Spurious timeout of listener " + who);
4356 }
Christopher Tate21e9f192017-08-08 13:49:11 -07004357 mLog.w("Spurious timeout of listener " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004359 }
4360 }
4361
4362 /**
4363 * Deliver an alarm and set up the post-delivery handling appropriately
4364 */
Andreas Gampea36dc622018-02-05 17:19:22 -08004365 @GuardedBy("mLock")
Christopher Tate14a7bb02015-10-01 10:24:31 -07004366 public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
4367 if (alarm.operation != null) {
4368 // PendingIntent alarm
Christopher Tate21e9f192017-08-08 13:49:11 -07004369 mSendCount++;
Christopher Tate12cf0b62018-01-05 18:40:14 -08004370
Christopher Tate14a7bb02015-10-01 10:24:31 -07004371 try {
4372 alarm.operation.send(getContext(), 0,
4373 mBackgroundIntent.putExtra(
4374 Intent.EXTRA_ALARM_COUNT, alarm.count),
4375 mDeliveryTracker, mHandler, null,
4376 allowWhileIdle ? mIdleOptions : null);
4377 } catch (PendingIntent.CanceledException e) {
4378 if (alarm.repeatInterval > 0) {
4379 // This IntentSender is no longer valid, but this
4380 // is a repeating alarm, so toss it
Christopher Tatec8b7f432018-09-28 16:23:10 -07004381 removeImpl(alarm.operation, null);
Christopher Tate14a7bb02015-10-01 10:24:31 -07004382 }
Christopher Tate7f2a0352015-12-08 10:24:33 -08004383 // No actual delivery was possible, so the delivery tracker's
4384 // 'finished' callback won't be invoked. We also don't need
4385 // to do any wakelock or stats tracking, so we have nothing
4386 // left to do here but go on to the next thing.
Christopher Tateeabba732017-08-17 17:12:52 -07004387 mSendFinishCount++;
Christopher Tate7f2a0352015-12-08 10:24:33 -08004388 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004389 }
4390 } else {
4391 // Direct listener callback alarm
Christopher Tate21e9f192017-08-08 13:49:11 -07004392 mListenerCount++;
Christopher Tatec8b7f432018-09-28 16:23:10 -07004393
4394 if (RECORD_ALARMS_IN_HISTORY) {
4395 if (alarm.listener == mTimeTickTrigger) {
4396 mTickHistory[mNextTickHistory++] = nowELAPSED;
4397 if (mNextTickHistory >= TICK_HISTORY_DEPTH) {
4398 mNextTickHistory = 0;
4399 }
4400 }
4401 }
4402
Christopher Tate14a7bb02015-10-01 10:24:31 -07004403 try {
4404 if (DEBUG_LISTENER_CALLBACK) {
4405 Slog.v(TAG, "Alarm to uid=" + alarm.uid
4406 + " listener=" + alarm.listener.asBinder());
4407 }
4408 alarm.listener.doAlarm(this);
4409 mHandler.sendMessageDelayed(
4410 mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
4411 alarm.listener.asBinder()),
4412 mConstants.LISTENER_TIMEOUT);
4413 } catch (Exception e) {
4414 if (DEBUG_LISTENER_CALLBACK) {
4415 Slog.i(TAG, "Alarm undeliverable to listener "
4416 + alarm.listener.asBinder(), e);
4417 }
Christopher Tate7f2a0352015-12-08 10:24:33 -08004418 // As in the PendingIntent.CanceledException case, delivery of the
4419 // alarm was not possible, so we have no wakelock or timeout or
4420 // stats management to do. It threw before we posted the delayed
4421 // timeout message, so we're done here.
Christopher Tateeabba732017-08-17 17:12:52 -07004422 mListenerFinishCount++;
Christopher Tate7f2a0352015-12-08 10:24:33 -08004423 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004424 }
4425 }
4426
4427 // The alarm is now in flight; now arrange wakelock and stats tracking
Makoto Onuki3e7d8452017-03-02 15:33:17 -08004428 if (DEBUG_WAKELOCK) {
4429 Slog.d(TAG, "mBroadcastRefCount -> " + (mBroadcastRefCount + 1));
4430 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004431 if (mBroadcastRefCount == 0) {
4432 setWakelockWorkSource(alarm.operation, alarm.workSource,
4433 alarm.type, alarm.statsTag, (alarm.operation == null) ? alarm.uid : -1,
4434 true);
4435 mWakeLock.acquire();
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004436 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07004437 }
4438 final InFlight inflight = new InFlight(AlarmManagerService.this,
4439 alarm.operation, alarm.listener, alarm.workSource, alarm.uid,
4440 alarm.packageName, alarm.type, alarm.statsTag, nowELAPSED);
4441 mInFlight.add(inflight);
4442 mBroadcastRefCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004443 if (allowWhileIdle) {
4444 // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
Suprabh Shuklac25447d2018-01-19 16:43:35 -08004445 mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED);
Makoto Onukie4918212018-02-06 11:30:15 -08004446 if ((mAppStateTracker == null)
4447 || mAppStateTracker.isUidInForeground(alarm.creatorUid)) {
Suprabh Shuklac25447d2018-01-19 16:43:35 -08004448 mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true);
4449 } else {
4450 mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false);
4451 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004452 if (RECORD_DEVICE_IDLE_ALARMS) {
4453 IdleDispatchEntry ent = new IdleDispatchEntry();
4454 ent.uid = alarm.uid;
4455 ent.pkg = alarm.packageName;
4456 ent.tag = alarm.statsTag;
4457 ent.op = "DELIVER";
4458 ent.elapsedRealtime = nowELAPSED;
4459 mAllowWhileIdleDispatches.add(ent);
4460 }
4461 }
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08004462 if (!isExemptFromAppStandby(alarm)) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08004463 final Pair<String, Integer> packageUser = Pair.create(alarm.sourcePackage,
4464 UserHandle.getUserId(alarm.creatorUid));
4465 mLastAlarmDeliveredForPackage.put(packageUser, nowELAPSED);
4466 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004467
4468 final BroadcastStats bs = inflight.mBroadcastStats;
4469 bs.count++;
4470 if (bs.nesting == 0) {
4471 bs.nesting = 1;
4472 bs.startTime = nowELAPSED;
4473 } else {
4474 bs.nesting++;
4475 }
4476 final FilterStats fs = inflight.mFilterStats;
4477 fs.count++;
4478 if (fs.nesting == 0) {
4479 fs.nesting = 1;
4480 fs.startTime = nowELAPSED;
4481 } else {
4482 fs.nesting++;
4483 }
4484 if (alarm.type == ELAPSED_REALTIME_WAKEUP
4485 || alarm.type == RTC_WAKEUP) {
4486 bs.numWakeup++;
4487 fs.numWakeup++;
Narayan Kamath695cf722017-12-21 18:32:47 +00004488 ActivityManager.noteWakeupAlarm(
4489 alarm.operation, alarm.workSource, alarm.uid, alarm.packageName,
4490 alarm.statsTag);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 }
4492 }
4493 }
mswest463f4c99d2018-02-01 10:13:10 -08004494
4495 private class ShellCmd extends ShellCommand {
4496
4497 IAlarmManager getBinderService() {
4498 return IAlarmManager.Stub.asInterface(mService);
4499 }
4500
4501 @Override
4502 public int onCommand(String cmd) {
4503 if (cmd == null) {
4504 return handleDefaultCommands(cmd);
4505 }
4506
4507 final PrintWriter pw = getOutPrintWriter();
4508 try {
4509 switch (cmd) {
4510 case "set-time":
4511 final long millis = Long.parseLong(getNextArgRequired());
4512 return (getBinderService().setTime(millis)) ? 0 : -1;
4513 case "set-timezone":
4514 final String tz = getNextArgRequired();
4515 getBinderService().setTimeZone(tz);
4516 return 0;
4517 default:
4518 return handleDefaultCommands(cmd);
4519 }
4520 } catch (Exception e) {
4521 pw.println(e);
4522 }
4523 return -1;
4524 }
4525
4526 @Override
4527 public void onHelp() {
4528 PrintWriter pw = getOutPrintWriter();
4529 pw.println("Alarm manager service (alarm) commands:");
4530 pw.println(" help");
4531 pw.println(" Print this help text.");
4532 pw.println(" set-time TIME");
4533 pw.println(" Set the system clock time to TIME where TIME is milliseconds");
4534 pw.println(" since the Epoch.");
4535 pw.println(" set-timezone TZ");
4536 pw.println(" Set the system timezone to TZ where TZ is an Olson id.");
4537 }
4538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004539}