blob: d51ca6e9ab4201bc0e0947e80e98a186e8f1a2ac [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;
Winson Chungf2b41772019-11-06 15:00:48 -080025import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
26import static android.os.UserHandle.USER_SYSTEM;
Jeff Sharkey9911a282018-02-14 22:29:11 -070027
Suprabh Shukla75edab12018-01-29 14:09:06 -080028import android.annotation.UserIdInt;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080029import android.app.Activity;
Adrian Roosc42a1e12014-07-07 23:35:53 +020030import android.app.ActivityManager;
Christopher Tate57ceaaa2013-07-19 16:30:43 -070031import android.app.AlarmManager;
Christopher Tate14a7bb02015-10-01 10:24:31 -070032import android.app.AppOpsManager;
Dianne Hackborna750a632015-06-16 17:18:23 -070033import android.app.BroadcastOptions;
Christopher Tate14a7bb02015-10-01 10:24:31 -070034import android.app.IAlarmCompleteListener;
35import android.app.IAlarmListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.app.IAlarmManager;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070037import android.app.IUidObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.app.PendingIntent;
Suprabh Shukla75edab12018-01-29 14:09:06 -080039import android.app.usage.UsageStatsManager;
40import android.app.usage.UsageStatsManagerInternal;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.content.BroadcastReceiver;
Dianne Hackborna750a632015-06-16 17:18:23 -070042import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.content.Context;
44import android.content.Intent;
45import android.content.IntentFilter;
Winson Chungf2b41772019-11-06 15:00:48 -080046import android.content.pm.PackageManagerInternal;
Dianne Hackborna750a632015-06-16 17:18:23 -070047import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.net.Uri;
Kweku Adamsdf33ae12019-10-08 11:51:41 -070049import android.os.BatteryManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.os.Binder;
Christopher Tate3d65d4d2018-12-11 14:55:19 -080051import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.os.Bundle;
Christopher Tate247571462017-04-10 11:45:05 -070053import android.os.Environment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.os.Handler;
Adam Lesinski182f73f2013-12-05 16:48:06 -080055import android.os.IBinder;
Suprabh Shukla6226c2f2018-08-22 18:15:04 -070056import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.os.Message;
Jeff Sharkey9911a282018-02-14 22:29:11 -070058import android.os.ParcelableException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.os.PowerManager;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -070060import android.os.Process;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070061import android.os.RemoteException;
mswest463f4c99d2018-02-01 10:13:10 -080062import android.os.ResultReceiver;
63import android.os.ShellCallback;
64import android.os.ShellCommand;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.os.SystemClock;
66import android.os.SystemProperties;
Marcin Oczeretko735b19b2018-12-14 15:38:15 +000067import android.os.ThreadLocalWorkSource;
Tim Murray175c0f92017-11-28 15:01:04 -080068import android.os.Trace;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070069import android.os.UserHandle;
Christopher Tatec4a07d12012-04-06 14:19:13 -070070import android.os.WorkSource;
Adrian Roosc42a1e12014-07-07 23:35:53 +020071import android.provider.Settings;
Christopher Tate8b98ade2018-02-09 11:13:19 -080072import android.system.Os;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.text.TextUtils;
Adrian Roosc42a1e12014-07-07 23:35:53 +020074import android.text.format.DateFormat;
Christopher Tate22e919d2018-02-16 16:16:50 -080075import android.text.format.DateUtils;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080076import android.util.ArrayMap;
Suprabh Shukla92994ab2018-01-31 17:39:30 -080077import android.util.ArraySet;
Dianne Hackborna750a632015-06-16 17:18:23 -070078import android.util.KeyValueListParser;
Adrian Roosc42a1e12014-07-07 23:35:53 +020079import android.util.Log;
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -080080import android.util.LongArrayQueue;
Christopher Tate490227c2018-11-02 14:05:47 -070081import android.util.MutableBoolean;
Jeff Sharkey9911a282018-02-14 22:29:11 -070082import android.util.NtpTrustedTime;
Suprabh Shukla75edab12018-01-29 14:09:06 -080083import android.util.Pair;
Joe Onorato8a9b2202010-02-26 18:56:32 -080084import android.util.Slog;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -080085import android.util.SparseArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +020086import android.util.SparseBooleanArray;
Suprabh Shukla0e49b642019-03-04 14:14:32 -080087import android.util.SparseIntArray;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -070088import android.util.SparseLongArray;
Dianne Hackborn043fcd92010-10-06 14:27:34 -070089import android.util.TimeUtils;
Kweku Adams61e03292017-10-19 14:27:12 -070090import android.util.proto.ProtoOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091
Jeff Sharkey9911a282018-02-14 22:29:11 -070092import com.android.internal.annotations.GuardedBy;
93import com.android.internal.annotations.VisibleForTesting;
94import com.android.internal.util.ArrayUtils;
95import com.android.internal.util.DumpUtils;
Muhammad Qureshie2b24322020-01-28 10:54:17 -080096import com.android.internal.util.FrameworkStatsLog;
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -080097import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey9911a282018-02-14 22:29:11 -070098import com.android.internal.util.LocalLog;
Makoto Onuki49392d32018-04-11 13:51:02 -070099import com.android.internal.util.StatLogger;
Jeff Sharkey9911a282018-02-14 22:29:11 -0700100import com.android.server.AppStateTracker.Listener;
Christopher Tateb909c4d52019-10-21 12:50:37 -0700101import com.android.server.usage.AppStandbyInternal;
102import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
Jeff Sharkey9911a282018-02-14 22:29:11 -0700103
Christopher Tate4cb338d2013-07-26 13:11:31 -0700104import java.io.ByteArrayOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import java.io.FileDescriptor;
106import java.io.PrintWriter;
Suprabh Shukla8ec95612020-06-17 19:56:30 -0700107import java.io.StringWriter;
Dianne Hackborn043fcd92010-10-06 14:27:34 -0700108import java.text.SimpleDateFormat;
Jeff Sharkey9911a282018-02-14 22:29:11 -0700109import java.time.DateTimeException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import java.util.ArrayList;
Dianne Hackborn81038902012-11-26 17:04:09 -0800111import java.util.Arrays;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.util.Calendar;
113import java.util.Collections;
114import java.util.Comparator;
Mike Lockwood1f7b4132009-11-20 15:12:51 -0500115import java.util.Date;
Christopher Tate1590f1e2014-10-02 17:27:57 -0700116import java.util.HashMap;
Christopher Tate18a75f12013-07-01 18:18:59 -0700117import java.util.LinkedList;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200118import java.util.Locale;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700119import java.util.Random;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.util.TimeZone;
John Spurlock604a5ee2015-06-01 12:27:22 -0400121import java.util.TreeSet;
Makoto Onuki2206af32017-11-21 16:25:35 -0800122import java.util.function.Predicate;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123
Makoto Onuki2206af32017-11-21 16:25:35 -0800124/**
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700125 * Alarm manager implementation.
Makoto Onuki2206af32017-11-21 16:25:35 -0800126 *
127 * Unit test:
128 atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AlarmManagerServiceTest.java
129 */
Adam Lesinski182f73f2013-12-05 16:48:06 -0800130class AlarmManagerService extends SystemService {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700131 private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
132 private static final int RTC_MASK = 1 << RTC;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800133 private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700134 private static final int ELAPSED_REALTIME_MASK = 1 << ELAPSED_REALTIME;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800135 static final int TIME_CHANGED_MASK = 1 << 16;
136 static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK|ELAPSED_REALTIME_WAKEUP_MASK;
Christopher Tateb8849c12011-02-08 13:39:01 -0800137
Christopher Tatee0a22b32013-07-11 14:43:13 -0700138 // Mask for testing whether a given alarm type is wakeup vs non-wakeup
Adam Lesinski182f73f2013-12-05 16:48:06 -0800139 static final int TYPE_NONWAKEUP_MASK = 0x1; // low bit => non-wakeup
Christopher Tateb8849c12011-02-08 13:39:01 -0800140
Adam Lesinski182f73f2013-12-05 16:48:06 -0800141 static final String TAG = "AlarmManager";
Adam Lesinski182f73f2013-12-05 16:48:06 -0800142 static final boolean localLOGV = false;
143 static final boolean DEBUG_BATCH = localLOGV || false;
144 static final boolean DEBUG_VALIDATE = localLOGV || false;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200145 static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700146 static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
Makoto Onuki3e7d8452017-03-02 15:33:17 -0800147 static final boolean DEBUG_WAKELOCK = localLOGV || false;
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700148 static final boolean DEBUG_BG_LIMIT = localLOGV || false;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800149 static final boolean DEBUG_STANDBY = localLOGV || false;
Suprabh Shukla8ec95612020-06-17 19:56:30 -0700150
151 // TODO (b/157782538): Turn off once bug is fixed.
152 static final boolean DEBUG_PER_UID_LIMIT = true;
153 // TODO (b/157782538): Turn off once bug is fixed.
154 static final boolean WARN_SYSTEM_ON_ALARM_LIMIT = true;
155
Dianne Hackborn1e383822015-04-10 14:02:33 -0700156 static final boolean RECORD_ALARMS_IN_HISTORY = true;
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700157 static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800158 static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
Adrian Roosc42a1e12014-07-07 23:35:53 +0200159
Christopher Tatec8b7f432018-09-28 16:23:10 -0700160 static final int TICK_HISTORY_DEPTH = 10;
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800161 static final long MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
Christopher Tatec8b7f432018-09-28 16:23:10 -0700162
Kweku Adams9e5ef1d2019-10-15 15:41:28 -0700163 // Indices into the KEYS_APP_STANDBY_QUOTAS array.
Christopher Tatef2159712018-03-27 16:04:14 -0700164 static final int ACTIVE_INDEX = 0;
165 static final int WORKING_INDEX = 1;
166 static final int FREQUENT_INDEX = 2;
167 static final int RARE_INDEX = 3;
168 static final int NEVER_INDEX = 4;
169
Christopher Tate14a7bb02015-10-01 10:24:31 -0700170 private final Intent mBackgroundIntent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
Adam Lesinski182f73f2013-12-05 16:48:06 -0800172 static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700173
Adam Lesinski182f73f2013-12-05 16:48:06 -0800174 static final boolean WAKEUP_STATS = false;
Christopher Tate18a75f12013-07-01 18:18:59 -0700175
Christopher Tate24cd46f2016-02-02 14:28:01 -0800176 private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT =
177 new Intent(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)
Christopher Tate50191db2017-05-09 16:02:25 -0700178 .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
179 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
Adrian Roosc42a1e12014-07-07 23:35:53 +0200180
Adam Lesinski182f73f2013-12-05 16:48:06 -0800181 final LocalLog mLog = new LocalLog(TAG);
Dianne Hackborn81038902012-11-26 17:04:09 -0800182
Christopher Tate14a7bb02015-10-01 10:24:31 -0700183 AppOpsManager mAppOps;
Makoto Onukieaf7eed2019-08-12 15:27:15 -0700184 DeviceIdleInternal mLocalDeviceIdleController;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800185 private UsageStatsManagerInternal mUsageStatsManagerInternal;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700186
Adam Lesinski182f73f2013-12-05 16:48:06 -0800187 final Object mLock = new Object();
Dianne Hackborn81038902012-11-26 17:04:09 -0800188
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700189 // List of alarms per uid deferred due to user applied background restrictions on the source app
190 SparseArray<ArrayList<Alarm>> mPendingBackgroundAlarms = new SparseArray<>();
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800191 private long mNextWakeup;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700192 private long mNextNonWakeup;
Suprabh Shukla0e4510d2018-06-20 17:28:26 -0700193 private long mNextWakeUpSetAt;
194 private long mNextNonWakeUpSetAt;
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -0700195 private long mLastWakeup;
Christopher Tate8b98ade2018-02-09 11:13:19 -0800196 private long mLastTrigger;
Christopher Tatec8b7f432018-09-28 16:23:10 -0700197
Christopher Tate12cf0b62018-01-05 18:40:14 -0800198 private long mLastTickSet;
Christopher Tate12cf0b62018-01-05 18:40:14 -0800199 private long mLastTickReceived;
Makoto Onuki5d93b832018-01-10 16:12:39 -0800200 private long mLastTickAdded;
201 private long mLastTickRemoved;
Christopher Tatec8b7f432018-09-28 16:23:10 -0700202 // ring buffer of recent TIME_TICK issuance, in the elapsed timebase
203 private final long[] mTickHistory = new long[TICK_HISTORY_DEPTH];
204 private int mNextTickHistory;
205
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700206 private final Injector mInjector;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800207 int mBroadcastRefCount = 0;
208 PowerManager.WakeLock mWakeLock;
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800209 SparseIntArray mAlarmsPerUid = new SparseIntArray();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700210 ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
211 ArrayList<InFlight> mInFlight = new ArrayList<>();
Christopher Tate2f558d22019-01-17 16:58:31 -0800212 private final ArrayList<AlarmManagerInternal.InFlightListener> mInFlightListeners =
213 new ArrayList<>();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700214 AlarmHandler mHandler;
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800215 AppWakeupHistory mAppWakeupHistory;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800216 ClockReceiver mClockReceiver;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700217 final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
Suprabh Shukla5bfaaa62019-12-23 17:32:30 -0800218 IBinder.DeathRecipient mListenerDeathRecipient;
Christopher Tatec8b7f432018-09-28 16:23:10 -0700219 Intent mTimeTickIntent;
220 IAlarmListener mTimeTickTrigger;
Adam Lesinski182f73f2013-12-05 16:48:06 -0800221 PendingIntent mDateChangeSender;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700222 Random mRandom;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -0700223 boolean mInteractive = true;
224 long mNonInteractiveStartTime;
225 long mNonInteractiveTime;
226 long mLastAlarmDeliveryTime;
227 long mStartCurrentDelayTime;
228 long mNextNonWakeupDeliveryTime;
Dianne Hackbornc3527222015-05-13 14:03:20 -0700229 long mLastTimeChangeClockTime;
230 long mLastTimeChangeRealtime;
Dianne Hackborn998e6082014-09-11 19:13:23 -0700231 int mNumTimeChanged;
Dianne Hackborn81038902012-11-26 17:04:09 -0800232
Christopher Tatebb9cce52017-04-18 14:19:43 -0700233 /**
234 * At boot we use SYSTEM_UI_SELF_PERMISSION to look up the definer's uid.
235 */
236 int mSystemUiUid;
237
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700238 /**
239 * For each uid, this is the last time we dispatched an "allow while idle" alarm,
Kweku Adams61e03292017-10-19 14:27:12 -0700240 * used to determine the earliest we can dispatch the next such alarm. Times are in the
241 * 'elapsed' timebase.
Dianne Hackborn3d1933c42015-06-10 16:25:57 -0700242 */
243 final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
244
Suprabh Shuklac25447d2018-01-19 16:43:35 -0800245 /**
246 * For each uid, we store whether the last allow-while-idle alarm was dispatched while
247 * the uid was in foreground or not. We will use the allow_while_idle_short_time in such cases.
248 */
249 final SparseBooleanArray mUseAllowWhileIdleShortTime = new SparseBooleanArray();
250
Dianne Hackbornae78bf82015-10-26 13:33:20 -0700251 final static class IdleDispatchEntry {
252 int uid;
253 String pkg;
254 String tag;
255 String op;
256 long elapsedRealtime;
257 long argRealtime;
258 }
259 final ArrayList<IdleDispatchEntry> mAllowWhileIdleDispatches = new ArrayList();
260
Suprabh Shukla75edab12018-01-29 14:09:06 -0800261 interface Stats {
262 int REBATCH_ALL_ALARMS = 0;
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800263 int REORDER_ALARMS_FOR_STANDBY = 1;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800264 }
265
266 private final StatLogger mStatLogger = new StatLogger(new String[] {
267 "REBATCH_ALL_ALARMS",
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800268 "REORDER_ALARMS_FOR_STANDBY",
Suprabh Shukla75edab12018-01-29 14:09:06 -0800269 });
270
Dianne Hackborna750a632015-06-16 17:18:23 -0700271 /**
272 * Broadcast options to use for FLAG_ALLOW_WHILE_IDLE.
273 */
274 Bundle mIdleOptions;
275
Jose Lima235510e2014-08-13 12:50:01 -0700276 private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
277 new SparseArray<>();
278 private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
279 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200280 private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
281 new SparseBooleanArray();
282 private boolean mNextAlarmClockMayChange;
283
284 // May only use on mHandler's thread, locking not required.
Jose Lima235510e2014-08-13 12:50:01 -0700285 private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
286 new SparseArray<>();
Adrian Roosc42a1e12014-07-07 23:35:53 +0200287
Makoto Onukie4918212018-02-06 11:30:15 -0800288 private AppStateTracker mAppStateTracker;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800289 private boolean mAppStandbyParole;
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800290
291 /**
292 * A rolling window history of previous times when an alarm was sent to a package.
293 */
294 private static class AppWakeupHistory {
295 private ArrayMap<Pair<String, Integer>, LongArrayQueue> mPackageHistory =
296 new ArrayMap<>();
297 private long mWindowSize;
298
299 AppWakeupHistory(long windowSize) {
300 mWindowSize = windowSize;
301 }
302
303 void recordAlarmForPackage(String packageName, int userId, long nowElapsed) {
304 final Pair<String, Integer> packageUser = Pair.create(packageName, userId);
305 LongArrayQueue history = mPackageHistory.get(packageUser);
306 if (history == null) {
307 history = new LongArrayQueue();
308 mPackageHistory.put(packageUser, history);
309 }
310 if (history.size() == 0 || history.peekLast() < nowElapsed) {
311 history.addLast(nowElapsed);
312 }
313 snapToWindow(history);
314 }
315
316 void removeForUser(int userId) {
317 for (int i = mPackageHistory.size() - 1; i >= 0; i--) {
318 final Pair<String, Integer> packageUserKey = mPackageHistory.keyAt(i);
319 if (packageUserKey.second == userId) {
320 mPackageHistory.removeAt(i);
321 }
322 }
323 }
324
325 void removeForPackage(String packageName, int userId) {
326 final Pair<String, Integer> packageUser = Pair.create(packageName, userId);
327 mPackageHistory.remove(packageUser);
328 }
329
330 private void snapToWindow(LongArrayQueue history) {
331 while (history.peekFirst() + mWindowSize < history.peekLast()) {
332 history.removeFirst();
333 }
334 }
335
336 int getTotalWakeupsInWindow(String packageName, int userId) {
337 final LongArrayQueue history = mPackageHistory.get(Pair.create(packageName, userId));
338 return (history == null) ? 0 : history.size();
339 }
340
Kweku Adams610aee72020-01-15 16:43:27 -0800341 /**
342 * @param n The desired nth-last wakeup
343 * (1=1st-last=the ultimate wakeup and 2=2nd-last=the penultimate wakeup)
344 */
345 long getNthLastWakeupForPackage(String packageName, int userId, int n) {
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800346 final LongArrayQueue history = mPackageHistory.get(Pair.create(packageName, userId));
347 if (history == null) {
348 return 0;
349 }
Kweku Adams610aee72020-01-15 16:43:27 -0800350 final int i = history.size() - n;
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800351 return (i < 0) ? 0 : history.get(i);
352 }
353
354 void dump(PrintWriter pw, String prefix, long nowElapsed) {
355 dump(new IndentingPrintWriter(pw, " ").setIndent(prefix), nowElapsed);
356 }
357
358 void dump(IndentingPrintWriter pw, long nowElapsed) {
359 pw.println("App Alarm history:");
360 pw.increaseIndent();
361 for (int i = 0; i < mPackageHistory.size(); i++) {
362 final Pair<String, Integer> packageUser = mPackageHistory.keyAt(i);
363 final LongArrayQueue timestamps = mPackageHistory.valueAt(i);
364 pw.print(packageUser.first);
365 pw.print(", u");
366 pw.print(packageUser.second);
367 pw.print(": ");
368 // limit dumping to a max of 100 values
369 final int lastIdx = Math.max(0, timestamps.size() - 100);
370 for (int j = timestamps.size() - 1; j >= lastIdx; j--) {
371 TimeUtils.formatDuration(timestamps.get(j), nowElapsed, pw);
372 pw.print(", ");
373 }
374 pw.println();
375 }
376 pw.decreaseIndent();
377 }
378 }
Makoto Onuki2206af32017-11-21 16:25:35 -0800379
Dianne Hackborna750a632015-06-16 17:18:23 -0700380 /**
381 * All times are in milliseconds. These constants are kept synchronized with the system
382 * global Settings. Any access to this class or its fields should be done while
383 * holding the AlarmManagerService.mLock lock.
384 */
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700385 @VisibleForTesting
386 final class Constants extends ContentObserver {
Dianne Hackborna750a632015-06-16 17:18:23 -0700387 // Key names stored in the settings value.
Suprabh Shuklaadfa6e82018-10-19 17:32:08 -0700388 @VisibleForTesting
389 static final String KEY_MIN_FUTURITY = "min_futurity";
390 @VisibleForTesting
391 static final String KEY_MIN_INTERVAL = "min_interval";
392 @VisibleForTesting
393 static final String KEY_MAX_INTERVAL = "max_interval";
394 @VisibleForTesting
395 static final String KEY_ALLOW_WHILE_IDLE_SHORT_TIME = "allow_while_idle_short_time";
396 @VisibleForTesting
397 static final String KEY_ALLOW_WHILE_IDLE_LONG_TIME = "allow_while_idle_long_time";
398 @VisibleForTesting
399 static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
Dianne Hackborna750a632015-06-16 17:18:23 -0700400 = "allow_while_idle_whitelist_duration";
Suprabh Shuklaadfa6e82018-10-19 17:32:08 -0700401 @VisibleForTesting
402 static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800403 @VisibleForTesting
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800404 static final String KEY_MAX_ALARMS_PER_UID = "max_alarms_per_uid";
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800405 private static final String KEY_APP_STANDBY_WINDOW = "app_standby_window";
406 @VisibleForTesting
407 final String[] KEYS_APP_STANDBY_QUOTAS = {
408 "standby_active_quota",
409 "standby_working_quota",
410 "standby_frequent_quota",
411 "standby_rare_quota",
412 "standby_never_quota",
413 };
Kweku Adams610aee72020-01-15 16:43:27 -0800414 // Not putting this in the KEYS_APP_STANDBY_QUOTAS array because this uses a different
415 // window size.
416 private static final String KEY_APP_STANDBY_RESTRICTED_QUOTA = "standby_restricted_quota";
417 private static final String KEY_APP_STANDBY_RESTRICTED_WINDOW =
418 "app_standby_restricted_window";
Dianne Hackborna750a632015-06-16 17:18:23 -0700419
420 private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
421 private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
Christopher Tate22e919d2018-02-16 16:16:50 -0800422 private static final long DEFAULT_MAX_INTERVAL = 365 * DateUtils.DAY_IN_MILLIS;
Christopher Tateaa244da2015-08-27 15:57:57 -0700423 private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
Dianne Hackborn7682b262015-10-26 17:51:57 -0700424 private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000;
Dianne Hackborna750a632015-06-16 17:18:23 -0700425 private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700426 private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800427 private static final int DEFAULT_MAX_ALARMS_PER_UID = 500;
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800428 private static final long DEFAULT_APP_STANDBY_WINDOW = 60 * 60 * 1000; // 1 hr
429 /**
430 * Max number of times an app can receive alarms in {@link #APP_STANDBY_WINDOW}
431 */
432 private final int[] DEFAULT_APP_STANDBY_QUOTAS = {
433 720, // Active
434 10, // Working
435 2, // Frequent
436 1, // Rare
437 0 // Never
438 };
Kweku Adams610aee72020-01-15 16:43:27 -0800439 private static final int DEFAULT_APP_STANDBY_RESTRICTED_QUOTA = 1;
440 private static final long DEFAULT_APP_STANDBY_RESTRICTED_WINDOW = MILLIS_IN_DAY;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700441
Dianne Hackborna750a632015-06-16 17:18:23 -0700442 // Minimum futurity of a new alarm
443 public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
444
445 // Minimum alarm recurrence interval
446 public long MIN_INTERVAL = DEFAULT_MIN_INTERVAL;
447
Christopher Tate22e919d2018-02-16 16:16:50 -0800448 // Maximum alarm recurrence interval
449 public long MAX_INTERVAL = DEFAULT_MAX_INTERVAL;
450
Dianne Hackborna750a632015-06-16 17:18:23 -0700451 // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
452 public long ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME;
453
454 // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
455 public long ALLOW_WHILE_IDLE_LONG_TIME = DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME;
456
457 // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
458 public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
459 = DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
460
Christopher Tate14a7bb02015-10-01 10:24:31 -0700461 // Direct alarm listener callback timeout
462 public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800463 public int MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID;
464
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800465 public long APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW;
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800466 public int[] APP_STANDBY_QUOTAS = new int[DEFAULT_APP_STANDBY_QUOTAS.length];
Kweku Adams610aee72020-01-15 16:43:27 -0800467 public int APP_STANDBY_RESTRICTED_QUOTA = DEFAULT_APP_STANDBY_RESTRICTED_QUOTA;
468 public long APP_STANDBY_RESTRICTED_WINDOW = DEFAULT_APP_STANDBY_RESTRICTED_WINDOW;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800469
Dianne Hackborna750a632015-06-16 17:18:23 -0700470 private ContentResolver mResolver;
471 private final KeyValueListParser mParser = new KeyValueListParser(',');
472 private long mLastAllowWhileIdleWhitelistDuration = -1;
473
474 public Constants(Handler handler) {
475 super(handler);
Dianne Hackborna750a632015-06-16 17:18:23 -0700476 updateAllowWhileIdleWhitelistDurationLocked();
477 }
478
479 public void start(ContentResolver resolver) {
480 mResolver = resolver;
481 mResolver.registerContentObserver(Settings.Global.getUriFor(
482 Settings.Global.ALARM_MANAGER_CONSTANTS), false, this);
483 updateConstants();
484 }
485
Dianne Hackborna750a632015-06-16 17:18:23 -0700486 public void updateAllowWhileIdleWhitelistDurationLocked() {
487 if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
488 mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
489 BroadcastOptions opts = BroadcastOptions.makeBasic();
490 opts.setTemporaryAppWhitelistDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION);
491 mIdleOptions = opts.toBundle();
492 }
493 }
494
495 @Override
496 public void onChange(boolean selfChange, Uri uri) {
497 updateConstants();
498 }
499
500 private void updateConstants() {
501 synchronized (mLock) {
502 try {
503 mParser.setString(Settings.Global.getString(mResolver,
504 Settings.Global.ALARM_MANAGER_CONSTANTS));
505 } catch (IllegalArgumentException e) {
506 // Failed to parse the settings string, log this and move on
507 // with defaults.
Dianne Hackborn0ef403e2017-01-24 18:22:15 -0800508 Slog.e(TAG, "Bad alarm manager settings", e);
Dianne Hackborna750a632015-06-16 17:18:23 -0700509 }
510
511 MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
512 MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
Christopher Tate22e919d2018-02-16 16:16:50 -0800513 MAX_INTERVAL = mParser.getLong(KEY_MAX_INTERVAL, DEFAULT_MAX_INTERVAL);
Dianne Hackborna750a632015-06-16 17:18:23 -0700514 ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
515 DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
516 ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME,
517 DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
518 ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong(
519 KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
520 DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700521 LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
522 DEFAULT_LISTENER_TIMEOUT);
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800523
524 APP_STANDBY_WINDOW = mParser.getLong(KEY_APP_STANDBY_WINDOW,
525 DEFAULT_APP_STANDBY_WINDOW);
526 if (APP_STANDBY_WINDOW > DEFAULT_APP_STANDBY_WINDOW) {
527 Slog.w(TAG, "Cannot exceed the app_standby_window size of "
528 + DEFAULT_APP_STANDBY_WINDOW);
529 APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW;
530 } else if (APP_STANDBY_WINDOW < DEFAULT_APP_STANDBY_WINDOW) {
531 // Not recommended outside of testing.
532 Slog.w(TAG, "Using a non-default app_standby_window of " + APP_STANDBY_WINDOW);
533 }
534
535 APP_STANDBY_QUOTAS[ACTIVE_INDEX] = mParser.getInt(
536 KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX],
537 DEFAULT_APP_STANDBY_QUOTAS[ACTIVE_INDEX]);
538 for (int i = WORKING_INDEX; i < KEYS_APP_STANDBY_QUOTAS.length; i++) {
539 APP_STANDBY_QUOTAS[i] = mParser.getInt(KEYS_APP_STANDBY_QUOTAS[i],
540 Math.min(APP_STANDBY_QUOTAS[i - 1], DEFAULT_APP_STANDBY_QUOTAS[i]));
Suprabh Shukla75edab12018-01-29 14:09:06 -0800541 }
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800542
Kweku Adams610aee72020-01-15 16:43:27 -0800543 APP_STANDBY_RESTRICTED_QUOTA = Math.max(1,
544 mParser.getInt(KEY_APP_STANDBY_RESTRICTED_QUOTA,
545 DEFAULT_APP_STANDBY_RESTRICTED_QUOTA));
546
547 APP_STANDBY_RESTRICTED_WINDOW = Math.max(APP_STANDBY_WINDOW,
548 mParser.getLong(KEY_APP_STANDBY_RESTRICTED_WINDOW,
549 DEFAULT_APP_STANDBY_RESTRICTED_WINDOW));
550
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800551 MAX_ALARMS_PER_UID = mParser.getInt(KEY_MAX_ALARMS_PER_UID,
552 DEFAULT_MAX_ALARMS_PER_UID);
553 if (MAX_ALARMS_PER_UID < DEFAULT_MAX_ALARMS_PER_UID) {
554 Slog.w(TAG, "Cannot set " + KEY_MAX_ALARMS_PER_UID + " lower than "
555 + DEFAULT_MAX_ALARMS_PER_UID);
556 MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID;
557 }
558
Dianne Hackborna750a632015-06-16 17:18:23 -0700559 updateAllowWhileIdleWhitelistDurationLocked();
560 }
561 }
562
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800563 void dump(PrintWriter pw, String prefix) {
564 dump(new IndentingPrintWriter(pw, " ").setIndent(prefix));
565 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700566
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800567 void dump(IndentingPrintWriter pw) {
568 pw.println("Settings:");
569
570 pw.increaseIndent();
571
572 pw.print(KEY_MIN_FUTURITY); pw.print("=");
Dianne Hackborna750a632015-06-16 17:18:23 -0700573 TimeUtils.formatDuration(MIN_FUTURITY, pw);
574 pw.println();
575
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800576 pw.print(KEY_MIN_INTERVAL); pw.print("=");
Dianne Hackborna750a632015-06-16 17:18:23 -0700577 TimeUtils.formatDuration(MIN_INTERVAL, pw);
578 pw.println();
579
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800580 pw.print(KEY_MAX_INTERVAL); pw.print("=");
Christopher Tate22e919d2018-02-16 16:16:50 -0800581 TimeUtils.formatDuration(MAX_INTERVAL, pw);
582 pw.println();
583
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800584 pw.print(KEY_LISTENER_TIMEOUT); pw.print("=");
Christopher Tate14a7bb02015-10-01 10:24:31 -0700585 TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
586 pw.println();
587
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800588 pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME); pw.print("=");
Dianne Hackborna750a632015-06-16 17:18:23 -0700589 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw);
590 pw.println();
591
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800592 pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME); pw.print("=");
Dianne Hackborna750a632015-06-16 17:18:23 -0700593 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw);
594 pw.println();
595
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800596 pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION); pw.print("=");
Dianne Hackborna750a632015-06-16 17:18:23 -0700597 TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
598 pw.println();
Suprabh Shukla75edab12018-01-29 14:09:06 -0800599
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800600 pw.print(KEY_MAX_ALARMS_PER_UID); pw.print("=");
601 pw.println(MAX_ALARMS_PER_UID);
602
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800603 pw.print(KEY_APP_STANDBY_WINDOW); pw.print("=");
604 TimeUtils.formatDuration(APP_STANDBY_WINDOW, pw);
605 pw.println();
606
607 for (int i = 0; i < KEYS_APP_STANDBY_QUOTAS.length; i++) {
608 pw.print(KEYS_APP_STANDBY_QUOTAS[i]); pw.print("=");
609 pw.println(APP_STANDBY_QUOTAS[i]);
610 }
611
Kweku Adams610aee72020-01-15 16:43:27 -0800612 pw.print(KEY_APP_STANDBY_RESTRICTED_QUOTA); pw.print("=");
Kweku Adams5fabc292020-04-21 11:58:18 -0400613 pw.println(APP_STANDBY_RESTRICTED_QUOTA);
Kweku Adams610aee72020-01-15 16:43:27 -0800614
615 pw.print(KEY_APP_STANDBY_RESTRICTED_WINDOW); pw.print("=");
616 TimeUtils.formatDuration(APP_STANDBY_RESTRICTED_WINDOW, pw);
617 pw.println();
618
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -0800619 pw.decreaseIndent();
Dianne Hackborna750a632015-06-16 17:18:23 -0700620 }
Kweku Adams61e03292017-10-19 14:27:12 -0700621
622 void dumpProto(ProtoOutputStream proto, long fieldId) {
623 final long token = proto.start(fieldId);
624
625 proto.write(ConstantsProto.MIN_FUTURITY_DURATION_MS, MIN_FUTURITY);
626 proto.write(ConstantsProto.MIN_INTERVAL_DURATION_MS, MIN_INTERVAL);
Christopher Tate22e919d2018-02-16 16:16:50 -0800627 proto.write(ConstantsProto.MAX_INTERVAL_DURATION_MS, MAX_INTERVAL);
Kweku Adams61e03292017-10-19 14:27:12 -0700628 proto.write(ConstantsProto.LISTENER_TIMEOUT_DURATION_MS, LISTENER_TIMEOUT);
629 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_SHORT_DURATION_MS,
630 ALLOW_WHILE_IDLE_SHORT_TIME);
631 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_LONG_DURATION_MS,
632 ALLOW_WHILE_IDLE_LONG_TIME);
633 proto.write(ConstantsProto.ALLOW_WHILE_IDLE_WHITELIST_DURATION_MS,
634 ALLOW_WHILE_IDLE_WHITELIST_DURATION);
635
636 proto.end(token);
637 }
Dianne Hackborna750a632015-06-16 17:18:23 -0700638 }
639
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700640 Constants mConstants;
Dianne Hackborna750a632015-06-16 17:18:23 -0700641
Christopher Tate1590f1e2014-10-02 17:27:57 -0700642 // Alarm delivery ordering bookkeeping
643 static final int PRIO_TICK = 0;
644 static final int PRIO_WAKEUP = 1;
645 static final int PRIO_NORMAL = 2;
646
Dianne Hackborna750a632015-06-16 17:18:23 -0700647 final class PriorityClass {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700648 int seq;
649 int priority;
650
651 PriorityClass() {
652 seq = mCurrentSeq - 1;
653 priority = PRIO_NORMAL;
654 }
655 }
656
Dianne Hackborna750a632015-06-16 17:18:23 -0700657 final HashMap<String, PriorityClass> mPriorities = new HashMap<>();
Christopher Tate1590f1e2014-10-02 17:27:57 -0700658 int mCurrentSeq = 0;
659
Dianne Hackborna750a632015-06-16 17:18:23 -0700660 static final class WakeupEvent {
Christopher Tate18a75f12013-07-01 18:18:59 -0700661 public long when;
662 public int uid;
663 public String action;
664
665 public WakeupEvent(long theTime, int theUid, String theAction) {
666 when = theTime;
667 uid = theUid;
668 action = theAction;
669 }
670 }
671
Adam Lesinski182f73f2013-12-05 16:48:06 -0800672 final LinkedList<WakeupEvent> mRecentWakeups = new LinkedList<WakeupEvent>();
673 final long RECENT_WAKEUP_PERIOD = 1000L * 60 * 60 * 24; // one day
Christopher Tate18a75f12013-07-01 18:18:59 -0700674
Adrian Roosc42a1e12014-07-07 23:35:53 +0200675 final class Batch {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700676 long start; // These endpoints are always in ELAPSED
677 long end;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700678 int flags; // Flags for alarms, such as FLAG_STANDALONE.
Christopher Tatee0a22b32013-07-11 14:43:13 -0700679
680 final ArrayList<Alarm> alarms = new ArrayList<Alarm>();
681
Christopher Tatee0a22b32013-07-11 14:43:13 -0700682 Batch(Alarm seed) {
683 start = seed.whenElapsed;
Christopher Tate22e919d2018-02-16 16:16:50 -0800684 end = clampPositive(seed.maxWhenElapsed);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700685 flags = seed.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700686 alarms.add(seed);
Christopher Tatec8b7f432018-09-28 16:23:10 -0700687 if (seed.listener == mTimeTickTrigger) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700688 mLastTickAdded = mInjector.getCurrentTimeMillis();
Makoto Onuki5d93b832018-01-10 16:12:39 -0800689 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700690 }
691
692 int size() {
693 return alarms.size();
694 }
695
696 Alarm get(int index) {
697 return alarms.get(index);
698 }
699
700 boolean canHold(long whenElapsed, long maxWhen) {
701 return (end >= whenElapsed) && (start <= maxWhen);
702 }
703
704 boolean add(Alarm alarm) {
705 boolean newStart = false;
706 // narrows the batch if necessary; presumes that canHold(alarm) is true
707 int index = Collections.binarySearch(alarms, alarm, sIncreasingTimeOrder);
708 if (index < 0) {
709 index = 0 - index - 1;
710 }
711 alarms.add(index, alarm);
Christopher Tatec8b7f432018-09-28 16:23:10 -0700712 if (alarm.listener == mTimeTickTrigger) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700713 mLastTickAdded = mInjector.getCurrentTimeMillis();
Makoto Onuki5d93b832018-01-10 16:12:39 -0800714 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700715 if (DEBUG_BATCH) {
716 Slog.v(TAG, "Adding " + alarm + " to " + this);
717 }
718 if (alarm.whenElapsed > start) {
719 start = alarm.whenElapsed;
720 newStart = true;
721 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700722 if (alarm.maxWhenElapsed < end) {
723 end = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700724 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700725 flags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700726
727 if (DEBUG_BATCH) {
728 Slog.v(TAG, " => now " + this);
729 }
730 return newStart;
731 }
732
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800733 /**
734 * Remove an alarm from this batch.
735 * <p> <b> Should be used only while re-ordering the alarm within the service </b> as it
736 * does not update {@link #mAlarmsPerUid}
737 */
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800738 boolean remove(Alarm alarm) {
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800739 return remove(a -> (a == alarm), true);
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800740 }
741
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800742 boolean remove(Predicate<Alarm> predicate, boolean reOrdering) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700743 boolean didRemove = false;
744 long newStart = 0; // recalculate endpoints as we go
745 long newEnd = Long.MAX_VALUE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700746 int newFlags = 0;
Christopher Tateae269d52013-09-26 13:11:55 -0700747 for (int i = 0; i < alarms.size(); ) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700748 Alarm alarm = alarms.get(i);
Christopher Tate1d99c392017-12-07 16:54:04 -0800749 if (predicate.test(alarm)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700750 alarms.remove(i);
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800751 if (!reOrdering) {
Suprabh Shukla5afe2f312019-04-12 17:19:30 -0700752 decrementAlarmCount(alarm.uid, 1);
Suprabh Shukla0e49b642019-03-04 14:14:32 -0800753 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700754 didRemove = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +0200755 if (alarm.alarmClock != null) {
756 mNextAlarmClockMayChange = true;
757 }
Christopher Tatec8b7f432018-09-28 16:23:10 -0700758 if (alarm.listener == mTimeTickTrigger) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700759 mLastTickRemoved = mInjector.getCurrentTimeMillis();
Makoto Onuki5d93b832018-01-10 16:12:39 -0800760 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700761 } else {
762 if (alarm.whenElapsed > newStart) {
763 newStart = alarm.whenElapsed;
764 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700765 if (alarm.maxWhenElapsed < newEnd) {
766 newEnd = alarm.maxWhenElapsed;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700767 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700768 newFlags |= alarm.flags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700769 i++;
770 }
771 }
772 if (didRemove) {
773 // commit the new batch bounds
774 start = newStart;
775 end = newEnd;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700776 flags = newFlags;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700777 }
778 return didRemove;
779 }
780
Christopher Tatee0a22b32013-07-11 14:43:13 -0700781 boolean hasPackage(final String packageName) {
782 final int N = alarms.size();
783 for (int i = 0; i < N; i++) {
784 Alarm a = alarms.get(i);
Christopher Tate14a7bb02015-10-01 10:24:31 -0700785 if (a.matches(packageName)) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700786 return true;
787 }
788 }
789 return false;
790 }
791
792 boolean hasWakeups() {
793 final int N = alarms.size();
794 for (int i = 0; i < N; i++) {
795 Alarm a = alarms.get(i);
796 // non-wakeup alarms are types 1 and 3, i.e. have the low bit set
797 if ((a.type & TYPE_NONWAKEUP_MASK) == 0) {
798 return true;
799 }
800 }
801 return false;
802 }
803
804 @Override
805 public String toString() {
806 StringBuilder b = new StringBuilder(40);
807 b.append("Batch{"); b.append(Integer.toHexString(this.hashCode()));
808 b.append(" num="); b.append(size());
809 b.append(" start="); b.append(start);
810 b.append(" end="); b.append(end);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700811 if (flags != 0) {
812 b.append(" flgs=0x");
813 b.append(Integer.toHexString(flags));
Christopher Tatee0a22b32013-07-11 14:43:13 -0700814 }
815 b.append('}');
816 return b.toString();
817 }
Kweku Adams61e03292017-10-19 14:27:12 -0700818
Jeffrey Huangcb782852019-12-05 11:28:11 -0800819 public void dumpDebug(ProtoOutputStream proto, long fieldId, long nowElapsed,
Kweku Adams61e03292017-10-19 14:27:12 -0700820 long nowRTC) {
821 final long token = proto.start(fieldId);
822
823 proto.write(BatchProto.START_REALTIME, start);
824 proto.write(BatchProto.END_REALTIME, end);
825 proto.write(BatchProto.FLAGS, flags);
826 for (Alarm a : alarms) {
Jeffrey Huangcb782852019-12-05 11:28:11 -0800827 a.dumpDebug(proto, BatchProto.ALARMS, nowElapsed, nowRTC);
Kweku Adams61e03292017-10-19 14:27:12 -0700828 }
829
830 proto.end(token);
831 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700832 }
833
834 static class BatchTimeOrder implements Comparator<Batch> {
835 public int compare(Batch b1, Batch b2) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -0800836 long when1 = b1.start;
837 long when2 = b2.start;
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800838 if (when1 > when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700839 return 1;
840 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +0800841 if (when1 < when2) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700842 return -1;
843 }
844 return 0;
845 }
846 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800847
848 final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
849 @Override
850 public int compare(Alarm lhs, Alarm rhs) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700851 // priority class trumps everything. TICK < WAKEUP < NORMAL
852 if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
853 return -1;
854 } else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
855 return 1;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800856 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700857
858 // within each class, sort by nominal delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800859 if (lhs.whenElapsed < rhs.whenElapsed) {
860 return -1;
861 } else if (lhs.whenElapsed > rhs.whenElapsed) {
862 return 1;
863 }
Christopher Tate1590f1e2014-10-02 17:27:57 -0700864
865 // same priority class + same target delivery time
Dianne Hackborn3d658bf2014-02-05 13:38:56 -0800866 return 0;
867 }
868 };
869
Christopher Tate1590f1e2014-10-02 17:27:57 -0700870 void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
871 final int N = alarms.size();
872 for (int i = 0; i < N; i++) {
873 Alarm a = alarms.get(i);
874
875 final int alarmPrio;
Christopher Tatec8b7f432018-09-28 16:23:10 -0700876 if (a.listener == mTimeTickTrigger) {
Christopher Tate1590f1e2014-10-02 17:27:57 -0700877 alarmPrio = PRIO_TICK;
878 } else if (a.wakeup) {
879 alarmPrio = PRIO_WAKEUP;
880 } else {
881 alarmPrio = PRIO_NORMAL;
882 }
883
884 PriorityClass packagePrio = a.priorityClass;
Suprabh Shukla75edab12018-01-29 14:09:06 -0800885 String alarmPackage = a.sourcePackage;
Christopher Tate14a7bb02015-10-01 10:24:31 -0700886 if (packagePrio == null) packagePrio = mPriorities.get(alarmPackage);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700887 if (packagePrio == null) {
888 packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
Christopher Tate14a7bb02015-10-01 10:24:31 -0700889 mPriorities.put(alarmPackage, packagePrio);
Christopher Tate1590f1e2014-10-02 17:27:57 -0700890 }
891 a.priorityClass = packagePrio;
892
893 if (packagePrio.seq != mCurrentSeq) {
894 // first alarm we've seen in the current delivery generation from this package
895 packagePrio.priority = alarmPrio;
896 packagePrio.seq = mCurrentSeq;
897 } else {
898 // Multiple alarms from this package being delivered in this generation;
899 // bump the package's delivery class if it's warranted.
900 // TICK < WAKEUP < NORMAL
901 if (alarmPrio < packagePrio.priority) {
902 packagePrio.priority = alarmPrio;
903 }
904 }
905 }
906 }
907
Christopher Tatee0a22b32013-07-11 14:43:13 -0700908 // minimum recurrence period or alarm futurity for us to be able to fuzz it
Adam Lesinski182f73f2013-12-05 16:48:06 -0800909 static final long MIN_FUZZABLE_INTERVAL = 10000;
910 static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700911 final ArrayList<Batch> mAlarmBatches = new ArrayList<>();
912
Suprabh Shukladb6bf662017-08-30 15:41:53 -0700913 // 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 -0700914 // to run during this time are placed in mPendingWhileIdleAlarms
915 Alarm mPendingIdleUntil = null;
Dianne Hackbornf70faed2015-04-21 14:11:38 -0700916 Alarm mNextWakeFromIdle = null;
Dianne Hackborn0b4daca2015-04-27 09:47:32 -0700917 ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>();
Christopher Tatee0a22b32013-07-11 14:43:13 -0700918
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700919 @VisibleForTesting
920 AlarmManagerService(Context context, Injector injector) {
Jeff Brownb880d882014-02-10 19:47:07 -0800921 super(context);
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700922 mInjector = injector;
Jeff Brownb880d882014-02-10 19:47:07 -0800923 }
924
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700925 AlarmManagerService(Context context) {
926 this(context, new Injector(context));
927 }
928
929 private long convertToElapsed(long when, int type) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700930 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
931 if (isRtc) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -0700932 when -= mInjector.getCurrentTimeMillis() - mInjector.getElapsedRealtime();
Christopher Tatee0a22b32013-07-11 14:43:13 -0700933 }
934 return when;
935 }
936
937 // Apply a heuristic to { recurrence interval, futurity of the trigger time } to
938 // calculate the end of our nominal delivery window for the alarm.
939 static long maxTriggerTime(long now, long triggerAtTime, long interval) {
940 // Current heuristic: batchable window is 75% of either the recurrence interval
941 // [for a periodic alarm] or of the time from now to the desired delivery time,
942 // with a minimum delay/interval of 10 seconds, under which we will simply not
943 // defer the alarm.
944 long futurity = (interval == 0)
945 ? (triggerAtTime - now)
946 : interval;
Christopher Tate57ceaaa2013-07-19 16:30:43 -0700947 if (futurity < MIN_FUZZABLE_INTERVAL) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700948 futurity = 0;
949 }
Christopher Tate22e919d2018-02-16 16:16:50 -0800950 return clampPositive(triggerAtTime + (long)(.75 * futurity));
Christopher Tatee0a22b32013-07-11 14:43:13 -0700951 }
952
953 // returns true if the batch was added at the head
954 static boolean addBatchLocked(ArrayList<Batch> list, Batch newBatch) {
955 int index = Collections.binarySearch(list, newBatch, sBatchOrder);
956 if (index < 0) {
957 index = 0 - index - 1;
958 }
959 list.add(index, newBatch);
960 return (index == 0);
961 }
962
Suprabh Shukla92994ab2018-01-31 17:39:30 -0800963 private void insertAndBatchAlarmLocked(Alarm alarm) {
964 final int whichBatch = ((alarm.flags & AlarmManager.FLAG_STANDALONE) != 0) ? -1
965 : attemptCoalesceLocked(alarm.whenElapsed, alarm.maxWhenElapsed);
966
967 if (whichBatch < 0) {
968 addBatchLocked(mAlarmBatches, new Batch(alarm));
969 } else {
970 final Batch batch = mAlarmBatches.get(whichBatch);
971 if (batch.add(alarm)) {
972 // The start time of this batch advanced, so batch ordering may
973 // have just been broken. Move it to where it now belongs.
974 mAlarmBatches.remove(whichBatch);
975 addBatchLocked(mAlarmBatches, batch);
976 }
977 }
978 }
979
Christopher Tate385e4982013-07-23 18:22:29 -0700980 // Return the index of the matching batch, or -1 if none found.
981 int attemptCoalesceLocked(long whenElapsed, long maxWhen) {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700982 final int N = mAlarmBatches.size();
983 for (int i = 0; i < N; i++) {
984 Batch b = mAlarmBatches.get(i);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -0700985 if ((b.flags&AlarmManager.FLAG_STANDALONE) == 0 && b.canHold(whenElapsed, maxWhen)) {
Christopher Tate385e4982013-07-23 18:22:29 -0700986 return i;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700987 }
988 }
Christopher Tate385e4982013-07-23 18:22:29 -0700989 return -1;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700990 }
Makoto Onuki5d93b832018-01-10 16:12:39 -0800991 /** @return total count of the alarms in a set of alarm batches. */
992 static int getAlarmCount(ArrayList<Batch> batches) {
993 int ret = 0;
994
995 final int size = batches.size();
996 for (int i = 0; i < size; i++) {
997 ret += batches.get(i).size();
998 }
999 return ret;
1000 }
1001
1002 boolean haveAlarmsTimeTickAlarm(ArrayList<Alarm> alarms) {
1003 if (alarms.size() == 0) {
1004 return false;
1005 }
1006 final int batchSize = alarms.size();
1007 for (int j = 0; j < batchSize; j++) {
Christopher Tatec8b7f432018-09-28 16:23:10 -07001008 if (alarms.get(j).listener == mTimeTickTrigger) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08001009 return true;
1010 }
1011 }
1012 return false;
1013 }
1014
1015 boolean haveBatchesTimeTickAlarm(ArrayList<Batch> batches) {
1016 final int numBatches = batches.size();
1017 for (int i = 0; i < numBatches; i++) {
1018 if (haveAlarmsTimeTickAlarm(batches.get(i).alarms)) {
1019 return true;
1020 }
1021 }
1022 return false;
1023 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001024
1025 // The RTC clock has moved arbitrarily, so we need to recalculate all the batching
1026 void rebatchAllAlarms() {
Christopher Tatee0a22b32013-07-11 14:43:13 -07001027 synchronized (mLock) {
Christopher Tate4cb338d2013-07-26 13:11:31 -07001028 rebatchAllAlarmsLocked(true);
1029 }
1030 }
1031
1032 void rebatchAllAlarmsLocked(boolean doValidate) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001033 final long start = mStatLogger.getTime();
Makoto Onuki5d93b832018-01-10 16:12:39 -08001034 final int oldCount =
1035 getAlarmCount(mAlarmBatches) + ArrayUtils.size(mPendingWhileIdleAlarms);
1036 final boolean oldHasTick = haveBatchesTimeTickAlarm(mAlarmBatches)
1037 || haveAlarmsTimeTickAlarm(mPendingWhileIdleAlarms);
1038
Christopher Tate4cb338d2013-07-26 13:11:31 -07001039 ArrayList<Batch> oldSet = (ArrayList<Batch>) mAlarmBatches.clone();
1040 mAlarmBatches.clear();
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001041 Alarm oldPendingIdleUntil = mPendingIdleUntil;
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001042 final long nowElapsed = mInjector.getElapsedRealtime();
Christopher Tate4cb338d2013-07-26 13:11:31 -07001043 final int oldBatches = oldSet.size();
1044 for (int batchNum = 0; batchNum < oldBatches; batchNum++) {
1045 Batch batch = oldSet.get(batchNum);
1046 final int N = batch.size();
1047 for (int i = 0; i < N; i++) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001048 reAddAlarmLocked(batch.get(i), nowElapsed, doValidate);
Christopher Tatee0a22b32013-07-11 14:43:13 -07001049 }
1050 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001051 if (oldPendingIdleUntil != null && oldPendingIdleUntil != mPendingIdleUntil) {
1052 Slog.wtf(TAG, "Rebatching: idle until changed from " + oldPendingIdleUntil
1053 + " to " + mPendingIdleUntil);
1054 if (mPendingIdleUntil == null) {
1055 // Somehow we lost this... we need to restore all of the pending alarms.
1056 restorePendingWhileIdleAlarmsLocked();
1057 }
1058 }
Makoto Onuki5d93b832018-01-10 16:12:39 -08001059 final int newCount =
1060 getAlarmCount(mAlarmBatches) + ArrayUtils.size(mPendingWhileIdleAlarms);
1061 final boolean newHasTick = haveBatchesTimeTickAlarm(mAlarmBatches)
1062 || haveAlarmsTimeTickAlarm(mPendingWhileIdleAlarms);
1063
1064 if (oldCount != newCount) {
1065 Slog.wtf(TAG, "Rebatching: total count changed from " + oldCount + " to " + newCount);
1066 }
1067 if (oldHasTick != newHasTick) {
1068 Slog.wtf(TAG, "Rebatching: hasTick changed from " + oldHasTick + " to " + newHasTick);
1069 }
1070
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001071 rescheduleKernelAlarmsLocked();
1072 updateNextAlarmClockLocked();
Suprabh Shukla75edab12018-01-29 14:09:06 -08001073 mStatLogger.logDurationStat(Stats.REBATCH_ALL_ALARMS, start);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001074 }
1075
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001076 /**
1077 * Re-orders the alarm batches based on newly evaluated send times based on the current
1078 * app-standby buckets
1079 * @param targetPackages [Package, User] pairs for which alarms need to be re-evaluated,
1080 * null indicates all
1081 * @return True if there was any reordering done to the current list.
1082 */
1083 boolean reorderAlarmsBasedOnStandbyBuckets(ArraySet<Pair<String, Integer>> targetPackages) {
1084 final long start = mStatLogger.getTime();
1085 final ArrayList<Alarm> rescheduledAlarms = new ArrayList<>();
1086
1087 for (int batchIndex = mAlarmBatches.size() - 1; batchIndex >= 0; batchIndex--) {
1088 final Batch batch = mAlarmBatches.get(batchIndex);
1089 for (int alarmIndex = batch.size() - 1; alarmIndex >= 0; alarmIndex--) {
1090 final Alarm alarm = batch.get(alarmIndex);
1091 final Pair<String, Integer> packageUser =
1092 Pair.create(alarm.sourcePackage, UserHandle.getUserId(alarm.creatorUid));
1093 if (targetPackages != null && !targetPackages.contains(packageUser)) {
1094 continue;
1095 }
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08001096 if (adjustDeliveryTimeBasedOnBucketLocked(alarm)) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001097 batch.remove(alarm);
1098 rescheduledAlarms.add(alarm);
1099 }
1100 }
1101 if (batch.size() == 0) {
1102 mAlarmBatches.remove(batchIndex);
1103 }
1104 }
1105 for (int i = 0; i < rescheduledAlarms.size(); i++) {
1106 final Alarm a = rescheduledAlarms.get(i);
1107 insertAndBatchAlarmLocked(a);
1108 }
1109
1110 mStatLogger.logDurationStat(Stats.REORDER_ALARMS_FOR_STANDBY, start);
1111 return rescheduledAlarms.size() > 0;
1112 }
1113
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001114 void reAddAlarmLocked(Alarm a, long nowElapsed, boolean doValidate) {
1115 a.when = a.origWhen;
1116 long whenElapsed = convertToElapsed(a.when, a.type);
1117 final long maxElapsed;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001118 if (a.windowLength == AlarmManager.WINDOW_EXACT) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001119 // Exact
1120 maxElapsed = whenElapsed;
1121 } else {
1122 // Not exact. Preserve any explicit window, otherwise recalculate
1123 // the window based on the alarm's new futurity. Note that this
1124 // reflects a policy of preferring timely to deferred delivery.
1125 maxElapsed = (a.windowLength > 0)
Christopher Tate22e919d2018-02-16 16:16:50 -08001126 ? clampPositive(whenElapsed + a.windowLength)
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001127 : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
1128 }
Suprabh Shuklaabdd7362019-05-13 13:31:56 -07001129 a.expectedWhenElapsed = a.whenElapsed = whenElapsed;
1130 a.expectedMaxWhenElapsed = a.maxWhenElapsed = maxElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001131 setImplLocked(a, true, doValidate);
1132 }
1133
Christopher Tate22e919d2018-02-16 16:16:50 -08001134 static long clampPositive(long val) {
1135 return (val >= 0) ? val : Long.MAX_VALUE;
1136 }
1137
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001138 /**
1139 * Sends alarms that were blocked due to user applied background restrictions - either because
1140 * the user lifted those or the uid came to foreground.
1141 *
1142 * @param uid uid to filter on
1143 * @param packageName package to filter on, or null for all packages in uid
1144 */
1145 void sendPendingBackgroundAlarmsLocked(int uid, String packageName) {
1146 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(uid);
1147 if (alarmsForUid == null || alarmsForUid.size() == 0) {
1148 return;
1149 }
1150 final ArrayList<Alarm> alarmsToDeliver;
1151 if (packageName != null) {
1152 if (DEBUG_BG_LIMIT) {
1153 Slog.d(TAG, "Sending blocked alarms for uid " + uid + ", package " + packageName);
1154 }
1155 alarmsToDeliver = new ArrayList<>();
1156 for (int i = alarmsForUid.size() - 1; i >= 0; i--) {
1157 final Alarm a = alarmsForUid.get(i);
1158 if (a.matches(packageName)) {
1159 alarmsToDeliver.add(alarmsForUid.remove(i));
1160 }
1161 }
1162 if (alarmsForUid.size() == 0) {
1163 mPendingBackgroundAlarms.remove(uid);
1164 }
1165 } else {
1166 if (DEBUG_BG_LIMIT) {
1167 Slog.d(TAG, "Sending blocked alarms for uid " + uid);
1168 }
1169 alarmsToDeliver = alarmsForUid;
1170 mPendingBackgroundAlarms.remove(uid);
1171 }
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001172 deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001173 }
1174
Makoto Onuki2206af32017-11-21 16:25:35 -08001175 /**
1176 * Check all alarms in {@link #mPendingBackgroundAlarms} and send the ones that are not
1177 * restricted.
1178 *
1179 * This is only called when the global "force all apps-standby" flag changes or when the
1180 * power save whitelist changes, so it's okay to be slow.
1181 */
1182 void sendAllUnrestrictedPendingBackgroundAlarmsLocked() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001183 final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
Makoto Onuki2206af32017-11-21 16:25:35 -08001184
1185 findAllUnrestrictedPendingBackgroundAlarmsLockedInner(
1186 mPendingBackgroundAlarms, alarmsToDeliver, this::isBackgroundRestricted);
1187
1188 if (alarmsToDeliver.size() > 0) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001189 deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
Makoto Onuki2206af32017-11-21 16:25:35 -08001190 }
1191 }
1192
1193 @VisibleForTesting
1194 static void findAllUnrestrictedPendingBackgroundAlarmsLockedInner(
1195 SparseArray<ArrayList<Alarm>> pendingAlarms, ArrayList<Alarm> unrestrictedAlarms,
1196 Predicate<Alarm> isBackgroundRestricted) {
1197
1198 for (int uidIndex = pendingAlarms.size() - 1; uidIndex >= 0; uidIndex--) {
1199 final int uid = pendingAlarms.keyAt(uidIndex);
1200 final ArrayList<Alarm> alarmsForUid = pendingAlarms.valueAt(uidIndex);
1201
1202 for (int alarmIndex = alarmsForUid.size() - 1; alarmIndex >= 0; alarmIndex--) {
1203 final Alarm alarm = alarmsForUid.get(alarmIndex);
1204
1205 if (isBackgroundRestricted.test(alarm)) {
1206 continue;
1207 }
1208
1209 unrestrictedAlarms.add(alarm);
1210 alarmsForUid.remove(alarmIndex);
1211 }
1212
1213 if (alarmsForUid.size() == 0) {
1214 pendingAlarms.removeAt(uidIndex);
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001215 }
1216 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001217 }
1218
1219 private void deliverPendingBackgroundAlarmsLocked(ArrayList<Alarm> alarms, long nowELAPSED) {
1220 final int N = alarms.size();
1221 boolean hasWakeup = false;
1222 for (int i = 0; i < N; i++) {
1223 final Alarm alarm = alarms.get(i);
1224 if (alarm.wakeup) {
1225 hasWakeup = true;
1226 }
1227 alarm.count = 1;
1228 // Recurring alarms may have passed several alarm intervals while the
1229 // alarm was kept pending. Send the appropriate trigger count.
1230 if (alarm.repeatInterval > 0) {
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001231 alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001232 // Also schedule its next recurrence
1233 final long delta = alarm.count * alarm.repeatInterval;
Suprabh Shuklaabdd7362019-05-13 13:31:56 -07001234 final long nextElapsed = alarm.expectedWhenElapsed + delta;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07001235 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
1236 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
1237 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
1238 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
1239 // Kernel alarms will be rescheduled as needed in setImplLocked
1240 }
1241 }
1242 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
1243 // No need to wakeup for non wakeup alarms
1244 if (mPendingNonWakeupAlarms.size() == 0) {
1245 mStartCurrentDelayTime = nowELAPSED;
1246 mNextNonWakeupDeliveryTime = nowELAPSED
1247 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
1248 }
1249 mPendingNonWakeupAlarms.addAll(alarms);
1250 mNumDelayedAlarms += alarms.size();
1251 } else {
1252 if (DEBUG_BG_LIMIT) {
1253 Slog.d(TAG, "Waking up to deliver pending blocked alarms");
1254 }
1255 // Since we are waking up, also deliver any pending non wakeup alarms we have.
1256 if (mPendingNonWakeupAlarms.size() > 0) {
1257 alarms.addAll(mPendingNonWakeupAlarms);
1258 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
1259 mTotalDelayTime += thisDelayTime;
1260 if (mMaxDelayTime < thisDelayTime) {
1261 mMaxDelayTime = thisDelayTime;
1262 }
1263 mPendingNonWakeupAlarms.clear();
1264 }
1265 calculateDeliveryPriorities(alarms);
1266 Collections.sort(alarms, mAlarmDispatchComparator);
1267 deliverAlarmsLocked(alarms, nowELAPSED);
1268 }
1269 }
1270
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001271 void restorePendingWhileIdleAlarmsLocked() {
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001272 if (RECORD_DEVICE_IDLE_ALARMS) {
1273 IdleDispatchEntry ent = new IdleDispatchEntry();
1274 ent.uid = 0;
1275 ent.pkg = "FINISH IDLE";
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001276 ent.elapsedRealtime = mInjector.getElapsedRealtime();
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001277 mAllowWhileIdleDispatches.add(ent);
1278 }
1279
Dianne Hackborn35d54032015-04-23 10:30:43 -07001280 // Bring pending alarms back into the main list.
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001281 if (mPendingWhileIdleAlarms.size() > 0) {
1282 ArrayList<Alarm> alarms = mPendingWhileIdleAlarms;
1283 mPendingWhileIdleAlarms = new ArrayList<>();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001284 final long nowElapsed = mInjector.getElapsedRealtime();
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07001285 for (int i=alarms.size() - 1; i >= 0; i--) {
1286 Alarm a = alarms.get(i);
1287 reAddAlarmLocked(a, nowElapsed, false);
1288 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001289 }
Dianne Hackborn35d54032015-04-23 10:30:43 -07001290
1291 // Reschedule everything.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001292 rescheduleKernelAlarmsLocked();
1293 updateNextAlarmClockLocked();
Dianne Hackborn35d54032015-04-23 10:30:43 -07001294
Christopher Tatee0a22b32013-07-11 14:43:13 -07001295 }
1296
Christopher Tate14a7bb02015-10-01 10:24:31 -07001297 static final class InFlight {
Dianne Hackborn81038902012-11-26 17:04:09 -08001298 final PendingIntent mPendingIntent;
Christopher Tateeabba732017-08-17 17:12:52 -07001299 final long mWhenElapsed;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001300 final IBinder mListener;
David Christieebe51fc2013-07-26 13:23:29 -07001301 final WorkSource mWorkSource;
Christopher Tate14a7bb02015-10-01 10:24:31 -07001302 final int mUid;
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00001303 final int mCreatorUid;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001304 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001305 final BroadcastStats mBroadcastStats;
1306 final FilterStats mFilterStats;
Dianne Hackborne5167ca2014-03-08 14:39:10 -08001307 final int mAlarmType;
Dianne Hackborn81038902012-11-26 17:04:09 -08001308
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00001309 InFlight(AlarmManagerService service, Alarm alarm, long nowELAPSED) {
1310 mPendingIntent = alarm.operation;
Christopher Tateeabba732017-08-17 17:12:52 -07001311 mWhenElapsed = nowELAPSED;
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00001312 mListener = alarm.listener != null ? alarm.listener.asBinder() : null;
1313 mWorkSource = alarm.workSource;
1314 mUid = alarm.uid;
1315 mCreatorUid = alarm.creatorUid;
1316 mTag = alarm.statsTag;
1317 mBroadcastStats = (alarm.operation != null)
1318 ? service.getStatsLocked(alarm.operation)
1319 : service.getStatsLocked(alarm.uid, alarm.packageName);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001320 FilterStats fs = mBroadcastStats.filterStats.get(mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08001321 if (fs == null) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001322 fs = new FilterStats(mBroadcastStats, mTag);
1323 mBroadcastStats.filterStats.put(mTag, fs);
Dianne Hackborn81038902012-11-26 17:04:09 -08001324 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001325 fs.lastTime = nowELAPSED;
Dianne Hackborn81038902012-11-26 17:04:09 -08001326 mFilterStats = fs;
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00001327 mAlarmType = alarm.type;
Dianne Hackborn81038902012-11-26 17:04:09 -08001328 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001329
Christopher Tate2f558d22019-01-17 16:58:31 -08001330 boolean isBroadcast() {
1331 return mPendingIntent != null && mPendingIntent.isBroadcast();
1332 }
1333
Makoto Onuki33955e12017-03-01 18:11:00 -08001334 @Override
1335 public String toString() {
1336 return "InFlight{"
1337 + "pendingIntent=" + mPendingIntent
Christopher Tateeabba732017-08-17 17:12:52 -07001338 + ", when=" + mWhenElapsed
Makoto Onuki33955e12017-03-01 18:11:00 -08001339 + ", workSource=" + mWorkSource
1340 + ", uid=" + mUid
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00001341 + ", creatorUid=" + mCreatorUid
Makoto Onuki33955e12017-03-01 18:11:00 -08001342 + ", tag=" + mTag
1343 + ", broadcastStats=" + mBroadcastStats
1344 + ", filterStats=" + mFilterStats
1345 + ", alarmType=" + mAlarmType
1346 + "}";
1347 }
Kweku Adams61e03292017-10-19 14:27:12 -07001348
Jeffrey Huangcb782852019-12-05 11:28:11 -08001349 public void dumpDebug(ProtoOutputStream proto, long fieldId) {
Kweku Adams61e03292017-10-19 14:27:12 -07001350 final long token = proto.start(fieldId);
1351
1352 proto.write(InFlightProto.UID, mUid);
1353 proto.write(InFlightProto.TAG, mTag);
1354 proto.write(InFlightProto.WHEN_ELAPSED_MS, mWhenElapsed);
1355 proto.write(InFlightProto.ALARM_TYPE, mAlarmType);
1356 if (mPendingIntent != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08001357 mPendingIntent.dumpDebug(proto, InFlightProto.PENDING_INTENT);
Kweku Adams61e03292017-10-19 14:27:12 -07001358 }
1359 if (mBroadcastStats != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08001360 mBroadcastStats.dumpDebug(proto, InFlightProto.BROADCAST_STATS);
Kweku Adams61e03292017-10-19 14:27:12 -07001361 }
1362 if (mFilterStats != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08001363 mFilterStats.dumpDebug(proto, InFlightProto.FILTER_STATS);
Kweku Adams61e03292017-10-19 14:27:12 -07001364 }
1365 if (mWorkSource != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08001366 mWorkSource.dumpDebug(proto, InFlightProto.WORK_SOURCE);
Kweku Adams61e03292017-10-19 14:27:12 -07001367 }
1368
1369 proto.end(token);
1370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001371 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001372
Christopher Tate2f558d22019-01-17 16:58:31 -08001373 private void notifyBroadcastAlarmPendingLocked(int uid) {
1374 final int numListeners = mInFlightListeners.size();
1375 for (int i = 0; i < numListeners; i++) {
1376 mInFlightListeners.get(i).broadcastAlarmPending(uid);
1377 }
1378 }
1379
1380 private void notifyBroadcastAlarmCompleteLocked(int uid) {
1381 final int numListeners = mInFlightListeners.size();
1382 for (int i = 0; i < numListeners; i++) {
1383 mInFlightListeners.get(i).broadcastAlarmComplete(uid);
1384 }
1385 }
1386
Adam Lesinski182f73f2013-12-05 16:48:06 -08001387 static final class FilterStats {
Dianne Hackborn81038902012-11-26 17:04:09 -08001388 final BroadcastStats mBroadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001389 final String mTag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001390
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001391 long lastTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 long aggregateTime;
Dianne Hackborn81038902012-11-26 17:04:09 -08001393 int count;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001394 int numWakeup;
1395 long startTime;
1396 int nesting;
Dianne Hackborn81038902012-11-26 17:04:09 -08001397
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001398 FilterStats(BroadcastStats broadcastStats, String tag) {
Dianne Hackborn81038902012-11-26 17:04:09 -08001399 mBroadcastStats = broadcastStats;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001400 mTag = tag;
Dianne Hackborn81038902012-11-26 17:04:09 -08001401 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001402
1403 @Override
1404 public String toString() {
1405 return "FilterStats{"
1406 + "tag=" + mTag
1407 + ", lastTime=" + lastTime
1408 + ", aggregateTime=" + aggregateTime
1409 + ", count=" + count
1410 + ", numWakeup=" + numWakeup
1411 + ", startTime=" + startTime
1412 + ", nesting=" + nesting
1413 + "}";
1414 }
Kweku Adams61e03292017-10-19 14:27:12 -07001415
Jeffrey Huangcb782852019-12-05 11:28:11 -08001416 public void dumpDebug(ProtoOutputStream proto, long fieldId) {
Kweku Adams61e03292017-10-19 14:27:12 -07001417 final long token = proto.start(fieldId);
1418
1419 proto.write(FilterStatsProto.TAG, mTag);
1420 proto.write(FilterStatsProto.LAST_FLIGHT_TIME_REALTIME, lastTime);
1421 proto.write(FilterStatsProto.TOTAL_FLIGHT_DURATION_MS, aggregateTime);
1422 proto.write(FilterStatsProto.COUNT, count);
1423 proto.write(FilterStatsProto.WAKEUP_COUNT, numWakeup);
1424 proto.write(FilterStatsProto.START_TIME_REALTIME, startTime);
1425 proto.write(FilterStatsProto.NESTING, nesting);
1426
1427 proto.end(token);
1428 }
Dianne Hackborn81038902012-11-26 17:04:09 -08001429 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001430
Adam Lesinski182f73f2013-12-05 16:48:06 -08001431 static final class BroadcastStats {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001432 final int mUid;
Dianne Hackborn81038902012-11-26 17:04:09 -08001433 final String mPackageName;
1434
1435 long aggregateTime;
1436 int count;
1437 int numWakeup;
1438 long startTime;
1439 int nesting;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001440 final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
Dianne Hackborn81038902012-11-26 17:04:09 -08001441
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001442 BroadcastStats(int uid, String packageName) {
1443 mUid = uid;
Dianne Hackborn81038902012-11-26 17:04:09 -08001444 mPackageName = packageName;
1445 }
Makoto Onuki33955e12017-03-01 18:11:00 -08001446
1447 @Override
1448 public String toString() {
1449 return "BroadcastStats{"
1450 + "uid=" + mUid
1451 + ", packageName=" + mPackageName
1452 + ", aggregateTime=" + aggregateTime
1453 + ", count=" + count
1454 + ", numWakeup=" + numWakeup
1455 + ", startTime=" + startTime
1456 + ", nesting=" + nesting
1457 + "}";
1458 }
Kweku Adams61e03292017-10-19 14:27:12 -07001459
Jeffrey Huangcb782852019-12-05 11:28:11 -08001460 public void dumpDebug(ProtoOutputStream proto, long fieldId) {
Kweku Adams61e03292017-10-19 14:27:12 -07001461 final long token = proto.start(fieldId);
1462
1463 proto.write(BroadcastStatsProto.UID, mUid);
1464 proto.write(BroadcastStatsProto.PACKAGE_NAME, mPackageName);
1465 proto.write(BroadcastStatsProto.TOTAL_FLIGHT_DURATION_MS, aggregateTime);
1466 proto.write(BroadcastStatsProto.COUNT, count);
1467 proto.write(BroadcastStatsProto.WAKEUP_COUNT, numWakeup);
1468 proto.write(BroadcastStatsProto.START_TIME_REALTIME, startTime);
1469 proto.write(BroadcastStatsProto.NESTING, nesting);
1470
1471 proto.end(token);
1472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001474
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08001475 final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
1476 = new SparseArray<ArrayMap<String, BroadcastStats>>();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07001477
1478 int mNumDelayedAlarms = 0;
1479 long mTotalDelayTime = 0;
1480 long mMaxDelayTime = 0;
1481
Adam Lesinski182f73f2013-12-05 16:48:06 -08001482 @Override
1483 public void onStart() {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001484 mInjector.init();
Robert CH Chou64ba8e42009-11-04 21:38:49 +08001485
Suprabh Shukla5bfaaa62019-12-23 17:32:30 -08001486 mListenerDeathRecipient = new IBinder.DeathRecipient() {
1487 @Override
1488 public void binderDied() {
1489 }
1490
1491 @Override
1492 public void binderDied(IBinder who) {
1493 final IAlarmListener listener = IAlarmListener.Stub.asInterface(who);
1494 removeImpl(null, listener);
1495 }
1496 };
1497
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001498 synchronized (mLock) {
Suprabh Shukla12bd0162018-11-12 18:00:18 -08001499 mHandler = new AlarmHandler();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001500 mConstants = new Constants(mHandler);
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08001501 mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW);
Robert CH Chou64ba8e42009-11-04 21:38:49 +08001502
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001503 mNextWakeup = mNextNonWakeup = 0;
1504
1505 // We have to set current TimeZone info to kernel
1506 // because kernel doesn't keep this after reboot
1507 setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
1508
Christopher Tate3d65d4d2018-12-11 14:55:19 -08001509 // Ensure that we're booting with a halfway sensible current time. Use the
1510 // most recent of Build.TIME, the root file system's timestamp, and the
1511 // value of the ro.build.date.utc system property (which is in seconds).
1512 final long systemBuildTime = Long.max(
1513 1000L * SystemProperties.getLong("ro.build.date.utc", -1L),
1514 Long.max(Environment.getRootDirectory().lastModified(), Build.TIME));
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001515 if (mInjector.getCurrentTimeMillis() < systemBuildTime) {
1516 Slog.i(TAG, "Current time only " + mInjector.getCurrentTimeMillis()
Christopher Tate247571462017-04-10 11:45:05 -07001517 + ", advancing to build time " + systemBuildTime);
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001518 mInjector.setKernelTime(systemBuildTime);
Christopher Tate247571462017-04-10 11:45:05 -07001519 }
Christopher Tate247571462017-04-10 11:45:05 -07001520
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001521 // Determine SysUI's uid
1522 mSystemUiUid = mInjector.getSystemUiUid();
1523 if (mSystemUiUid <= 0) {
1524 Slog.wtf(TAG, "SysUI package not found!");
1525 }
1526 mWakeLock = mInjector.getAlarmWakeLock();
1527
Christopher Tatec8b7f432018-09-28 16:23:10 -07001528 mTimeTickIntent = new Intent(Intent.ACTION_TIME_TICK).addFlags(
1529 Intent.FLAG_RECEIVER_REGISTERED_ONLY
1530 | Intent.FLAG_RECEIVER_FOREGROUND
1531 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
1532
1533 mTimeTickTrigger = new IAlarmListener.Stub() {
1534 @Override
1535 public void doAlarm(final IAlarmCompleteListener callback) throws RemoteException {
1536 if (DEBUG_BATCH) {
1537 Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
1538 }
1539
1540 // Via handler because dispatch invokes this within its lock. OnAlarmListener
1541 // takes care of this automatically, but we're using the direct internal
1542 // interface here rather than that client-side wrapper infrastructure.
1543 mHandler.post(() -> {
1544 getContext().sendBroadcastAsUser(mTimeTickIntent, UserHandle.ALL);
1545
1546 try {
1547 callback.alarmComplete(this);
1548 } catch (RemoteException e) { /* local method call */ }
1549 });
1550
1551 synchronized (mLock) {
1552 mLastTickReceived = mInjector.getCurrentTimeMillis();
1553 }
1554 mClockReceiver.scheduleTimeTickEvent();
1555 }
1556 };
1557
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001558 Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
1559 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
1560 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
1561 mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
1562 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
1563
1564 mClockReceiver = mInjector.getClockReceiver(this);
Kweku Adamsdf33ae12019-10-08 11:51:41 -07001565 new ChargingReceiver();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001566 new InteractiveStateReceiver();
1567 new UninstallReceiver();
1568
1569 if (mInjector.isAlarmDriverPresent()) {
1570 AlarmThread waitThread = new AlarmThread();
1571 waitThread.start();
Christopher Tatebb9cce52017-04-18 14:19:43 -07001572 } else {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001573 Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
Christopher Tatebb9cce52017-04-18 14:19:43 -07001574 }
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001575
1576 try {
1577 ActivityManager.getService().registerUidObserver(new UidObserver(),
1578 ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
1579 | ActivityManager.UID_OBSERVER_ACTIVE,
1580 ActivityManager.PROCESS_STATE_UNKNOWN, null);
1581 } catch (RemoteException e) {
1582 // ignored; both services live in system_server
1583 }
Christopher Tatebb9cce52017-04-18 14:19:43 -07001584 }
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001585 publishLocalService(AlarmManagerInternal.class, new LocalService());
Adam Lesinski182f73f2013-12-05 16:48:06 -08001586 publishBinderService(Context.ALARM_SERVICE, mService);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08001588
1589 @Override
Dianne Hackborna750a632015-06-16 17:18:23 -07001590 public void onBootPhase(int phase) {
1591 if (phase == PHASE_SYSTEM_SERVICES_READY) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001592 synchronized (mLock) {
1593 mConstants.start(getContext().getContentResolver());
1594 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
1595 mLocalDeviceIdleController =
Makoto Onukieaf7eed2019-08-12 15:27:15 -07001596 LocalServices.getService(DeviceIdleInternal.class);
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001597 mUsageStatsManagerInternal =
1598 LocalServices.getService(UsageStatsManagerInternal.class);
Christopher Tateb909c4d52019-10-21 12:50:37 -07001599 AppStandbyInternal appStandbyInternal =
1600 LocalServices.getService(AppStandbyInternal.class);
1601 appStandbyInternal.addListener(new AppStandbyTracker());
Makoto Onukie4918212018-02-06 11:30:15 -08001602
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001603 mAppStateTracker = LocalServices.getService(AppStateTracker.class);
1604 mAppStateTracker.addListener(mForceAppStandbyListener);
1605
1606 mClockReceiver.scheduleTimeTickEvent();
1607 mClockReceiver.scheduleDateChangedEvent();
1608 }
Dianne Hackborna750a632015-06-16 17:18:23 -07001609 }
1610 }
1611
1612 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 protected void finalize() throws Throwable {
1614 try {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001615 mInjector.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001616 } finally {
1617 super.finalize();
1618 }
1619 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001620
mswest463f4c99d2018-02-01 10:13:10 -08001621 boolean setTimeImpl(long millis) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001622 if (!mInjector.isAlarmDriverPresent()) {
mswest463f4c99d2018-02-01 10:13:10 -08001623 Slog.w(TAG, "Not setting time since no alarm driver is available.");
1624 return false;
1625 }
1626
1627 synchronized (mLock) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001628 final long currentTimeMillis = mInjector.getCurrentTimeMillis();
1629 mInjector.setKernelTime(millis);
Christine Hallstromf5d585a2018-05-21 14:27:23 -07001630 final TimeZone timeZone = TimeZone.getDefault();
1631 final int currentTzOffset = timeZone.getOffset(currentTimeMillis);
1632 final int newTzOffset = timeZone.getOffset(millis);
1633 if (currentTzOffset != newTzOffset) {
1634 Slog.i(TAG, "Timezone offset has changed, updating kernel timezone");
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001635 mInjector.setKernelTimezone(-(newTzOffset / 60000));
Christine Hallstromf5d585a2018-05-21 14:27:23 -07001636 }
1637 // The native implementation of setKernelTime can return -1 even when the kernel
1638 // time was set correctly, so assume setting kernel time was successful and always
1639 // return true.
1640 return true;
mswest463f4c99d2018-02-01 10:13:10 -08001641 }
1642 }
1643
Adam Lesinski182f73f2013-12-05 16:48:06 -08001644 void setTimeZoneImpl(String tz) {
1645 if (TextUtils.isEmpty(tz)) {
1646 return;
David Christieebe51fc2013-07-26 13:23:29 -07001647 }
1648
Adam Lesinski182f73f2013-12-05 16:48:06 -08001649 TimeZone zone = TimeZone.getTimeZone(tz);
1650 // Prevent reentrant calls from stepping on each other when writing
1651 // the time zone property
1652 boolean timeZoneWasChanged = false;
1653 synchronized (this) {
1654 String current = SystemProperties.get(TIMEZONE_PROPERTY);
1655 if (current == null || !current.equals(zone.getID())) {
1656 if (localLOGV) {
1657 Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
1658 }
1659 timeZoneWasChanged = true;
1660 SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
1661 }
1662
1663 // Update the kernel timezone information
1664 // Kernel tracks time offsets as 'minutes west of GMT'
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001665 int gmtOffset = zone.getOffset(mInjector.getCurrentTimeMillis());
1666 mInjector.setKernelTimezone(-(gmtOffset / 60000));
Adam Lesinski182f73f2013-12-05 16:48:06 -08001667 }
1668
1669 TimeZone.setDefault(null);
1670
1671 if (timeZoneWasChanged) {
Christopher Tatea4618b02018-10-11 16:22:55 -07001672 // Don't wait for broadcasts to update our midnight alarm
1673 mClockReceiver.scheduleDateChangedEvent();
1674
1675 // And now let everyone else know
Adam Lesinski182f73f2013-12-05 16:48:06 -08001676 Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
Chad Brubaker291df4f2017-03-14 10:23:02 -07001677 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
Christopher Tate5cdf9f82017-05-03 18:10:39 -07001678 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
jianzhouacce5e42018-05-11 14:47:12 +08001679 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
Chad Brubaker291df4f2017-03-14 10:23:02 -07001680 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Suprabh Shukla2e7408e2020-03-10 17:09:25 -07001681 intent.putExtra(Intent.EXTRA_TIMEZONE, zone.getID());
Adam Lesinski182f73f2013-12-05 16:48:06 -08001682 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
1683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001685
Christopher Tatec8b7f432018-09-28 16:23:10 -07001686 void removeImpl(PendingIntent operation, IAlarmListener listener) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08001687 synchronized (mLock) {
Christopher Tatec8b7f432018-09-28 16:23:10 -07001688 removeLocked(operation, listener);
Adam Lesinski182f73f2013-12-05 16:48:06 -08001689 }
1690 }
1691
1692 void setImpl(int type, long triggerAtTime, long windowLength, long interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001693 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1694 int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
1695 int callingUid, String callingPackage) {
1696 // must be *either* PendingIntent or AlarmReceiver, but not both
1697 if ((operation == null && directReceiver == null)
1698 || (operation != null && directReceiver != null)) {
1699 Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver");
1700 // NB: previous releases failed silently here, so we are continuing to do the same
1701 // rather than throw an IllegalArgumentException.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 return;
1703 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07001704
Suprabh Shukla5bfaaa62019-12-23 17:32:30 -08001705 if (directReceiver != null) {
1706 try {
1707 directReceiver.asBinder().linkToDeath(mListenerDeathRecipient, 0);
1708 } catch (RemoteException e) {
1709 Slog.w(TAG, "Dropping unreachable alarm listener " + listenerTag);
1710 return;
1711 }
1712 }
1713
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001714 // Sanity check the window length. This will catch people mistakenly
1715 // trying to pass an end-of-window timestamp rather than a duration.
1716 if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
1717 Slog.w(TAG, "Window length " + windowLength
1718 + "ms suspiciously long; limiting to 1 hour");
1719 windowLength = AlarmManager.INTERVAL_HOUR;
1720 }
1721
Christopher Tate498c6cb2014-11-17 16:09:27 -08001722 // Sanity check the recurrence interval. This will catch people who supply
Christopher Tate22e919d2018-02-16 16:16:50 -08001723 // seconds when the API expects milliseconds, or apps trying shenanigans
1724 // around intentional period overflow, etc.
Dianne Hackborna750a632015-06-16 17:18:23 -07001725 final long minInterval = mConstants.MIN_INTERVAL;
1726 if (interval > 0 && interval < minInterval) {
Christopher Tate498c6cb2014-11-17 16:09:27 -08001727 Slog.w(TAG, "Suspiciously short interval " + interval
Dianne Hackborna750a632015-06-16 17:18:23 -07001728 + " millis; expanding to " + (minInterval/1000)
Christopher Tate498c6cb2014-11-17 16:09:27 -08001729 + " seconds");
Dianne Hackborna750a632015-06-16 17:18:23 -07001730 interval = minInterval;
Christopher Tate22e919d2018-02-16 16:16:50 -08001731 } else if (interval > mConstants.MAX_INTERVAL) {
1732 Slog.w(TAG, "Suspiciously long interval " + interval
1733 + " millis; clamping");
1734 interval = mConstants.MAX_INTERVAL;
Christopher Tate498c6cb2014-11-17 16:09:27 -08001735 }
1736
Christopher Tatee0a22b32013-07-11 14:43:13 -07001737 if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
1738 throw new IllegalArgumentException("Invalid alarm type " + type);
1739 }
1740
Christopher Tate5f221e82013-07-30 17:13:15 -07001741 if (triggerAtTime < 0) {
Christopher Tate5f221e82013-07-30 17:13:15 -07001742 final long what = Binder.getCallingPid();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001743 Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
Christopher Tate5f221e82013-07-30 17:13:15 -07001744 + " pid=" + what);
1745 triggerAtTime = 0;
1746 }
1747
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001748 final long nowElapsed = mInjector.getElapsedRealtime();
Christopher Tate498c6cb2014-11-17 16:09:27 -08001749 final long nominalTrigger = convertToElapsed(triggerAtTime, type);
Christopher Tate7f8041f2020-04-01 10:09:07 -07001750 // Try to prevent spamming by making sure apps aren't firing alarms in the immediate future
1751 final long minTrigger = nowElapsed
1752 + (UserHandle.isCore(callingUid) ? 0L : mConstants.MIN_FUTURITY);
Christopher Tate498c6cb2014-11-17 16:09:27 -08001753 final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
1754
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001755 final long maxElapsed;
1756 if (windowLength == AlarmManager.WINDOW_EXACT) {
1757 maxElapsed = triggerElapsed;
1758 } else if (windowLength < 0) {
1759 maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001760 // Fix this window in place, so that as time approaches we don't collapse it.
1761 windowLength = maxElapsed - triggerElapsed;
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001762 } else {
1763 maxElapsed = triggerElapsed + windowLength;
1764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 synchronized (mLock) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07001766 if (DEBUG_BATCH) {
1767 Slog.v(TAG, "set(" + operation + ") : type=" + type
Christopher Tate57ceaaa2013-07-19 16:30:43 -07001768 + " triggerAtTime=" + triggerAtTime + " win=" + windowLength
Christopher Tatee0a22b32013-07-11 14:43:13 -07001769 + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001770 + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 }
Suprabh Shukla0e49b642019-03-04 14:14:32 -08001772 if (mAlarmsPerUid.get(callingUid, 0) >= mConstants.MAX_ALARMS_PER_UID) {
1773 final String errorMsg =
1774 "Maximum limit of concurrent alarms " + mConstants.MAX_ALARMS_PER_UID
1775 + " reached for uid: " + UserHandle.formatUid(callingUid)
1776 + ", callingPackage: " + callingPackage;
Suprabh Shukla8ec95612020-06-17 19:56:30 -07001777
1778 if (WARN_SYSTEM_ON_ALARM_LIMIT && UserHandle.isCore(callingUid)) {
1779 final StringWriter logWriter = new StringWriter();
1780 final PrintWriter pw = new PrintWriter(logWriter);
1781 pw.println(errorMsg);
1782 pw.println("Next 20 alarms for " + callingUid + ":");
1783 dumpUpcomingNAlarmsForUid(pw, callingUid, 20);
1784 pw.flush();
1785 Slog.wtf(TAG, logWriter.toString());
1786 } else {
1787 Slog.w(TAG, errorMsg);
1788 }
1789 if (DEBUG_PER_UID_LIMIT) {
1790 logAllAlarmsForUidLocked(callingUid);
1791 }
Suprabh Shukla7e3f7832019-05-28 14:48:44 -07001792 throw new IllegalStateException(errorMsg);
Suprabh Shukla0e49b642019-03-04 14:14:32 -08001793 }
Christopher Tate3e04b472013-10-21 17:51:31 -07001794 setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001795 interval, operation, directReceiver, listenerTag, flags, true, workSource,
1796 alarmClock, callingUid, callingPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 }
1798 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799
Suprabh Shukla8ec95612020-06-17 19:56:30 -07001800 private void logAllAlarmsForUidLocked(int uid) {
1801 final StringWriter logWriter = new StringWriter();
1802 final PrintWriter pw = new PrintWriter(logWriter);
1803
1804 pw.println("List of all pending alarms for " + UserHandle.formatUid(uid) + ":");
1805 dumpUpcomingNAlarmsForUid(pw, uid, mConstants.MAX_ALARMS_PER_UID);
1806 pw.flush();
1807 Slog.d(TAG, logWriter.toString());
1808 }
1809
1810 private void dumpUpcomingNAlarmsForUid(PrintWriter pw, int uid, int n) {
1811 final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1812 final long nowElapsed = mInjector.getElapsedRealtime();
1813 final long nowRtc = mInjector.getCurrentTimeMillis();
1814
1815 int count = 0;
1816 for (int i = 0; i < mAlarmBatches.size() && count < n; i++) {
1817 final Batch b = mAlarmBatches.get(i);
1818 for (int j = 0; j < b.size() && count < n; j++) {
1819 final Alarm a = b.get(j);
1820 if (a.uid == uid) {
1821 final String label = labelForType(a.type);
1822 pw.print(label + " #" + (++count) + ": ");
1823 pw.println(a);
1824 a.dump(pw, " ", nowElapsed, nowRtc, sdf);
1825 }
1826 }
1827 }
1828 }
1829
Christopher Tate3e04b472013-10-21 17:51:31 -07001830 private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001831 long maxWhen, long interval, PendingIntent operation, IAlarmListener directReceiver,
1832 String listenerTag, int flags, boolean doValidate, WorkSource workSource,
1833 AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) {
Christopher Tate3e04b472013-10-21 17:51:31 -07001834 Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
Christopher Tate14a7bb02015-10-01 10:24:31 -07001835 operation, directReceiver, listenerTag, workSource, flags, alarmClock,
1836 callingUid, callingPackage);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001837 try {
Dianne Hackbornc3af19a2017-01-20 17:00:44 -08001838 if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07001839 Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
1840 + " -- package not allowed to start");
1841 return;
1842 }
1843 } catch (RemoteException e) {
1844 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07001845 removeLocked(operation, directReceiver);
Suprabh Shukla0e49b642019-03-04 14:14:32 -08001846 incrementAlarmCount(a.uid);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001847 setImplLocked(a, false, doValidate);
1848 }
Christopher Tateb8849c12011-02-08 13:39:01 -08001849
Christopher Tatef2159712018-03-27 16:04:14 -07001850 /**
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08001851 * Returns the maximum alarms that an app in the specified bucket can receive in a rolling time
1852 * window given by {@link Constants#APP_STANDBY_WINDOW}
1853 */
1854 @VisibleForTesting
1855 int getQuotaForBucketLocked(int bucket) {
1856 final int index;
1857 if (bucket <= UsageStatsManager.STANDBY_BUCKET_ACTIVE) {
1858 index = ACTIVE_INDEX;
1859 } else if (bucket <= UsageStatsManager.STANDBY_BUCKET_WORKING_SET) {
1860 index = WORKING_INDEX;
1861 } else if (bucket <= UsageStatsManager.STANDBY_BUCKET_FREQUENT) {
1862 index = FREQUENT_INDEX;
1863 } else if (bucket < UsageStatsManager.STANDBY_BUCKET_NEVER) {
1864 index = RARE_INDEX;
1865 } else {
1866 index = NEVER_INDEX;
1867 }
1868 return mConstants.APP_STANDBY_QUOTAS[index];
1869 }
1870
1871 /**
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001872 * Adjusts the alarm delivery time based on the current app standby bucket.
1873 * @param alarm The alarm to adjust
1874 * @return true if the alarm delivery time was updated.
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001875 */
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08001876 private boolean adjustDeliveryTimeBasedOnBucketLocked(Alarm alarm) {
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001877 if (isExemptFromAppStandby(alarm)) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001878 return false;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001879 }
1880 if (mAppStandbyParole) {
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001881 if (alarm.whenElapsed > alarm.expectedWhenElapsed) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001882 // We did defer this alarm earlier, restore original requirements
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001883 alarm.whenElapsed = alarm.expectedWhenElapsed;
1884 alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
1885 return true;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001886 }
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08001887 return false;
Suprabh Shukla75edab12018-01-29 14:09:06 -08001888 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001889 final long oldWhenElapsed = alarm.whenElapsed;
1890 final long oldMaxWhenElapsed = alarm.maxWhenElapsed;
1891
Suprabh Shukla75edab12018-01-29 14:09:06 -08001892 final String sourcePackage = alarm.sourcePackage;
1893 final int sourceUserId = UserHandle.getUserId(alarm.creatorUid);
1894 final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket(
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001895 sourcePackage, sourceUserId, mInjector.getElapsedRealtime());
Suprabh Shukla75edab12018-01-29 14:09:06 -08001896
Kweku Adams9e5ef1d2019-10-15 15:41:28 -07001897 // Quota deferring implementation:
Kweku Adams610aee72020-01-15 16:43:27 -08001898 boolean deferred = false;
Kweku Adams9e5ef1d2019-10-15 15:41:28 -07001899 final int wakeupsInWindow = mAppWakeupHistory.getTotalWakeupsInWindow(sourcePackage,
1900 sourceUserId);
Kweku Adams610aee72020-01-15 16:43:27 -08001901 if (standbyBucket == UsageStatsManager.STANDBY_BUCKET_RESTRICTED) {
1902 // Special case because it's 1/day instead of 1/hour.
1903 // AppWakeupHistory doesn't delete old wakeup times until a new one is logged, so we
1904 // should always have the last wakeup available.
1905 if (wakeupsInWindow > 0) {
1906 final long lastWakeupTime = mAppWakeupHistory.getNthLastWakeupForPackage(
1907 sourcePackage, sourceUserId, mConstants.APP_STANDBY_RESTRICTED_QUOTA);
1908 if (mInjector.getElapsedRealtime() - lastWakeupTime
1909 < mConstants.APP_STANDBY_RESTRICTED_WINDOW) {
1910 final long minElapsed =
1911 lastWakeupTime + mConstants.APP_STANDBY_RESTRICTED_WINDOW;
1912 if (alarm.expectedWhenElapsed < minElapsed) {
1913 alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
1914 deferred = true;
1915 }
1916 }
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08001917 }
Kweku Adams610aee72020-01-15 16:43:27 -08001918 } else {
1919 final int quotaForBucket = getQuotaForBucketLocked(standbyBucket);
1920 if (wakeupsInWindow >= quotaForBucket) {
1921 final long minElapsed;
1922 if (quotaForBucket <= 0) {
1923 // Just keep deferring for a day till the quota changes
1924 minElapsed = mInjector.getElapsedRealtime() + MILLIS_IN_DAY;
1925 } else {
1926 // Suppose the quota for window was q, and the qth last delivery time for this
1927 // package was t(q) then the next delivery must be after t(q) + <window_size>
1928 final long t = mAppWakeupHistory.getNthLastWakeupForPackage(
1929 sourcePackage, sourceUserId, quotaForBucket);
Kweku Adamscaafee42020-03-23 12:18:24 -07001930 minElapsed = t + mConstants.APP_STANDBY_WINDOW;
Kweku Adams610aee72020-01-15 16:43:27 -08001931 }
1932 if (alarm.expectedWhenElapsed < minElapsed) {
1933 alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
1934 deferred = true;
1935 }
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08001936 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08001937 }
Kweku Adams9e5ef1d2019-10-15 15:41:28 -07001938 if (!deferred) {
1939 // Restore original requirements in case they were changed earlier.
1940 alarm.whenElapsed = alarm.expectedWhenElapsed;
1941 alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
1942 }
1943
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001944 return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed);
Suprabh Shukla75edab12018-01-29 14:09:06 -08001945 }
1946
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001947 private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
1948 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001949 // This is a special alarm that will put the system into idle until it goes off.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001950 // The caller has given the time they want this to happen at, however we need
1951 // to pull that earlier if there are existing alarms that have requested to
Dianne Hackbornf3831292015-10-15 14:51:06 -07001952 // bring us out of idle at an earlier time.
1953 if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001954 a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001955 }
1956 // Add fuzz to make the alarm go off some time before the actual desired time.
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001957 final long nowElapsed = mInjector.getElapsedRealtime();
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001958 final int fuzz = fuzzForDuration(a.whenElapsed-nowElapsed);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001959 if (fuzz > 0) {
1960 if (mRandom == null) {
1961 mRandom = new Random();
1962 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07001963 final int delta = mRandom.nextInt(fuzz);
1964 a.whenElapsed -= delta;
1965 if (false) {
1966 Slog.d(TAG, "Alarm when: " + a.whenElapsed);
1967 Slog.d(TAG, "Delta until alarm: " + (a.whenElapsed-nowElapsed));
1968 Slog.d(TAG, "Applied fuzz: " + fuzz);
1969 Slog.d(TAG, "Final delta: " + delta);
1970 Slog.d(TAG, "Final when: " + a.whenElapsed);
1971 }
1972 a.when = a.maxWhenElapsed = a.whenElapsed;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001973 }
1974
1975 } else if (mPendingIdleUntil != null) {
1976 // We currently have an idle until alarm scheduled; if the new alarm has
1977 // not explicitly stated it wants to run while idle, then put it on hold.
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07001978 if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
1979 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
1980 | AlarmManager.FLAG_WAKE_FROM_IDLE))
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07001981 == 0) {
1982 mPendingWhileIdleAlarms.add(a);
1983 return;
1984 }
1985 }
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001986 if (RECORD_DEVICE_IDLE_ALARMS) {
1987 if ((a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
1988 IdleDispatchEntry ent = new IdleDispatchEntry();
1989 ent.uid = a.uid;
1990 ent.pkg = a.operation.getCreatorPackage();
1991 ent.tag = a.operation.getTag("");
1992 ent.op = "SET";
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07001993 ent.elapsedRealtime = mInjector.getElapsedRealtime();
Dianne Hackbornae78bf82015-10-26 13:33:20 -07001994 ent.argRealtime = a.whenElapsed;
1995 mAllowWhileIdleDispatches.add(ent);
1996 }
1997 }
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08001998 adjustDeliveryTimeBasedOnBucketLocked(a);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08001999 insertAndBatchAlarmLocked(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002001 if (a.alarmClock != null) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02002002 mNextAlarmClockMayChange = true;
Adrian Roosc42a1e12014-07-07 23:35:53 +02002003 }
2004
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002005 boolean needRebatch = false;
2006
2007 if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
Dianne Hackbornae78bf82015-10-26 13:33:20 -07002008 if (RECORD_DEVICE_IDLE_ALARMS) {
2009 if (mPendingIdleUntil == null) {
2010 IdleDispatchEntry ent = new IdleDispatchEntry();
2011 ent.uid = 0;
2012 ent.pkg = "START IDLE";
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002013 ent.elapsedRealtime = mInjector.getElapsedRealtime();
Dianne Hackbornae78bf82015-10-26 13:33:20 -07002014 mAllowWhileIdleDispatches.add(ent);
2015 }
2016 }
Makoto Onuki4274a6d2017-04-21 12:21:25 -07002017 if ((mPendingIdleUntil != a) && (mPendingIdleUntil != null)) {
2018 Slog.wtfStack(TAG, "setImplLocked: idle until changed from " + mPendingIdleUntil
2019 + " to " + a);
2020 }
2021
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002022 mPendingIdleUntil = a;
2023 needRebatch = true;
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002024 } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
2025 if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
2026 mNextWakeFromIdle = a;
2027 // If this wake from idle is earlier than whatever was previously scheduled,
2028 // and we are currently idling, then we need to rebatch alarms in case the idle
2029 // until time needs to be updated.
2030 if (mPendingIdleUntil != null) {
2031 needRebatch = true;
2032 }
2033 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002034 }
2035
2036 if (!rebatching) {
2037 if (DEBUG_VALIDATE) {
2038 if (doValidate && !validateConsistencyLocked()) {
2039 Slog.v(TAG, "Tipping-point operation: type=" + a.type + " when=" + a.when
2040 + " when(hex)=" + Long.toHexString(a.when)
2041 + " whenElapsed=" + a.whenElapsed
2042 + " maxWhenElapsed=" + a.maxWhenElapsed
2043 + " interval=" + a.repeatInterval + " op=" + a.operation
2044 + " flags=0x" + Integer.toHexString(a.flags));
2045 rebatchAllAlarmsLocked(false);
2046 needRebatch = false;
2047 }
2048 }
2049
2050 if (needRebatch) {
Christopher Tate4cb338d2013-07-26 13:11:31 -07002051 rebatchAllAlarmsLocked(false);
Christopher Tate4cb338d2013-07-26 13:11:31 -07002052 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07002053
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002054 rescheduleKernelAlarmsLocked();
2055 updateNextAlarmClockLocked();
2056 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002057 }
2058
Christopher Tate1d99c392017-12-07 16:54:04 -08002059 /**
2060 * System-process internal API
2061 */
2062 private final class LocalService implements AlarmManagerInternal {
2063 @Override
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002064 public boolean isIdling() {
2065 return isIdlingImpl();
2066 }
2067
2068 @Override
Christopher Tate1d99c392017-12-07 16:54:04 -08002069 public void removeAlarmsForUid(int uid) {
2070 synchronized (mLock) {
2071 removeLocked(uid);
2072 }
2073 }
Christopher Tate2f558d22019-01-17 16:58:31 -08002074
2075 @Override
Suprabh Shukla0d51a8b2019-10-30 18:56:44 -07002076 public void remove(PendingIntent pi) {
2077 mHandler.obtainMessage(AlarmHandler.REMOVE_FOR_CANCELED, pi).sendToTarget();
2078 }
2079
2080 @Override
Christopher Tate2f558d22019-01-17 16:58:31 -08002081 public void registerInFlightListener(InFlightListener callback) {
2082 synchronized (mLock) {
2083 mInFlightListeners.add(callback);
2084 }
2085 }
Christopher Tate1d99c392017-12-07 16:54:04 -08002086 }
2087
2088 /**
2089 * Public-facing binder interface
2090 */
Adam Lesinski182f73f2013-12-05 16:48:06 -08002091 private final IBinder mService = new IAlarmManager.Stub() {
2092 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07002093 public void set(String callingPackage,
2094 int type, long triggerAtTime, long windowLength, long interval, int flags,
2095 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
2096 WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002097 final int callingUid = Binder.getCallingUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07002098
2099 // make sure the caller is not lying about which package should be blamed for
2100 // wakelock time spent in alarm delivery
2101 mAppOps.checkPackage(callingUid, callingPackage);
2102
2103 // Repeating alarms must use PendingIntent, not direct listener
2104 if (interval != 0) {
2105 if (directReceiver != null) {
2106 throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers");
2107 }
2108 }
2109
Adam Lesinski182f73f2013-12-05 16:48:06 -08002110 if (workSource != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002111 getContext().enforcePermission(
Adam Lesinski182f73f2013-12-05 16:48:06 -08002112 android.Manifest.permission.UPDATE_DEVICE_STATS,
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002113 Binder.getCallingPid(), callingUid, "AlarmManager.set");
Christopher Tate89779822012-08-31 14:40:03 -07002114 }
2115
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002116 // No incoming callers can request either WAKE_FROM_IDLE or
2117 // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
2118 flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
2119 | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
2120
2121 // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
2122 // manager when to come out of idle mode, which is only for DeviceIdleController.
2123 if (callingUid != Process.SYSTEM_UID) {
2124 flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
2125 }
2126
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002127 // If this is an exact time alarm, then it can't be batched with other alarms.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002128 if (windowLength == AlarmManager.WINDOW_EXACT) {
2129 flags |= AlarmManager.FLAG_STANDALONE;
2130 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002131
2132 // If this alarm is for an alarm clock, then it must be standalone and we will
2133 // use it to wake early from idle if needed.
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002134 if (alarmClock != null) {
2135 flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08002136
2137 // If the caller is a core system component or on the user's whitelist, and not calling
2138 // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
2139 // This means we will allow these alarms to go off as normal even while idle, with no
2140 // timing restrictions.
2141 } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08002142 || UserHandle.isSameApp(callingUid, mSystemUiUid)
Makoto Onukie4918212018-02-06 11:30:15 -08002143 || ((mAppStateTracker != null)
Suprabh Shukla5bf49812018-05-24 18:38:50 -07002144 && mAppStateTracker.isUidPowerSaveUserWhitelisted(callingUid)))) {
Dianne Hackborn262ae5c2016-02-10 16:28:29 -08002145 flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
2146 flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002147 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002148
Christopher Tate14a7bb02015-10-01 10:24:31 -07002149 setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
2150 listenerTag, flags, workSource, alarmClock, callingUid, callingPackage);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002151 }
Christopher Tate89779822012-08-31 14:40:03 -07002152
Adam Lesinski182f73f2013-12-05 16:48:06 -08002153 @Override
Greg Hackmann0cab8962014-02-21 16:35:52 -08002154 public boolean setTime(long millis) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08002155 getContext().enforceCallingOrSelfPermission(
2156 "android.permission.SET_TIME",
2157 "setTime");
2158
mswest463f4c99d2018-02-01 10:13:10 -08002159 return setTimeImpl(millis);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002160 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002161
2162 @Override
2163 public void setTimeZone(String tz) {
2164 getContext().enforceCallingOrSelfPermission(
2165 "android.permission.SET_TIME_ZONE",
2166 "setTimeZone");
2167
2168 final long oldId = Binder.clearCallingIdentity();
2169 try {
2170 setTimeZoneImpl(tz);
2171 } finally {
2172 Binder.restoreCallingIdentity(oldId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173 }
2174 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07002175
Adam Lesinski182f73f2013-12-05 16:48:06 -08002176 @Override
Christopher Tate14a7bb02015-10-01 10:24:31 -07002177 public void remove(PendingIntent operation, IAlarmListener listener) {
2178 if (operation == null && listener == null) {
2179 Slog.w(TAG, "remove() with no intent or listener");
2180 return;
2181 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07002182 synchronized (mLock) {
2183 removeLocked(operation, listener);
2184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185 }
Christopher Tate4cb338d2013-07-26 13:11:31 -07002186
Adam Lesinski182f73f2013-12-05 16:48:06 -08002187 @Override
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002188 public long getNextWakeFromIdleTime() {
2189 return getNextWakeFromIdleTimeImpl();
2190 }
2191
2192 @Override
Jose Lima235510e2014-08-13 12:50:01 -07002193 public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02002194 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2195 Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */,
2196 "getNextAlarmClock", null);
2197
2198 return getNextAlarmClockImpl(userId);
2199 }
2200
2201 @Override
Jeff Sharkey9911a282018-02-14 22:29:11 -07002202 public long currentNetworkTimeMillis() {
2203 final NtpTrustedTime time = NtpTrustedTime.getInstance(getContext());
Neil Fuller65f0f312019-12-20 15:59:38 +00002204 NtpTrustedTime.TimeResult ntpResult = time.getCachedTimeResult();
2205 if (ntpResult != null) {
2206 return ntpResult.currentTimeMillis();
Jeff Sharkey9911a282018-02-14 22:29:11 -07002207 } else {
2208 throw new ParcelableException(new DateTimeException("Missing NTP fix"));
2209 }
2210 }
2211
2212 @Override
Adam Lesinski182f73f2013-12-05 16:48:06 -08002213 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -06002214 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
Kweku Adams61e03292017-10-19 14:27:12 -07002215
2216 if (args.length > 0 && "--proto".equals(args[0])) {
2217 dumpProto(fd);
2218 } else {
2219 dumpImpl(pw);
2220 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07002221 }
mswest463f4c99d2018-02-01 10:13:10 -08002222
2223 @Override
2224 public void onShellCommand(FileDescriptor in, FileDescriptor out,
2225 FileDescriptor err, String[] args, ShellCallback callback,
2226 ResultReceiver resultReceiver) {
2227 (new ShellCmd()).exec(this, in, out, err, args, callback, resultReceiver);
2228 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08002229 };
Christopher Tate4cb338d2013-07-26 13:11:31 -07002230
Adam Lesinski182f73f2013-12-05 16:48:06 -08002231 void dumpImpl(PrintWriter pw) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002232 synchronized (mLock) {
2233 pw.println("Current Alarm Manager state:");
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08002234 mConstants.dump(pw, " ");
Dianne Hackborna750a632015-06-16 17:18:23 -07002235 pw.println();
2236
Makoto Onukie4918212018-02-06 11:30:15 -08002237 if (mAppStateTracker != null) {
2238 mAppStateTracker.dump(pw, " ");
2239 pw.println();
2240 }
Makoto Onuki2206af32017-11-21 16:25:35 -08002241
Suprabh Shukla75edab12018-01-29 14:09:06 -08002242 pw.println(" App Standby Parole: " + mAppStandbyParole);
2243 pw.println();
2244
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002245 final long nowELAPSED = mInjector.getElapsedRealtime();
Makoto Onukie8edbcf2018-03-02 16:49:29 -08002246 final long nowUPTIME = SystemClock.uptimeMillis();
Christopher Tatec8b7f432018-09-28 16:23:10 -07002247 final long nowRTC = mInjector.getCurrentTimeMillis();
Makoto Onuki5d93b832018-01-10 16:12:39 -08002248 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Christopher Tatee0a22b32013-07-11 14:43:13 -07002249
Dianne Hackborna750a632015-06-16 17:18:23 -07002250 pw.print(" nowRTC="); pw.print(nowRTC);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002251 pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
Christopher Tate7f2a0352015-12-08 10:24:33 -08002252 pw.print(" nowELAPSED="); pw.print(nowELAPSED);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002253 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002254 pw.print(" mLastTimeChangeClockTime="); pw.print(mLastTimeChangeClockTime);
Dianne Hackbornc3527222015-05-13 14:03:20 -07002255 pw.print("="); pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
Christopher Tate12cf0b62018-01-05 18:40:14 -08002256 pw.print(" mLastTimeChangeRealtime="); pw.println(mLastTimeChangeRealtime);
Christopher Tate12cf0b62018-01-05 18:40:14 -08002257 pw.print(" mLastTickReceived="); pw.println(sdf.format(new Date(mLastTickReceived)));
2258 pw.print(" mLastTickSet="); pw.println(sdf.format(new Date(mLastTickSet)));
Makoto Onuki5d93b832018-01-10 16:12:39 -08002259 pw.print(" mLastTickAdded="); pw.println(sdf.format(new Date(mLastTickAdded)));
2260 pw.print(" mLastTickRemoved="); pw.println(sdf.format(new Date(mLastTickRemoved)));
Makoto Onukie8edbcf2018-03-02 16:49:29 -08002261
Christopher Tatec8b7f432018-09-28 16:23:10 -07002262 if (RECORD_ALARMS_IN_HISTORY) {
2263 pw.println();
2264 pw.println(" Recent TIME_TICK history:");
2265 int i = mNextTickHistory;
2266 do {
2267 i--;
2268 if (i < 0) i = TICK_HISTORY_DEPTH - 1;
2269 final long time = mTickHistory[i];
2270 pw.print(" ");
2271 pw.println((time > 0)
2272 ? sdf.format(new Date(nowRTC - (nowELAPSED - time)))
2273 : "-");
2274 } while (i != mNextTickHistory);
Christopher Tatec8b7f432018-09-28 16:23:10 -07002275 }
2276
Makoto Onukie8edbcf2018-03-02 16:49:29 -08002277 SystemServiceManager ssm = LocalServices.getService(SystemServiceManager.class);
2278 if (ssm != null) {
2279 pw.println();
2280 pw.print(" RuntimeStarted=");
2281 pw.print(sdf.format(
2282 new Date(nowRTC - nowELAPSED + ssm.getRuntimeStartElapsedTime())));
2283 if (ssm.isRuntimeRestarted()) {
2284 pw.print(" (Runtime restarted)");
2285 }
2286 pw.println();
2287 pw.print(" Runtime uptime (elapsed): ");
2288 TimeUtils.formatDuration(nowELAPSED, ssm.getRuntimeStartElapsedTime(), pw);
2289 pw.println();
2290 pw.print(" Runtime uptime (uptime): ");
2291 TimeUtils.formatDuration(nowUPTIME, ssm.getRuntimeStartUptime(), pw);
2292 pw.println();
2293 }
2294
Dianne Hackbornc3527222015-05-13 14:03:20 -07002295 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002296 if (!mInteractive) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002297 pw.print(" Time since non-interactive: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002298 TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
2299 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002300 }
Makoto Onuki0b05aa62018-02-09 16:14:26 -08002301 pw.print(" Max wakeup delay: ");
2302 TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
2303 pw.println();
2304 pw.print(" Time since last dispatch: ");
2305 TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
2306 pw.println();
2307 pw.print(" Next non-wakeup delivery time: ");
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002308 TimeUtils.formatDuration(mNextNonWakeupDeliveryTime, nowELAPSED, pw);
Makoto Onuki0b05aa62018-02-09 16:14:26 -08002309 pw.println();
Christopher Tatee0a22b32013-07-11 14:43:13 -07002310
2311 long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
2312 long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
Dianne Hackborna750a632015-06-16 17:18:23 -07002313 pw.print(" Next non-wakeup alarm: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002314 TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
Christopher Tate8b98ade2018-02-09 11:13:19 -08002315 pw.print(" = "); pw.print(mNextNonWakeup);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002316 pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002317 pw.print(" set at "); TimeUtils.formatDuration(mNextNonWakeUpSetAt, nowELAPSED, pw);
2318 pw.println();
Christopher Tate8b98ade2018-02-09 11:13:19 -08002319 pw.print(" Next wakeup alarm: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
2320 pw.print(" = "); pw.print(mNextWakeup);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002321 pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002322 pw.print(" set at "); TimeUtils.formatDuration(mNextWakeUpSetAt, nowELAPSED, pw);
Christopher Tate8b98ade2018-02-09 11:13:19 -08002323 pw.println();
Suprabh Shukla2324e982018-06-05 21:06:22 -07002324
2325 pw.print(" Next kernel non-wakeup alarm: ");
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002326 TimeUtils.formatDuration(mInjector.getNextAlarm(ELAPSED_REALTIME), pw);
Suprabh Shukla2324e982018-06-05 21:06:22 -07002327 pw.println();
2328 pw.print(" Next kernel wakeup alarm: ");
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002329 TimeUtils.formatDuration(mInjector.getNextAlarm(ELAPSED_REALTIME_WAKEUP), pw);
Suprabh Shukla2324e982018-06-05 21:06:22 -07002330 pw.println();
2331
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07002332 pw.print(" Last wakeup: "); TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw);
Christopher Tate8b98ade2018-02-09 11:13:19 -08002333 pw.print(" = "); pw.println(mLastWakeup);
2334 pw.print(" Last trigger: "); TimeUtils.formatDuration(mLastTrigger, nowELAPSED, pw);
2335 pw.print(" = "); pw.println(mLastTrigger);
Dianne Hackborna750a632015-06-16 17:18:23 -07002336 pw.print(" Num time change events: "); pw.println(mNumTimeChanged);
Christopher Tatee0a22b32013-07-11 14:43:13 -07002337
John Spurlock604a5ee2015-06-01 12:27:22 -04002338 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002339 pw.println(" Next alarm clock information: ");
John Spurlock604a5ee2015-06-01 12:27:22 -04002340 final TreeSet<Integer> users = new TreeSet<>();
2341 for (int i = 0; i < mNextAlarmClockForUser.size(); i++) {
2342 users.add(mNextAlarmClockForUser.keyAt(i));
2343 }
2344 for (int i = 0; i < mPendingSendNextAlarmClockChangedForUser.size(); i++) {
2345 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
2346 }
2347 for (int user : users) {
2348 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
2349 final long time = next != null ? next.getTriggerTime() : 0;
2350 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
Dianne Hackborna750a632015-06-16 17:18:23 -07002351 pw.print(" user:"); pw.print(user);
John Spurlock604a5ee2015-06-01 12:27:22 -04002352 pw.print(" pendingSend:"); pw.print(pendingSend);
2353 pw.print(" time:"); pw.print(time);
2354 if (time > 0) {
2355 pw.print(" = "); pw.print(sdf.format(new Date(time)));
2356 pw.print(" = "); TimeUtils.formatDuration(time, nowRTC, pw);
2357 }
2358 pw.println();
2359 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07002360 if (mAlarmBatches.size() > 0) {
2361 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002362 pw.print(" Pending alarm batches: ");
Christopher Tatee0a22b32013-07-11 14:43:13 -07002363 pw.println(mAlarmBatches.size());
2364 for (Batch b : mAlarmBatches) {
2365 pw.print(b); pw.println(':');
Dianne Hackborna750a632015-06-16 17:18:23 -07002366 dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07002369 pw.println();
2370 pw.println(" Pending user blocked background alarms: ");
2371 boolean blocked = false;
2372 for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
2373 final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
2374 if (blockedAlarms != null && blockedAlarms.size() > 0) {
2375 blocked = true;
2376 dumpAlarmList(pw, blockedAlarms, " ", nowELAPSED, nowRTC, sdf);
2377 }
2378 }
2379 if (!blocked) {
2380 pw.println(" none");
2381 }
Suprabh Shukla0e49b642019-03-04 14:14:32 -08002382 pw.println();
2383 pw.print(" Pending alarms per uid: [");
2384 for (int i = 0; i < mAlarmsPerUid.size(); i++) {
2385 if (i > 0) {
2386 pw.print(", ");
2387 }
2388 UserHandle.formatUid(pw, mAlarmsPerUid.keyAt(i));
2389 pw.print(":");
2390 pw.print(mAlarmsPerUid.valueAt(i));
2391 }
2392 pw.println("]");
2393 pw.println();
Suprabh Shuklac25447d2018-01-19 16:43:35 -08002394
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08002395 mAppWakeupHistory.dump(pw, " ", nowELAPSED);
Suprabh Shukla75edab12018-01-29 14:09:06 -08002396
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002397 if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002398 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002399 pw.println(" Idle mode state:");
2400 pw.print(" Idling until: ");
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002401 if (mPendingIdleUntil != null) {
2402 pw.println(mPendingIdleUntil);
Kweku Adams61e03292017-10-19 14:27:12 -07002403 mPendingIdleUntil.dump(pw, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn0b4daca2015-04-27 09:47:32 -07002404 } else {
2405 pw.println("null");
2406 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002407 pw.println(" Pending alarms:");
2408 dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07002409 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002410 if (mNextWakeFromIdle != null) {
2411 pw.println();
2412 pw.print(" Next wake from idle: "); pw.println(mNextWakeFromIdle);
Kweku Adams61e03292017-10-19 14:27:12 -07002413 mNextWakeFromIdle.dump(pw, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002414 }
Dianne Hackborn81038902012-11-26 17:04:09 -08002415
2416 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002417 pw.print(" Past-due non-wakeup alarms: ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002418 if (mPendingNonWakeupAlarms.size() > 0) {
2419 pw.println(mPendingNonWakeupAlarms.size());
Dianne Hackborna750a632015-06-16 17:18:23 -07002420 dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002421 } else {
2422 pw.println("(none)");
2423 }
Dianne Hackborna750a632015-06-16 17:18:23 -07002424 pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002425 pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
2426 pw.println();
Dianne Hackborna750a632015-06-16 17:18:23 -07002427 pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002428 pw.print(", max non-interactive time: ");
2429 TimeUtils.formatDuration(mNonInteractiveTime, pw);
2430 pw.println();
2431
2432 pw.println();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002433 pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
Christopher Tateeabba732017-08-17 17:12:52 -07002434 pw.print(" PendingIntent send count: "); pw.println(mSendCount);
2435 pw.print(" PendingIntent finish count: "); pw.println(mSendFinishCount);
2436 pw.print(" Listener send count: "); pw.println(mListenerCount);
2437 pw.print(" Listener finish count: "); pw.println(mListenerFinishCount);
Dianne Hackborn81038902012-11-26 17:04:09 -08002438 pw.println();
2439
Christopher Tate7f2a0352015-12-08 10:24:33 -08002440 if (mInFlight.size() > 0) {
2441 pw.println("Outstanding deliveries:");
2442 for (int i = 0; i < mInFlight.size(); i++) {
2443 pw.print(" #"); pw.print(i); pw.print(": ");
2444 pw.println(mInFlight.get(i));
2445 }
2446 pw.println();
2447 }
2448
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002449 if (mLastAllowWhileIdleDispatch.size() > 0) {
Dianne Hackborna750a632015-06-16 17:18:23 -07002450 pw.println(" Last allow while idle dispatch times:");
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002451 for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
Makoto Onukiadb50d82018-01-29 16:20:30 -08002452 pw.print(" UID ");
2453 final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
2454 UserHandle.formatUid(pw, uid);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002455 pw.print(": ");
Makoto Onukiadb50d82018-01-29 16:20:30 -08002456 final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
2457 TimeUtils.formatDuration(lastTime, nowELAPSED, pw);
2458
2459 final long minInterval = getWhileIdleMinIntervalLocked(uid);
2460 pw.print(" Next allowed:");
2461 TimeUtils.formatDuration(lastTime + minInterval, nowELAPSED, pw);
2462 pw.print(" (");
2463 TimeUtils.formatDuration(minInterval, 0, pw);
2464 pw.print(")");
2465
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002466 pw.println();
2467 }
2468 }
Makoto Onukiadb50d82018-01-29 16:20:30 -08002469
2470 pw.print(" mUseAllowWhileIdleShortTime: [");
2471 for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
2472 if (mUseAllowWhileIdleShortTime.valueAt(i)) {
2473 UserHandle.formatUid(pw, mUseAllowWhileIdleShortTime.keyAt(i));
2474 pw.print(" ");
2475 }
2476 }
2477 pw.println("]");
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002478 pw.println();
2479
Dianne Hackborn81038902012-11-26 17:04:09 -08002480 if (mLog.dump(pw, " Recent problems", " ")) {
2481 pw.println();
2482 }
2483
2484 final FilterStats[] topFilters = new FilterStats[10];
2485 final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
2486 @Override
2487 public int compare(FilterStats lhs, FilterStats rhs) {
2488 if (lhs.aggregateTime < rhs.aggregateTime) {
2489 return 1;
2490 } else if (lhs.aggregateTime > rhs.aggregateTime) {
2491 return -1;
2492 }
2493 return 0;
2494 }
2495 };
2496 int len = 0;
Kweku Adams61e03292017-10-19 14:27:12 -07002497 // Get the top 10 FilterStats, ordered by aggregateTime.
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002498 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
2499 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2500 for (int ip=0; ip<uidStats.size(); ip++) {
2501 BroadcastStats bs = uidStats.valueAt(ip);
2502 for (int is=0; is<bs.filterStats.size(); is++) {
2503 FilterStats fs = bs.filterStats.valueAt(is);
2504 int pos = len > 0
2505 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
2506 if (pos < 0) {
2507 pos = -pos - 1;
Dianne Hackborn81038902012-11-26 17:04:09 -08002508 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002509 if (pos < topFilters.length) {
2510 int copylen = topFilters.length - pos - 1;
2511 if (copylen > 0) {
2512 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
2513 }
2514 topFilters[pos] = fs;
2515 if (len < topFilters.length) {
2516 len++;
2517 }
Dianne Hackborn81038902012-11-26 17:04:09 -08002518 }
2519 }
2520 }
2521 }
2522 if (len > 0) {
2523 pw.println(" Top Alarms:");
2524 for (int i=0; i<len; i++) {
2525 FilterStats fs = topFilters[i];
2526 pw.print(" ");
2527 if (fs.nesting > 0) pw.print("*ACTIVE* ");
2528 TimeUtils.formatDuration(fs.aggregateTime, pw);
2529 pw.print(" running, "); pw.print(fs.numWakeup);
2530 pw.print(" wakeups, "); pw.print(fs.count);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002531 pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
2532 pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
Dianne Hackborn81038902012-11-26 17:04:09 -08002533 pw.println();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002534 pw.print(" "); pw.print(fs.mTag);
Dianne Hackborn81038902012-11-26 17:04:09 -08002535 pw.println();
2536 }
2537 }
2538
2539 pw.println(" ");
2540 pw.println(" Alarm Stats:");
2541 final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002542 for (int iu=0; iu<mBroadcastStats.size(); iu++) {
2543 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2544 for (int ip=0; ip<uidStats.size(); ip++) {
2545 BroadcastStats bs = uidStats.valueAt(ip);
2546 pw.print(" ");
2547 if (bs.nesting > 0) pw.print("*ACTIVE* ");
2548 UserHandle.formatUid(pw, bs.mUid);
2549 pw.print(":");
2550 pw.print(bs.mPackageName);
2551 pw.print(" "); TimeUtils.formatDuration(bs.aggregateTime, pw);
2552 pw.print(" running, "); pw.print(bs.numWakeup);
2553 pw.println(" wakeups:");
2554 tmpFilters.clear();
2555 for (int is=0; is<bs.filterStats.size(); is++) {
2556 tmpFilters.add(bs.filterStats.valueAt(is));
2557 }
2558 Collections.sort(tmpFilters, comparator);
2559 for (int i=0; i<tmpFilters.size(); i++) {
2560 FilterStats fs = tmpFilters.get(i);
2561 pw.print(" ");
2562 if (fs.nesting > 0) pw.print("*ACTIVE* ");
2563 TimeUtils.formatDuration(fs.aggregateTime, pw);
2564 pw.print(" "); pw.print(fs.numWakeup);
2565 pw.print(" wakes " ); pw.print(fs.count);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002566 pw.print(" alarms, last ");
2567 TimeUtils.formatDuration(fs.lastTime, nowELAPSED, pw);
2568 pw.println(":");
2569 pw.print(" ");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002570 pw.print(fs.mTag);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08002571 pw.println();
2572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002573 }
2574 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08002575 pw.println();
2576 mStatLogger.dump(pw, " ");
Christopher Tate18a75f12013-07-01 18:18:59 -07002577
Dianne Hackbornae78bf82015-10-26 13:33:20 -07002578 if (RECORD_DEVICE_IDLE_ALARMS) {
2579 pw.println();
2580 pw.println(" Allow while idle dispatches:");
2581 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
2582 IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
2583 pw.print(" ");
2584 TimeUtils.formatDuration(ent.elapsedRealtime, nowELAPSED, pw);
2585 pw.print(": ");
2586 UserHandle.formatUid(pw, ent.uid);
2587 pw.print(":");
2588 pw.println(ent.pkg);
2589 if (ent.op != null) {
2590 pw.print(" ");
2591 pw.print(ent.op);
2592 pw.print(" / ");
2593 pw.print(ent.tag);
2594 if (ent.argRealtime != 0) {
2595 pw.print(" (");
2596 TimeUtils.formatDuration(ent.argRealtime, nowELAPSED, pw);
2597 pw.print(")");
2598 }
2599 pw.println();
2600 }
2601 }
2602 }
2603
Christopher Tate18a75f12013-07-01 18:18:59 -07002604 if (WAKEUP_STATS) {
2605 pw.println();
2606 pw.println(" Recent Wakeup History:");
Christopher Tate18a75f12013-07-01 18:18:59 -07002607 long last = -1;
2608 for (WakeupEvent event : mRecentWakeups) {
2609 pw.print(" "); pw.print(sdf.format(new Date(event.when)));
2610 pw.print('|');
2611 if (last < 0) {
2612 pw.print('0');
2613 } else {
2614 pw.print(event.when - last);
2615 }
2616 last = event.when;
2617 pw.print('|'); pw.print(event.uid);
2618 pw.print('|'); pw.print(event.action);
2619 pw.println();
2620 }
2621 pw.println();
2622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 }
2624 }
2625
Kweku Adams61e03292017-10-19 14:27:12 -07002626 void dumpProto(FileDescriptor fd) {
2627 final ProtoOutputStream proto = new ProtoOutputStream(fd);
2628
2629 synchronized (mLock) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002630 final long nowRTC = mInjector.getCurrentTimeMillis();
2631 final long nowElapsed = mInjector.getElapsedRealtime();
Yi Jin2b30f322018-02-20 15:41:47 -08002632 proto.write(AlarmManagerServiceDumpProto.CURRENT_TIME, nowRTC);
2633 proto.write(AlarmManagerServiceDumpProto.ELAPSED_REALTIME, nowElapsed);
2634 proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_CLOCK_TIME,
Kweku Adams61e03292017-10-19 14:27:12 -07002635 mLastTimeChangeClockTime);
Yi Jin2b30f322018-02-20 15:41:47 -08002636 proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_REALTIME,
Kweku Adams61e03292017-10-19 14:27:12 -07002637 mLastTimeChangeRealtime);
2638
Yi Jin2b30f322018-02-20 15:41:47 -08002639 mConstants.dumpProto(proto, AlarmManagerServiceDumpProto.SETTINGS);
Kweku Adams61e03292017-10-19 14:27:12 -07002640
Makoto Onukie4918212018-02-06 11:30:15 -08002641 if (mAppStateTracker != null) {
Kweku Adamsc3f9ba62019-08-01 12:14:55 -07002642 mAppStateTracker.dumpProto(proto, AlarmManagerServiceDumpProto.APP_STATE_TRACKER);
Makoto Onukie4918212018-02-06 11:30:15 -08002643 }
Kweku Adams61e03292017-10-19 14:27:12 -07002644
Yi Jin2b30f322018-02-20 15:41:47 -08002645 proto.write(AlarmManagerServiceDumpProto.IS_INTERACTIVE, mInteractive);
Kweku Adams61e03292017-10-19 14:27:12 -07002646 if (!mInteractive) {
2647 // Durations
Yi Jin2b30f322018-02-20 15:41:47 -08002648 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_NON_INTERACTIVE_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002649 nowElapsed - mNonInteractiveStartTime);
Yi Jin2b30f322018-02-20 15:41:47 -08002650 proto.write(AlarmManagerServiceDumpProto.MAX_WAKEUP_DELAY_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002651 currentNonWakeupFuzzLocked(nowElapsed));
Yi Jin2b30f322018-02-20 15:41:47 -08002652 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_DISPATCH_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002653 nowElapsed - mLastAlarmDeliveryTime);
Yi Jin2b30f322018-02-20 15:41:47 -08002654 proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_NON_WAKEUP_DELIVERY_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002655 nowElapsed - mNextNonWakeupDeliveryTime);
2656 }
2657
Yi Jin2b30f322018-02-20 15:41:47 -08002658 proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_NON_WAKEUP_ALARM_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002659 mNextNonWakeup - nowElapsed);
Yi Jin2b30f322018-02-20 15:41:47 -08002660 proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_WAKEUP_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002661 mNextWakeup - nowElapsed);
Yi Jin2b30f322018-02-20 15:41:47 -08002662 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_WAKEUP_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002663 nowElapsed - mLastWakeup);
Yi Jin2b30f322018-02-20 15:41:47 -08002664 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_WAKEUP_SET_MS,
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07002665 nowElapsed - mNextWakeUpSetAt);
Yi Jin2b30f322018-02-20 15:41:47 -08002666 proto.write(AlarmManagerServiceDumpProto.TIME_CHANGE_EVENT_COUNT, mNumTimeChanged);
Kweku Adams61e03292017-10-19 14:27:12 -07002667
2668 final TreeSet<Integer> users = new TreeSet<>();
2669 final int nextAlarmClockForUserSize = mNextAlarmClockForUser.size();
2670 for (int i = 0; i < nextAlarmClockForUserSize; i++) {
2671 users.add(mNextAlarmClockForUser.keyAt(i));
2672 }
2673 final int pendingSendNextAlarmClockChangedForUserSize =
2674 mPendingSendNextAlarmClockChangedForUser.size();
2675 for (int i = 0; i < pendingSendNextAlarmClockChangedForUserSize; i++) {
2676 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
2677 }
2678 for (int user : users) {
2679 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
2680 final long time = next != null ? next.getTriggerTime() : 0;
2681 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
Yi Jin2b30f322018-02-20 15:41:47 -08002682 final long aToken = proto.start(AlarmManagerServiceDumpProto.NEXT_ALARM_CLOCK_METADATA);
Kweku Adams61e03292017-10-19 14:27:12 -07002683 proto.write(AlarmClockMetadataProto.USER, user);
2684 proto.write(AlarmClockMetadataProto.IS_PENDING_SEND, pendingSend);
2685 proto.write(AlarmClockMetadataProto.TRIGGER_TIME_MS, time);
2686 proto.end(aToken);
2687 }
2688 for (Batch b : mAlarmBatches) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08002689 b.dumpDebug(proto, AlarmManagerServiceDumpProto.PENDING_ALARM_BATCHES,
Kweku Adams61e03292017-10-19 14:27:12 -07002690 nowElapsed, nowRTC);
2691 }
2692 for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
2693 final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
2694 if (blockedAlarms != null) {
2695 for (Alarm a : blockedAlarms) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08002696 a.dumpDebug(proto,
Yi Jin2b30f322018-02-20 15:41:47 -08002697 AlarmManagerServiceDumpProto.PENDING_USER_BLOCKED_BACKGROUND_ALARMS,
Kweku Adams61e03292017-10-19 14:27:12 -07002698 nowElapsed, nowRTC);
2699 }
2700 }
2701 }
2702 if (mPendingIdleUntil != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08002703 mPendingIdleUntil.dumpDebug(
Yi Jin2b30f322018-02-20 15:41:47 -08002704 proto, AlarmManagerServiceDumpProto.PENDING_IDLE_UNTIL, nowElapsed, nowRTC);
Kweku Adams61e03292017-10-19 14:27:12 -07002705 }
2706 for (Alarm a : mPendingWhileIdleAlarms) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08002707 a.dumpDebug(proto, AlarmManagerServiceDumpProto.PENDING_WHILE_IDLE_ALARMS,
Kweku Adams61e03292017-10-19 14:27:12 -07002708 nowElapsed, nowRTC);
2709 }
2710 if (mNextWakeFromIdle != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08002711 mNextWakeFromIdle.dumpDebug(proto, AlarmManagerServiceDumpProto.NEXT_WAKE_FROM_IDLE,
Kweku Adams61e03292017-10-19 14:27:12 -07002712 nowElapsed, nowRTC);
2713 }
2714
2715 for (Alarm a : mPendingNonWakeupAlarms) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08002716 a.dumpDebug(proto, AlarmManagerServiceDumpProto.PAST_DUE_NON_WAKEUP_ALARMS,
Kweku Adams61e03292017-10-19 14:27:12 -07002717 nowElapsed, nowRTC);
2718 }
2719
Yi Jin2b30f322018-02-20 15:41:47 -08002720 proto.write(AlarmManagerServiceDumpProto.DELAYED_ALARM_COUNT, mNumDelayedAlarms);
2721 proto.write(AlarmManagerServiceDumpProto.TOTAL_DELAY_TIME_MS, mTotalDelayTime);
2722 proto.write(AlarmManagerServiceDumpProto.MAX_DELAY_DURATION_MS, mMaxDelayTime);
2723 proto.write(AlarmManagerServiceDumpProto.MAX_NON_INTERACTIVE_DURATION_MS,
Kweku Adams61e03292017-10-19 14:27:12 -07002724 mNonInteractiveTime);
2725
Yi Jin2b30f322018-02-20 15:41:47 -08002726 proto.write(AlarmManagerServiceDumpProto.BROADCAST_REF_COUNT, mBroadcastRefCount);
2727 proto.write(AlarmManagerServiceDumpProto.PENDING_INTENT_SEND_COUNT, mSendCount);
2728 proto.write(AlarmManagerServiceDumpProto.PENDING_INTENT_FINISH_COUNT, mSendFinishCount);
2729 proto.write(AlarmManagerServiceDumpProto.LISTENER_SEND_COUNT, mListenerCount);
2730 proto.write(AlarmManagerServiceDumpProto.LISTENER_FINISH_COUNT, mListenerFinishCount);
Kweku Adams61e03292017-10-19 14:27:12 -07002731
2732 for (InFlight f : mInFlight) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08002733 f.dumpDebug(proto, AlarmManagerServiceDumpProto.OUTSTANDING_DELIVERIES);
Kweku Adams61e03292017-10-19 14:27:12 -07002734 }
2735
Kweku Adams61e03292017-10-19 14:27:12 -07002736 for (int i = 0; i < mLastAllowWhileIdleDispatch.size(); ++i) {
2737 final long token = proto.start(
Yi Jin2b30f322018-02-20 15:41:47 -08002738 AlarmManagerServiceDumpProto.LAST_ALLOW_WHILE_IDLE_DISPATCH_TIMES);
Makoto Onukiadb50d82018-01-29 16:20:30 -08002739 final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
2740 final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
2741
Yi Jin2b30f322018-02-20 15:41:47 -08002742 proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.UID, uid);
2743 proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.TIME_MS, lastTime);
2744 proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.NEXT_ALLOWED_MS,
Makoto Onukiadb50d82018-01-29 16:20:30 -08002745 lastTime + getWhileIdleMinIntervalLocked(uid));
Kweku Adams61e03292017-10-19 14:27:12 -07002746 proto.end(token);
2747 }
2748
Makoto Onukiadb50d82018-01-29 16:20:30 -08002749 for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
2750 if (mUseAllowWhileIdleShortTime.valueAt(i)) {
Yi Jin2b30f322018-02-20 15:41:47 -08002751 proto.write(AlarmManagerServiceDumpProto.USE_ALLOW_WHILE_IDLE_SHORT_TIME,
Makoto Onukiadb50d82018-01-29 16:20:30 -08002752 mUseAllowWhileIdleShortTime.keyAt(i));
2753 }
2754 }
2755
Jeffrey Huangcb782852019-12-05 11:28:11 -08002756 mLog.dumpDebug(proto, AlarmManagerServiceDumpProto.RECENT_PROBLEMS);
Kweku Adams61e03292017-10-19 14:27:12 -07002757
2758 final FilterStats[] topFilters = new FilterStats[10];
2759 final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
2760 @Override
2761 public int compare(FilterStats lhs, FilterStats rhs) {
2762 if (lhs.aggregateTime < rhs.aggregateTime) {
2763 return 1;
2764 } else if (lhs.aggregateTime > rhs.aggregateTime) {
2765 return -1;
2766 }
2767 return 0;
2768 }
2769 };
2770 int len = 0;
2771 // Get the top 10 FilterStats, ordered by aggregateTime.
2772 for (int iu = 0; iu < mBroadcastStats.size(); ++iu) {
2773 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2774 for (int ip = 0; ip < uidStats.size(); ++ip) {
2775 BroadcastStats bs = uidStats.valueAt(ip);
2776 for (int is = 0; is < bs.filterStats.size(); ++is) {
2777 FilterStats fs = bs.filterStats.valueAt(is);
2778 int pos = len > 0
2779 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
2780 if (pos < 0) {
2781 pos = -pos - 1;
2782 }
2783 if (pos < topFilters.length) {
2784 int copylen = topFilters.length - pos - 1;
2785 if (copylen > 0) {
2786 System.arraycopy(topFilters, pos, topFilters, pos+1, copylen);
2787 }
2788 topFilters[pos] = fs;
2789 if (len < topFilters.length) {
2790 len++;
2791 }
2792 }
2793 }
2794 }
2795 }
2796 for (int i = 0; i < len; ++i) {
Yi Jin2b30f322018-02-20 15:41:47 -08002797 final long token = proto.start(AlarmManagerServiceDumpProto.TOP_ALARMS);
Kweku Adams61e03292017-10-19 14:27:12 -07002798 FilterStats fs = topFilters[i];
2799
Yi Jin2b30f322018-02-20 15:41:47 -08002800 proto.write(AlarmManagerServiceDumpProto.TopAlarm.UID, fs.mBroadcastStats.mUid);
2801 proto.write(AlarmManagerServiceDumpProto.TopAlarm.PACKAGE_NAME,
Kweku Adams61e03292017-10-19 14:27:12 -07002802 fs.mBroadcastStats.mPackageName);
Jeffrey Huangcb782852019-12-05 11:28:11 -08002803 fs.dumpDebug(proto, AlarmManagerServiceDumpProto.TopAlarm.FILTER);
Kweku Adams61e03292017-10-19 14:27:12 -07002804
2805 proto.end(token);
2806 }
2807
2808 final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
2809 for (int iu = 0; iu < mBroadcastStats.size(); ++iu) {
2810 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
2811 for (int ip = 0; ip < uidStats.size(); ++ip) {
Yi Jin2b30f322018-02-20 15:41:47 -08002812 final long token = proto.start(AlarmManagerServiceDumpProto.ALARM_STATS);
Kweku Adams61e03292017-10-19 14:27:12 -07002813
2814 BroadcastStats bs = uidStats.valueAt(ip);
Jeffrey Huangcb782852019-12-05 11:28:11 -08002815 bs.dumpDebug(proto, AlarmManagerServiceDumpProto.AlarmStat.BROADCAST);
Kweku Adams61e03292017-10-19 14:27:12 -07002816
2817 // uidStats is an ArrayMap, which we can't sort.
2818 tmpFilters.clear();
2819 for (int is = 0; is < bs.filterStats.size(); ++is) {
2820 tmpFilters.add(bs.filterStats.valueAt(is));
2821 }
2822 Collections.sort(tmpFilters, comparator);
2823 for (FilterStats fs : tmpFilters) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08002824 fs.dumpDebug(proto, AlarmManagerServiceDumpProto.AlarmStat.FILTERS);
Kweku Adams61e03292017-10-19 14:27:12 -07002825 }
2826
2827 proto.end(token);
2828 }
2829 }
2830
2831 if (RECORD_DEVICE_IDLE_ALARMS) {
2832 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
2833 IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
2834 final long token = proto.start(
Yi Jin2b30f322018-02-20 15:41:47 -08002835 AlarmManagerServiceDumpProto.ALLOW_WHILE_IDLE_DISPATCHES);
Kweku Adams61e03292017-10-19 14:27:12 -07002836
2837 proto.write(IdleDispatchEntryProto.UID, ent.uid);
2838 proto.write(IdleDispatchEntryProto.PKG, ent.pkg);
2839 proto.write(IdleDispatchEntryProto.TAG, ent.tag);
2840 proto.write(IdleDispatchEntryProto.OP, ent.op);
2841 proto.write(IdleDispatchEntryProto.ENTRY_CREATION_REALTIME,
2842 ent.elapsedRealtime);
2843 proto.write(IdleDispatchEntryProto.ARG_REALTIME, ent.argRealtime);
2844
2845 proto.end(token);
2846 }
2847 }
2848
2849 if (WAKEUP_STATS) {
2850 for (WakeupEvent event : mRecentWakeups) {
Yi Jin2b30f322018-02-20 15:41:47 -08002851 final long token = proto.start(AlarmManagerServiceDumpProto.RECENT_WAKEUP_HISTORY);
Kweku Adams61e03292017-10-19 14:27:12 -07002852 proto.write(WakeupEventProto.UID, event.uid);
2853 proto.write(WakeupEventProto.ACTION, event.action);
2854 proto.write(WakeupEventProto.WHEN, event.when);
2855 proto.end(token);
2856 }
2857 }
2858 }
2859
2860 proto.flush();
2861 }
2862
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002863 private void logBatchesLocked(SimpleDateFormat sdf) {
Adam Lesinski182f73f2013-12-05 16:48:06 -08002864 ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
2865 PrintWriter pw = new PrintWriter(bs);
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07002866 final long nowRTC = mInjector.getCurrentTimeMillis();
2867 final long nowELAPSED = mInjector.getElapsedRealtime();
Adam Lesinski182f73f2013-12-05 16:48:06 -08002868 final int NZ = mAlarmBatches.size();
2869 for (int iz = 0; iz < NZ; iz++) {
2870 Batch bz = mAlarmBatches.get(iz);
2871 pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002872 dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC, sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002873 pw.flush();
2874 Slog.v(TAG, bs.toString());
2875 bs.reset();
2876 }
2877 }
2878
2879 private boolean validateConsistencyLocked() {
2880 if (DEBUG_VALIDATE) {
2881 long lastTime = Long.MIN_VALUE;
2882 final int N = mAlarmBatches.size();
2883 for (int i = 0; i < N; i++) {
2884 Batch b = mAlarmBatches.get(i);
2885 if (b.start >= lastTime) {
2886 // duplicate start times are okay because of standalone batches
2887 lastTime = b.start;
2888 } else {
2889 Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07002890 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2891 logBatchesLocked(sdf);
Adam Lesinski182f73f2013-12-05 16:48:06 -08002892 return false;
2893 }
2894 }
2895 }
2896 return true;
2897 }
2898
Christopher Tate0dab4dc2014-12-16 12:14:06 -08002899 private Batch findFirstWakeupBatchLocked() {
2900 final int N = mAlarmBatches.size();
2901 for (int i = 0; i < N; i++) {
2902 Batch b = mAlarmBatches.get(i);
2903 if (b.hasWakeups()) {
2904 return b;
2905 }
2906 }
2907 return null;
2908 }
2909
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002910 long getNextWakeFromIdleTimeImpl() {
2911 synchronized (mLock) {
2912 return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE;
2913 }
2914 }
2915
Kweku Adamsb7ce1902019-01-30 10:55:34 -08002916 private boolean isIdlingImpl() {
2917 synchronized (mLock) {
2918 return mPendingIdleUntil != null;
2919 }
2920 }
2921
Dianne Hackbornf70faed2015-04-21 14:11:38 -07002922 AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02002923 synchronized (mLock) {
2924 return mNextAlarmClockForUser.get(userId);
2925 }
2926 }
2927
2928 /**
2929 * Recomputes the next alarm clock for all users.
2930 */
2931 private void updateNextAlarmClockLocked() {
2932 if (!mNextAlarmClockMayChange) {
2933 return;
2934 }
2935 mNextAlarmClockMayChange = false;
2936
Jose Lima235510e2014-08-13 12:50:01 -07002937 SparseArray<AlarmManager.AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02002938 nextForUser.clear();
2939
2940 final int N = mAlarmBatches.size();
2941 for (int i = 0; i < N; i++) {
2942 ArrayList<Alarm> alarms = mAlarmBatches.get(i).alarms;
2943 final int M = alarms.size();
2944
2945 for (int j = 0; j < M; j++) {
2946 Alarm a = alarms.get(j);
2947 if (a.alarmClock != null) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07002948 final int userId = UserHandle.getUserId(a.uid);
Christopher Tate76389c02016-08-03 14:57:47 -07002949 AlarmManager.AlarmClockInfo current = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002950
2951 if (DEBUG_ALARM_CLOCK) {
Christopher Tate76389c02016-08-03 14:57:47 -07002952 Log.v(TAG, "Found AlarmClockInfo " + a.alarmClock + " at " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01002953 formatNextAlarm(getContext(), a.alarmClock, userId) +
Adrian Roosc42a1e12014-07-07 23:35:53 +02002954 " for user " + userId);
2955 }
2956
2957 // Alarms and batches are sorted by time, no need to compare times here.
2958 if (nextForUser.get(userId) == null) {
2959 nextForUser.put(userId, a.alarmClock);
Christopher Tate76389c02016-08-03 14:57:47 -07002960 } else if (a.alarmClock.equals(current)
2961 && current.getTriggerTime() <= nextForUser.get(userId).getTriggerTime()) {
2962 // same/earlier time and it's the one we cited before, so stick with it
2963 nextForUser.put(userId, current);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002964 }
2965 }
2966 }
2967 }
2968
2969 // Update mNextAlarmForUser with new values.
2970 final int NN = nextForUser.size();
2971 for (int i = 0; i < NN; i++) {
Jose Lima235510e2014-08-13 12:50:01 -07002972 AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002973 int userId = nextForUser.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07002974 AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
Adrian Roosc42a1e12014-07-07 23:35:53 +02002975 if (!newAlarm.equals(currentAlarm)) {
2976 updateNextAlarmInfoForUserLocked(userId, newAlarm);
2977 }
2978 }
2979
2980 // Remove users without any alarm clocks scheduled.
2981 final int NNN = mNextAlarmClockForUser.size();
2982 for (int i = NNN - 1; i >= 0; i--) {
2983 int userId = mNextAlarmClockForUser.keyAt(i);
2984 if (nextForUser.get(userId) == null) {
2985 updateNextAlarmInfoForUserLocked(userId, null);
2986 }
2987 }
2988 }
2989
Jose Lima235510e2014-08-13 12:50:01 -07002990 private void updateNextAlarmInfoForUserLocked(int userId,
2991 AlarmManager.AlarmClockInfo alarmClock) {
Adrian Roosc42a1e12014-07-07 23:35:53 +02002992 if (alarmClock != null) {
2993 if (DEBUG_ALARM_CLOCK) {
2994 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
Selim Cinek9c4a7072014-11-21 17:44:34 +01002995 formatNextAlarm(getContext(), alarmClock, userId));
Adrian Roosc42a1e12014-07-07 23:35:53 +02002996 }
2997 mNextAlarmClockForUser.put(userId, alarmClock);
2998 } else {
2999 if (DEBUG_ALARM_CLOCK) {
3000 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None");
3001 }
3002 mNextAlarmClockForUser.remove(userId);
3003 }
3004
3005 mPendingSendNextAlarmClockChangedForUser.put(userId, true);
3006 mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
3007 mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
3008 }
3009
3010 /**
3011 * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
3012 * for which alarm clocks have changed since the last call to this.
3013 *
3014 * Do not call with a lock held. Only call from mHandler's thread.
3015 *
3016 * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
3017 */
3018 private void sendNextAlarmClockChanged() {
Jose Lima235510e2014-08-13 12:50:01 -07003019 SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
Adrian Roosc42a1e12014-07-07 23:35:53 +02003020 pendingUsers.clear();
3021
3022 synchronized (mLock) {
3023 final int N = mPendingSendNextAlarmClockChangedForUser.size();
3024 for (int i = 0; i < N; i++) {
3025 int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i);
3026 pendingUsers.append(userId, mNextAlarmClockForUser.get(userId));
3027 }
3028 mPendingSendNextAlarmClockChangedForUser.clear();
3029 }
3030
3031 final int N = pendingUsers.size();
3032 for (int i = 0; i < N; i++) {
3033 int userId = pendingUsers.keyAt(i);
Jose Lima235510e2014-08-13 12:50:01 -07003034 AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
Adrian Roosc42a1e12014-07-07 23:35:53 +02003035 Settings.System.putStringForUser(getContext().getContentResolver(),
3036 Settings.System.NEXT_ALARM_FORMATTED,
Selim Cinek9c4a7072014-11-21 17:44:34 +01003037 formatNextAlarm(getContext(), alarmClock, userId),
Adrian Roosc42a1e12014-07-07 23:35:53 +02003038 userId);
3039
3040 getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT,
3041 new UserHandle(userId));
3042 }
3043 }
3044
3045 /**
3046 * Formats an alarm like platform/packages/apps/DeskClock used to.
3047 */
Selim Cinek9c4a7072014-11-21 17:44:34 +01003048 private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info,
3049 int userId) {
3050 String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma";
Adrian Roosc42a1e12014-07-07 23:35:53 +02003051 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
3052 return (info == null) ? "" :
3053 DateFormat.format(pattern, info.getTriggerTime()).toString();
3054 }
3055
Adam Lesinski182f73f2013-12-05 16:48:06 -08003056 void rescheduleKernelAlarmsLocked() {
3057 // Schedule the next upcoming wakeup alarm. If there is a deliverable batch
3058 // prior to that which contains no wakeups, we schedule that as well.
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003059 final long nowElapsed = mInjector.getElapsedRealtime();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003060 long nextNonWakeup = 0;
Adam Lesinski182f73f2013-12-05 16:48:06 -08003061 if (mAlarmBatches.size() > 0) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08003062 final Batch firstWakeup = findFirstWakeupBatchLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08003063 final Batch firstBatch = mAlarmBatches.get(0);
Suprabh Shukla2fa95452018-02-12 12:53:23 -08003064 if (firstWakeup != null) {
Christopher Tate0dab4dc2014-12-16 12:14:06 -08003065 mNextWakeup = firstWakeup.start;
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07003066 mNextWakeUpSetAt = nowElapsed;
Christopher Tate0dab4dc2014-12-16 12:14:06 -08003067 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003068 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003069 if (firstBatch != firstWakeup) {
3070 nextNonWakeup = firstBatch.start;
Adam Lesinski182f73f2013-12-05 16:48:06 -08003071 }
3072 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003073 if (mPendingNonWakeupAlarms.size() > 0) {
3074 if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
3075 nextNonWakeup = mNextNonWakeupDeliveryTime;
3076 }
3077 }
Suprabh Shukla2fa95452018-02-12 12:53:23 -08003078 if (nextNonWakeup != 0) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003079 mNextNonWakeup = nextNonWakeup;
Suprabh Shukla0e4510d2018-06-20 17:28:26 -07003080 mNextNonWakeUpSetAt = nowElapsed;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003081 setLocked(ELAPSED_REALTIME, nextNonWakeup);
3082 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08003083 }
3084
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003085 void removeLocked(PendingIntent operation, IAlarmListener directReceiver) {
Christopher Tate1d99c392017-12-07 16:54:04 -08003086 if (operation == null && directReceiver == null) {
3087 if (localLOGV) {
3088 Slog.w(TAG, "requested remove() of null operation",
3089 new RuntimeException("here"));
3090 }
3091 return;
3092 }
3093
Adam Lesinski182f73f2013-12-05 16:48:06 -08003094 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08003095 final Predicate<Alarm> whichAlarms = (Alarm a) -> a.matches(operation, directReceiver);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003096 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
3097 Batch b = mAlarmBatches.get(i);
Suprabh Shukla0e49b642019-03-04 14:14:32 -08003098 didRemove |= b.remove(whichAlarms, false);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003099 if (b.size() == 0) {
3100 mAlarmBatches.remove(i);
3101 }
3102 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003103 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003104 final Alarm alarm = mPendingWhileIdleAlarms.get(i);
3105 if (alarm.matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003106 // Don't set didRemove, since this doesn't impact the scheduled alarms.
3107 mPendingWhileIdleAlarms.remove(i);
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003108 decrementAlarmCount(alarm.uid, 1);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003109 }
3110 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003111 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
3112 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
3113 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003114 final Alarm alarm = alarmsForUid.get(j);
3115 if (alarm.matches(operation, directReceiver)) {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003116 // Don't set didRemove, since this doesn't impact the scheduled alarms.
3117 alarmsForUid.remove(j);
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003118 decrementAlarmCount(alarm.uid, 1);
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003119 }
3120 }
3121 if (alarmsForUid.size() == 0) {
3122 mPendingBackgroundAlarms.removeAt(i);
3123 }
3124 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08003125 if (didRemove) {
3126 if (DEBUG_BATCH) {
3127 Slog.v(TAG, "remove(operation) changed bounds; rebatching");
3128 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003129 boolean restorePending = false;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003130 if (mPendingIdleUntil != null && mPendingIdleUntil.matches(operation, directReceiver)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003131 mPendingIdleUntil = null;
3132 restorePending = true;
3133 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003134 if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) {
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003135 mNextWakeFromIdle = null;
3136 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08003137 rebatchAllAlarmsLocked(true);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003138 if (restorePending) {
3139 restorePendingWhileIdleAlarmsLocked();
3140 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02003141 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08003142 }
3143 }
3144
Christopher Tate1d99c392017-12-07 16:54:04 -08003145 void removeLocked(final int uid) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08003146 if (uid == Process.SYSTEM_UID) {
Christopher Tatee1ce1742019-04-16 13:37:13 -07003147 // If a force-stop occurs for a system-uid package, ignore it.
Makoto Onuki5d93b832018-01-10 16:12:39 -08003148 return;
3149 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08003150 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08003151 final Predicate<Alarm> whichAlarms = (Alarm a) -> a.uid == uid;
Adam Lesinski182f73f2013-12-05 16:48:06 -08003152 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
3153 Batch b = mAlarmBatches.get(i);
Suprabh Shukla0e49b642019-03-04 14:14:32 -08003154 didRemove |= b.remove(whichAlarms, false);
Christopher Tate1d99c392017-12-07 16:54:04 -08003155 if (b.size() == 0) {
3156 mAlarmBatches.remove(i);
3157 }
3158 }
3159 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
3160 final Alarm a = mPendingWhileIdleAlarms.get(i);
3161 if (a.uid == uid) {
3162 // Don't set didRemove, since this doesn't impact the scheduled alarms.
3163 mPendingWhileIdleAlarms.remove(i);
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003164 decrementAlarmCount(uid, 1);
Christopher Tate1d99c392017-12-07 16:54:04 -08003165 }
3166 }
3167 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i --) {
3168 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
3169 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
3170 if (alarmsForUid.get(j).uid == uid) {
3171 alarmsForUid.remove(j);
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003172 decrementAlarmCount(uid, 1);
Christopher Tate1d99c392017-12-07 16:54:04 -08003173 }
3174 }
3175 if (alarmsForUid.size() == 0) {
3176 mPendingBackgroundAlarms.removeAt(i);
3177 }
3178 }
Christopher Tate490227c2018-11-02 14:05:47 -07003179 // If we're currently keying off of this app's alarms for doze transitions,
3180 // make sure to reset to other triggers.
3181 if (mNextWakeFromIdle != null && mNextWakeFromIdle.uid == uid) {
3182 mNextWakeFromIdle = null;
3183 }
3184 if (mPendingIdleUntil != null && mPendingIdleUntil.uid == uid) {
3185 // Should never happen - only the system uid is allowed to set idle-until alarms
3186 Slog.wtf(TAG, "Removed app uid " + uid + " set idle-until alarm!");
3187 mPendingIdleUntil = null;
3188 }
Christopher Tate1d99c392017-12-07 16:54:04 -08003189 if (didRemove) {
3190 if (DEBUG_BATCH) {
3191 Slog.v(TAG, "remove(uid) changed bounds; rebatching");
3192 }
3193 rebatchAllAlarmsLocked(true);
3194 rescheduleKernelAlarmsLocked();
3195 updateNextAlarmClockLocked();
3196 }
3197 }
3198
3199 void removeLocked(final String packageName) {
3200 if (packageName == null) {
3201 if (localLOGV) {
3202 Slog.w(TAG, "requested remove() of null packageName",
3203 new RuntimeException("here"));
3204 }
3205 return;
3206 }
3207
3208 boolean didRemove = false;
Christopher Tate490227c2018-11-02 14:05:47 -07003209 final MutableBoolean removedNextWakeFromIdle = new MutableBoolean(false);
3210 final Predicate<Alarm> whichAlarms = (Alarm a) -> {
3211 final boolean didMatch = a.matches(packageName);
3212 if (didMatch && a == mNextWakeFromIdle) {
3213 removedNextWakeFromIdle.value = true;
3214 }
3215 return didMatch;
3216 };
Makoto Onuki5d93b832018-01-10 16:12:39 -08003217 final boolean oldHasTick = haveBatchesTimeTickAlarm(mAlarmBatches);
Christopher Tate1d99c392017-12-07 16:54:04 -08003218 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
3219 Batch b = mAlarmBatches.get(i);
Suprabh Shukla0e49b642019-03-04 14:14:32 -08003220 didRemove |= b.remove(whichAlarms, false);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003221 if (b.size() == 0) {
3222 mAlarmBatches.remove(i);
3223 }
3224 }
Makoto Onuki5d93b832018-01-10 16:12:39 -08003225 final boolean newHasTick = haveBatchesTimeTickAlarm(mAlarmBatches);
3226 if (oldHasTick != newHasTick) {
3227 Slog.wtf(TAG, "removeLocked: hasTick changed from " + oldHasTick + " to " + newHasTick);
3228 }
3229
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003230 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003231 final Alarm a = mPendingWhileIdleAlarms.get(i);
3232 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003233 // Don't set didRemove, since this doesn't impact the scheduled alarms.
3234 mPendingWhileIdleAlarms.remove(i);
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003235 decrementAlarmCount(a.uid, 1);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003236 }
3237 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003238 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i --) {
3239 final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
3240 for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003241 final Alarm alarm = alarmsForUid.get(j);
3242 if (alarm.matches(packageName)) {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003243 alarmsForUid.remove(j);
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003244 decrementAlarmCount(alarm.uid, 1);
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003245 }
3246 }
3247 if (alarmsForUid.size() == 0) {
3248 mPendingBackgroundAlarms.removeAt(i);
3249 }
3250 }
Christopher Tate490227c2018-11-02 14:05:47 -07003251 // If we're currently keying off of this app's alarms for doze transitions,
3252 // make sure to reset to other triggers.
3253 if (removedNextWakeFromIdle.value) {
3254 mNextWakeFromIdle = null;
3255 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08003256 if (didRemove) {
3257 if (DEBUG_BATCH) {
3258 Slog.v(TAG, "remove(package) changed bounds; rebatching");
3259 }
3260 rebatchAllAlarmsLocked(true);
3261 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02003262 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08003263 }
3264 }
3265
Suprabh Shukla0e49b642019-03-04 14:14:32 -08003266 // Only called for ephemeral apps
Christopher Tate1d99c392017-12-07 16:54:04 -08003267 void removeForStoppedLocked(final int uid) {
Makoto Onuki5d93b832018-01-10 16:12:39 -08003268 if (uid == Process.SYSTEM_UID) {
Christopher Tatee1ce1742019-04-16 13:37:13 -07003269 // If a force-stop occurs for a system-uid package, ignore it.
Makoto Onuki5d93b832018-01-10 16:12:39 -08003270 return;
3271 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003272 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08003273 final Predicate<Alarm> whichAlarms = (Alarm a) -> {
3274 try {
3275 if (a.uid == uid && ActivityManager.getService().isAppStartModeDisabled(
3276 uid, a.packageName)) {
3277 return true;
3278 }
3279 } catch (RemoteException e) { /* fall through */}
3280 return false;
3281 };
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003282 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
3283 Batch b = mAlarmBatches.get(i);
Suprabh Shukla0e49b642019-03-04 14:14:32 -08003284 didRemove |= b.remove(whichAlarms, false);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003285 if (b.size() == 0) {
3286 mAlarmBatches.remove(i);
3287 }
3288 }
3289 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
3290 final Alarm a = mPendingWhileIdleAlarms.get(i);
Dianne Hackborne07641d2016-11-09 15:07:23 -08003291 if (a.uid == uid) {
3292 // Don't set didRemove, since this doesn't impact the scheduled alarms.
3293 mPendingWhileIdleAlarms.remove(i);
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003294 decrementAlarmCount(uid, 1);
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003295 }
3296 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003297 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
3298 if (mPendingBackgroundAlarms.keyAt(i) == uid) {
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003299 final ArrayList<Alarm> toRemove = mPendingBackgroundAlarms.valueAt(i);
3300 if (toRemove != null) {
3301 decrementAlarmCount(uid, toRemove.size());
3302 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003303 mPendingBackgroundAlarms.removeAt(i);
3304 }
3305 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07003306 if (didRemove) {
3307 if (DEBUG_BATCH) {
3308 Slog.v(TAG, "remove(package) changed bounds; rebatching");
3309 }
3310 rebatchAllAlarmsLocked(true);
3311 rescheduleKernelAlarmsLocked();
3312 updateNextAlarmClockLocked();
3313 }
3314 }
3315
Adam Lesinski182f73f2013-12-05 16:48:06 -08003316 void removeUserLocked(int userHandle) {
Winson Chungf2b41772019-11-06 15:00:48 -08003317 if (userHandle == USER_SYSTEM) {
Christopher Tatee1ce1742019-04-16 13:37:13 -07003318 // If we're told we're removing the system user, ignore it.
Makoto Onuki5d93b832018-01-10 16:12:39 -08003319 return;
3320 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08003321 boolean didRemove = false;
Christopher Tate1d99c392017-12-07 16:54:04 -08003322 final Predicate<Alarm> whichAlarms =
3323 (Alarm a) -> UserHandle.getUserId(a.creatorUid) == userHandle;
Adam Lesinski182f73f2013-12-05 16:48:06 -08003324 for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
3325 Batch b = mAlarmBatches.get(i);
Suprabh Shukla0e49b642019-03-04 14:14:32 -08003326 didRemove |= b.remove(whichAlarms, false);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003327 if (b.size() == 0) {
3328 mAlarmBatches.remove(i);
3329 }
3330 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003331 for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003332 if (UserHandle.getUserId(mPendingWhileIdleAlarms.get(i).creatorUid)
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003333 == userHandle) {
3334 // Don't set didRemove, since this doesn't impact the scheduled alarms.
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003335 final Alarm removed = mPendingWhileIdleAlarms.remove(i);
3336 decrementAlarmCount(removed.uid, 1);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003337 }
3338 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003339 for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
3340 if (UserHandle.getUserId(mPendingBackgroundAlarms.keyAt(i)) == userHandle) {
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003341 final ArrayList<Alarm> toRemove = mPendingBackgroundAlarms.valueAt(i);
3342 if (toRemove != null) {
3343 for (int j = 0; j < toRemove.size(); j++) {
3344 decrementAlarmCount(toRemove.get(j).uid, 1);
3345 }
3346 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003347 mPendingBackgroundAlarms.removeAt(i);
3348 }
3349 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003350 for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
3351 if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
3352 mLastAllowWhileIdleDispatch.removeAt(i);
3353 }
3354 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08003355
3356 if (didRemove) {
3357 if (DEBUG_BATCH) {
3358 Slog.v(TAG, "remove(user) changed bounds; rebatching");
3359 }
3360 rebatchAllAlarmsLocked(true);
3361 rescheduleKernelAlarmsLocked();
Adrian Roosc42a1e12014-07-07 23:35:53 +02003362 updateNextAlarmClockLocked();
Adam Lesinski182f73f2013-12-05 16:48:06 -08003363 }
3364 }
3365
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003366 void interactiveStateChangedLocked(boolean interactive) {
3367 if (mInteractive != interactive) {
3368 mInteractive = interactive;
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003369 final long nowELAPSED = mInjector.getElapsedRealtime();
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003370 if (interactive) {
3371 if (mPendingNonWakeupAlarms.size() > 0) {
3372 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
3373 mTotalDelayTime += thisDelayTime;
3374 if (mMaxDelayTime < thisDelayTime) {
3375 mMaxDelayTime = thisDelayTime;
3376 }
3377 deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
3378 mPendingNonWakeupAlarms.clear();
3379 }
3380 if (mNonInteractiveStartTime > 0) {
3381 long dur = nowELAPSED - mNonInteractiveStartTime;
3382 if (dur > mNonInteractiveTime) {
3383 mNonInteractiveTime = dur;
3384 }
3385 }
Suprabh Shukla12bd0162018-11-12 18:00:18 -08003386 // And send a TIME_TICK right now, since it is important to get the UI updated.
3387 mHandler.post(() ->
3388 getContext().sendBroadcastAsUser(mTimeTickIntent, UserHandle.ALL));
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003389 } else {
3390 mNonInteractiveStartTime = nowELAPSED;
3391 }
3392 }
3393 }
3394
Adam Lesinski182f73f2013-12-05 16:48:06 -08003395 boolean lookForPackageLocked(String packageName) {
3396 for (int i = 0; i < mAlarmBatches.size(); i++) {
3397 Batch b = mAlarmBatches.get(i);
3398 if (b.hasPackage(packageName)) {
3399 return true;
3400 }
3401 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003402 for (int i = 0; i < mPendingWhileIdleAlarms.size(); i++) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003403 final Alarm a = mPendingWhileIdleAlarms.get(i);
3404 if (a.matches(packageName)) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003405 return true;
3406 }
3407 }
Adam Lesinski182f73f2013-12-05 16:48:06 -08003408 return false;
3409 }
3410
3411 private void setLocked(int type, long when) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003412 if (mInjector.isAlarmDriverPresent()) {
3413 mInjector.setAlarm(type, when);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003414 } else {
3415 Message msg = Message.obtain();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003416 msg.what = AlarmHandler.ALARM_EVENT;
Kweku Adams61e03292017-10-19 14:27:12 -07003417
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003418 mHandler.removeMessages(msg.what);
Adam Lesinski182f73f2013-12-05 16:48:06 -08003419 mHandler.sendMessageAtTime(msg, when);
3420 }
3421 }
3422
Dianne Hackborn043fcd92010-10-06 14:27:34 -07003423 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Kweku Adams61e03292017-10-19 14:27:12 -07003424 String prefix, String label, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003425 for (int i=list.size()-1; i>=0; i--) {
3426 Alarm a = list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003427 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
3428 pw.print(": "); pw.println(a);
Kweku Adams61e03292017-10-19 14:27:12 -07003429 a.dump(pw, prefix + " ", nowELAPSED, nowRTC, sdf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 }
3431 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003432
3433 private static final String labelForType(int type) {
3434 switch (type) {
3435 case RTC: return "RTC";
3436 case RTC_WAKEUP : return "RTC_WAKEUP";
3437 case ELAPSED_REALTIME : return "ELAPSED";
3438 case ELAPSED_REALTIME_WAKEUP: return "ELAPSED_WAKEUP";
Christopher Tatee0a22b32013-07-11 14:43:13 -07003439 }
3440 return "--unknown--";
3441 }
3442
3443 private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003444 String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07003445 for (int i=list.size()-1; i>=0; i--) {
3446 Alarm a = list.get(i);
3447 final String label = labelForType(a.type);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003448 pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
3449 pw.print(": "); pw.println(a);
Kweku Adams61e03292017-10-19 14:27:12 -07003450 a.dump(pw, prefix + " ", nowELAPSED, nowRTC, sdf);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003451 }
3452 }
3453
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003454 private boolean isBackgroundRestricted(Alarm alarm) {
Christopher Tateda3dc922018-05-09 13:49:41 -07003455 boolean exemptOnBatterySaver = (alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003456 if (alarm.alarmClock != null) {
Christopher Tateda3dc922018-05-09 13:49:41 -07003457 // Don't defer alarm clocks
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003458 return false;
3459 }
Christopher Tateda3dc922018-05-09 13:49:41 -07003460 if (alarm.operation != null) {
3461 if (alarm.operation.isActivity()) {
3462 // Don't defer starting actual UI
3463 return false;
3464 }
3465 if (alarm.operation.isForegroundService()) {
3466 // FG service alarms are nearly as important; consult AST policy
3467 exemptOnBatterySaver = true;
3468 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003469 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08003470 final String sourcePackage = alarm.sourcePackage;
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003471 final int sourceUid = alarm.creatorUid;
Makoto Onukie4918212018-02-06 11:30:15 -08003472 return (mAppStateTracker != null) &&
Christopher Tateda3dc922018-05-09 13:49:41 -07003473 mAppStateTracker.areAlarmsRestricted(sourceUid, sourcePackage,
3474 exemptOnBatterySaver);
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003475 }
3476
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003477 private static native long init();
3478 private static native void close(long nativeData);
3479 private static native int set(long nativeData, int type, long seconds, long nanoseconds);
3480 private static native int waitForAlarm(long nativeData);
3481 private static native int setKernelTime(long nativeData, long millis);
3482 private static native int setKernelTimezone(long nativeData, int minuteswest);
3483 private static native long getNextAlarm(long nativeData, int type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484
Makoto Onukiadb50d82018-01-29 16:20:30 -08003485 private long getWhileIdleMinIntervalLocked(int uid) {
3486 final boolean dozing = mPendingIdleUntil != null;
Makoto Onukie4918212018-02-06 11:30:15 -08003487 final boolean ebs = (mAppStateTracker != null)
3488 && mAppStateTracker.isForceAllAppsStandbyEnabled();
Makoto Onukiadb50d82018-01-29 16:20:30 -08003489 if (!dozing && !ebs) {
3490 return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
3491 }
3492 if (dozing) {
3493 return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
3494 }
3495 if (mUseAllowWhileIdleShortTime.get(uid)) {
3496 // if the last allow-while-idle went off while uid was fg, or the uid
3497 // recently came into fg, don't block the alarm for long.
3498 return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
3499 }
3500 return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
3501 }
3502
Suprabh Shukla0e49b642019-03-04 14:14:32 -08003503 boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003504 boolean hasWakeup = false;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003505 // batches are temporally sorted, so we need only pull from the
3506 // start of the list until we either empty it or hit a batch
3507 // that is not yet deliverable
Christopher Tate6578ad12013-09-24 17:12:46 -07003508 while (mAlarmBatches.size() > 0) {
3509 Batch batch = mAlarmBatches.get(0);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003510 if (batch.start > nowELAPSED) {
3511 // Everything else is scheduled for the future
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003512 break;
3513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514
Christopher Tatee0a22b32013-07-11 14:43:13 -07003515 // We will (re)schedule some alarms now; don't let that interfere
3516 // with delivery of this current batch
3517 mAlarmBatches.remove(0);
Dianne Hackborn390517b2013-05-30 15:03:32 -07003518
Christopher Tatee0a22b32013-07-11 14:43:13 -07003519 final int N = batch.size();
3520 for (int i = 0; i < N; i++) {
3521 Alarm alarm = batch.get(i);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003522
3523 if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
3524 // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
Christopher Tateddd1da142018-04-13 13:41:51 -07003525 // schedule such alarms. The first such alarm from an app is always delivered.
3526 final long lastTime = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, -1);
Makoto Onukiadb50d82018-01-29 16:20:30 -08003527 final long minTime = lastTime + getWhileIdleMinIntervalLocked(alarm.creatorUid);
Christopher Tateddd1da142018-04-13 13:41:51 -07003528 if (lastTime >= 0 && nowELAPSED < minTime) {
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003529 // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
3530 // alarm went off for this app. Reschedule the alarm to be in the
3531 // correct time period.
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003532 alarm.expectedWhenElapsed = alarm.whenElapsed = minTime;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003533 if (alarm.maxWhenElapsed < minTime) {
3534 alarm.maxWhenElapsed = minTime;
3535 }
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003536 alarm.expectedMaxWhenElapsed = alarm.maxWhenElapsed;
Dianne Hackbornae78bf82015-10-26 13:33:20 -07003537 if (RECORD_DEVICE_IDLE_ALARMS) {
3538 IdleDispatchEntry ent = new IdleDispatchEntry();
3539 ent.uid = alarm.uid;
3540 ent.pkg = alarm.operation.getCreatorPackage();
3541 ent.tag = alarm.operation.getTag("");
3542 ent.op = "RESCHEDULE";
3543 ent.elapsedRealtime = nowELAPSED;
3544 ent.argRealtime = lastTime;
3545 mAllowWhileIdleDispatches.add(ent);
3546 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003547 setImplLocked(alarm, true, false);
3548 continue;
3549 }
3550 }
Suprabh Shukladb6bf662017-08-30 15:41:53 -07003551 if (isBackgroundRestricted(alarm)) {
3552 // Alarms with FLAG_WAKE_FROM_IDLE or mPendingIdleUntil alarm are not deferred
3553 if (DEBUG_BG_LIMIT) {
3554 Slog.d(TAG, "Deferring alarm " + alarm + " due to user forced app standby");
3555 }
3556 ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(alarm.creatorUid);
3557 if (alarmsForUid == null) {
3558 alarmsForUid = new ArrayList<>();
3559 mPendingBackgroundAlarms.put(alarm.creatorUid, alarmsForUid);
3560 }
3561 alarmsForUid.add(alarm);
3562 continue;
3563 }
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003564
Christopher Tatee0a22b32013-07-11 14:43:13 -07003565 alarm.count = 1;
3566 triggerList.add(alarm);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003567 if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
3568 EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003569 alarm.statsTag);
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003570 }
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003571 if (mPendingIdleUntil == alarm) {
3572 mPendingIdleUntil = null;
3573 rebatchAllAlarmsLocked(false);
3574 restorePendingWhileIdleAlarmsLocked();
3575 }
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003576 if (mNextWakeFromIdle == alarm) {
3577 mNextWakeFromIdle = null;
3578 rebatchAllAlarmsLocked(false);
3579 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003580
3581 // Recurring alarms may have passed several alarm intervals while the
3582 // phone was asleep or off, so pass a trigger count when sending them.
3583 if (alarm.repeatInterval > 0) {
3584 // this adjustment will be zero if we're late by
3585 // less than one full repeat interval
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003586 alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003587 // Also schedule its next recurrence
3588 final long delta = alarm.count * alarm.repeatInterval;
Suprabh Shuklaabdd7362019-05-13 13:31:56 -07003589 final long nextElapsed = alarm.expectedWhenElapsed + delta;
Christopher Tate3e04b472013-10-21 17:51:31 -07003590 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
Christopher Tatee0a22b32013-07-11 14:43:13 -07003591 maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
Christopher Tate14a7bb02015-10-01 10:24:31 -07003592 alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
3593 alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
Christopher Tate864d42e2014-12-02 11:48:53 -08003594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003595
Christopher Tate864d42e2014-12-02 11:48:53 -08003596 if (alarm.wakeup) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003597 hasWakeup = true;
3598 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02003599
3600 // We removed an alarm clock. Let the caller recompute the next alarm clock.
3601 if (alarm.alarmClock != null) {
3602 mNextAlarmClockMayChange = true;
3603 }
Dianne Hackborn390517b2013-05-30 15:03:32 -07003604 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 }
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003606
Christopher Tate1590f1e2014-10-02 17:27:57 -07003607 // This is a new alarm delivery set; bump the sequence number to indicate that
3608 // all apps' alarm delivery classes should be recalculated.
3609 mCurrentSeq++;
3610 calculateDeliveryPriorities(triggerList);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003611 Collections.sort(triggerList, mAlarmDispatchComparator);
3612
3613 if (localLOGV) {
3614 for (int i=0; i<triggerList.size(); i++) {
3615 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
3616 }
3617 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003618
3619 return hasWakeup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622 /**
3623 * This Comparator sorts Alarms into increasing time order.
3624 */
3625 public static class IncreasingTimeOrder implements Comparator<Alarm> {
3626 public int compare(Alarm a1, Alarm a2) {
jinho.park1acd32a2015-05-27 14:44:18 +09003627 long when1 = a1.whenElapsed;
3628 long when2 = a2.whenElapsed;
Charles Tsaicdaaeee2015-05-20 18:16:48 +08003629 if (when1 > when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 return 1;
3631 }
Charles Tsaicdaaeee2015-05-20 18:16:48 +08003632 if (when1 < when2) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003633 return -1;
3634 }
3635 return 0;
3636 }
3637 }
Kweku Adams61e03292017-10-19 14:27:12 -07003638
Makoto Onuki2206af32017-11-21 16:25:35 -08003639 @VisibleForTesting
3640 static class Alarm {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003641 public final int type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003642 public final long origWhen;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003643 public final boolean wakeup;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003644 public final PendingIntent operation;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003645 public final IAlarmListener listener;
3646 public final String listenerTag;
3647 public final String statsTag;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003648 public final WorkSource workSource;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003649 public final int flags;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003650 public final AlarmManager.AlarmClockInfo alarmClock;
3651 public final int uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003652 public final int creatorUid;
3653 public final String packageName;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003654 public final String sourcePackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003655 public int count;
3656 public long when;
Christopher Tate3e04b472013-10-21 17:51:31 -07003657 public long windowLength;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003658 public long whenElapsed; // 'when' in the elapsed time base
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003659 public long maxWhenElapsed; // also in the elapsed time base
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003660 // Expected alarm expiry time before app standby deferring is applied.
3661 public long expectedWhenElapsed;
3662 public long expectedMaxWhenElapsed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 public long repeatInterval;
Christopher Tate1590f1e2014-10-02 17:27:57 -07003664 public PriorityClass priorityClass;
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003665
Christopher Tate3e04b472013-10-21 17:51:31 -07003666 public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
Christopher Tate14a7bb02015-10-01 10:24:31 -07003667 long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag,
3668 WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info,
3669 int _uid, String _pkgName) {
Christopher Tatee0a22b32013-07-11 14:43:13 -07003670 type = _type;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003671 origWhen = _when;
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003672 wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
3673 || _type == AlarmManager.RTC_WAKEUP;
Christopher Tatee0a22b32013-07-11 14:43:13 -07003674 when = _when;
3675 whenElapsed = _whenElapsed;
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003676 expectedWhenElapsed = _whenElapsed;
Christopher Tate3e04b472013-10-21 17:51:31 -07003677 windowLength = _windowLength;
Christopher Tate22e919d2018-02-16 16:16:50 -08003678 maxWhenElapsed = expectedMaxWhenElapsed = clampPositive(_maxWhen);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003679 repeatInterval = _interval;
3680 operation = _op;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003681 listener = _rec;
3682 listenerTag = _listenerTag;
3683 statsTag = makeTag(_op, _listenerTag, _type);
David Christieebe51fc2013-07-26 13:23:29 -07003684 workSource = _ws;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003685 flags = _flags;
Adrian Roosc42a1e12014-07-07 23:35:53 +02003686 alarmClock = _info;
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003687 uid = _uid;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003688 packageName = _pkgName;
Suprabh Shukla75edab12018-01-29 14:09:06 -08003689 sourcePackage = (operation != null) ? operation.getCreatorPackage() : packageName;
Christopher Tate14a7bb02015-10-01 10:24:31 -07003690 creatorUid = (operation != null) ? operation.getCreatorUid() : uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 }
Christopher Tatee0a22b32013-07-11 14:43:13 -07003692
Christopher Tate14a7bb02015-10-01 10:24:31 -07003693 public static String makeTag(PendingIntent pi, String tag, int type) {
3694 final String alarmString = type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
3695 ? "*walarm*:" : "*alarm*:";
3696 return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag);
3697 }
3698
3699 public WakeupEvent makeWakeupEvent(long nowRTC) {
3700 return new WakeupEvent(nowRTC, creatorUid,
3701 (operation != null)
3702 ? operation.getIntent().getAction()
3703 : ("<listener>:" + listenerTag));
3704 }
3705
3706 // Returns true if either matches
3707 public boolean matches(PendingIntent pi, IAlarmListener rec) {
3708 return (operation != null)
3709 ? operation.equals(pi)
Lorenzo Colitti9b43ce02015-11-22 22:00:08 +09003710 : rec != null && listener.asBinder().equals(rec.asBinder());
Christopher Tate14a7bb02015-10-01 10:24:31 -07003711 }
3712
3713 public boolean matches(String packageName) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08003714 return packageName.equals(sourcePackage);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003715 }
3716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003717 @Override
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003718 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003719 StringBuilder sb = new StringBuilder(128);
3720 sb.append("Alarm{");
3721 sb.append(Integer.toHexString(System.identityHashCode(this)));
3722 sb.append(" type ");
3723 sb.append(type);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08003724 sb.append(" when ");
3725 sb.append(when);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003726 sb.append(" ");
Suprabh Shukla75edab12018-01-29 14:09:06 -08003727 sb.append(sourcePackage);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003728 sb.append('}');
3729 return sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003730 }
3731
Kweku Adams61e03292017-10-19 14:27:12 -07003732 public void dump(PrintWriter pw, String prefix, long nowELAPSED, long nowRTC,
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003733 SimpleDateFormat sdf) {
3734 final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003735 pw.print(prefix); pw.print("tag="); pw.println(statsTag);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003736 pw.print(prefix); pw.print("type="); pw.print(type);
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003737 pw.print(" expectedWhenElapsed="); TimeUtils.formatDuration(
3738 expectedWhenElapsed, nowELAPSED, pw);
3739 pw.print(" expectedMaxWhenElapsed="); TimeUtils.formatDuration(
3740 expectedMaxWhenElapsed, nowELAPSED, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003741 pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
3742 nowELAPSED, pw);
Suprabh Shukla2fa95452018-02-12 12:53:23 -08003743 pw.print(" maxWhenElapsed="); TimeUtils.formatDuration(maxWhenElapsed,
3744 nowELAPSED, pw);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003745 pw.print(" when=");
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003746 if (isRtc) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003747 pw.print(sdf.format(new Date(when)));
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003748 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07003749 TimeUtils.formatDuration(when, nowELAPSED, pw);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003750 }
3751 pw.println();
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07003752 pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003753 pw.print(" repeatInterval="); pw.print(repeatInterval);
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003754 pw.print(" count="); pw.print(count);
3755 pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003756 if (alarmClock != null) {
3757 pw.print(prefix); pw.println("Alarm clock:");
3758 pw.print(prefix); pw.print(" triggerTime=");
3759 pw.println(sdf.format(new Date(alarmClock.getTriggerTime())));
3760 pw.print(prefix); pw.print(" showIntent="); pw.println(alarmClock.getShowIntent());
3761 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003762 pw.print(prefix); pw.print("operation="); pw.println(operation);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003763 if (listener != null) {
3764 pw.print(prefix); pw.print("listener="); pw.println(listener.asBinder());
3765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003766 }
Kweku Adams61e03292017-10-19 14:27:12 -07003767
Jeffrey Huangcb782852019-12-05 11:28:11 -08003768 public void dumpDebug(ProtoOutputStream proto, long fieldId, long nowElapsed,
Kweku Adams61e03292017-10-19 14:27:12 -07003769 long nowRTC) {
3770 final long token = proto.start(fieldId);
3771
3772 proto.write(AlarmProto.TAG, statsTag);
3773 proto.write(AlarmProto.TYPE, type);
Kweku Adams923ec432017-12-11 18:05:38 -08003774 proto.write(AlarmProto.TIME_UNTIL_WHEN_ELAPSED_MS, whenElapsed - nowElapsed);
Kweku Adams61e03292017-10-19 14:27:12 -07003775 proto.write(AlarmProto.WINDOW_LENGTH_MS, windowLength);
3776 proto.write(AlarmProto.REPEAT_INTERVAL_MS, repeatInterval);
3777 proto.write(AlarmProto.COUNT, count);
3778 proto.write(AlarmProto.FLAGS, flags);
3779 if (alarmClock != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08003780 alarmClock.dumpDebug(proto, AlarmProto.ALARM_CLOCK);
Kweku Adams61e03292017-10-19 14:27:12 -07003781 }
3782 if (operation != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08003783 operation.dumpDebug(proto, AlarmProto.OPERATION);
Kweku Adams61e03292017-10-19 14:27:12 -07003784 }
3785 if (listener != null) {
3786 proto.write(AlarmProto.LISTENER, listener.asBinder().toString());
3787 }
3788
3789 proto.end(token);
3790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003791 }
Christopher Tate18a75f12013-07-01 18:18:59 -07003792
Christopher Tatee0a22b32013-07-11 14:43:13 -07003793 void recordWakeupAlarms(ArrayList<Batch> batches, long nowELAPSED, long nowRTC) {
3794 final int numBatches = batches.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07003795 for (int nextBatch = 0; nextBatch < numBatches; nextBatch++) {
3796 Batch b = batches.get(nextBatch);
Christopher Tatee0a22b32013-07-11 14:43:13 -07003797 if (b.start > nowELAPSED) {
Christopher Tate18a75f12013-07-01 18:18:59 -07003798 break;
3799 }
3800
Christopher Tatee0a22b32013-07-11 14:43:13 -07003801 final int numAlarms = b.alarms.size();
Christopher Tatee982faf2013-07-19 14:51:44 -07003802 for (int nextAlarm = 0; nextAlarm < numAlarms; nextAlarm++) {
3803 Alarm a = b.alarms.get(nextAlarm);
Christopher Tate14a7bb02015-10-01 10:24:31 -07003804 mRecentWakeups.add(a.makeWakeupEvent(nowRTC));
Christopher Tatee0a22b32013-07-11 14:43:13 -07003805 }
Christopher Tate18a75f12013-07-01 18:18:59 -07003806 }
3807 }
3808
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003809 long currentNonWakeupFuzzLocked(long nowELAPSED) {
3810 long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
3811 if (timeSinceOn < 5*60*1000) {
3812 // If the screen has been off for 5 minutes, only delay by at most two minutes.
3813 return 2*60*1000;
3814 } else if (timeSinceOn < 30*60*1000) {
3815 // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
3816 return 15*60*1000;
3817 } else {
3818 // Otherwise, we will delay by at most an hour.
3819 return 60*60*1000;
3820 }
3821 }
3822
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003823 static int fuzzForDuration(long duration) {
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003824 if (duration < 15*60*1000) {
3825 // If the duration until the time is less than 15 minutes, the maximum fuzz
3826 // is the duration.
Dianne Hackbornf70faed2015-04-21 14:11:38 -07003827 return (int)duration;
Dianne Hackborn4870e9d2015-04-08 16:55:47 -07003828 } else if (duration < 90*60*1000) {
3829 // If duration is less than 1 1/2 hours, the maximum fuzz is 15 minutes,
3830 return 15*60*1000;
3831 } else {
3832 // Otherwise, we will fuzz by at most half an hour.
3833 return 30*60*1000;
3834 }
3835 }
3836
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003837 boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
3838 if (mInteractive) {
3839 return false;
3840 }
3841 if (mLastAlarmDeliveryTime <= 0) {
3842 return false;
3843 }
minho.choo649acab2014-12-12 16:13:55 +09003844 if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) {
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003845 // This is just a little paranoia, if somehow we have pending non-wakeup alarms
3846 // and the next delivery time is in the past, then just deliver them all. This
3847 // avoids bugs where we get stuck in a loop trying to poll for alarms.
3848 return false;
3849 }
3850 long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
3851 return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
3852 }
3853
3854 void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
3855 mLastAlarmDeliveryTime = nowELAPSED;
3856 for (int i=0; i<triggerList.size(); i++) {
3857 Alarm alarm = triggerList.get(i);
Dianne Hackborna750a632015-06-16 17:18:23 -07003858 final boolean allowWhileIdle = (alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0;
Tim Murray175c0f92017-11-28 15:01:04 -08003859 if (alarm.wakeup) {
3860 Trace.traceBegin(Trace.TRACE_TAG_POWER, "Dispatch wakeup alarm to " + alarm.packageName);
3861 } else {
3862 Trace.traceBegin(Trace.TRACE_TAG_POWER, "Dispatch non-wakeup alarm to " + alarm.packageName);
3863 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003864 try {
Christopher Tate2ff5a732014-09-18 13:47:57 -07003865 if (localLOGV) {
3866 Slog.v(TAG, "sending alarm " + alarm);
3867 }
Dianne Hackborn1e383822015-04-10 14:02:33 -07003868 if (RECORD_ALARMS_IN_HISTORY) {
Narayan Kamath695cf722017-12-21 18:32:47 +00003869 ActivityManager.noteAlarmStart(alarm.operation, alarm.workSource, alarm.uid,
3870 alarm.statsTag);
Dianne Hackborn1e383822015-04-10 14:02:33 -07003871 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07003872 mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003873 } catch (RuntimeException e) {
3874 Slog.w(TAG, "Failure sending alarm.", e);
3875 }
Tim Murray175c0f92017-11-28 15:01:04 -08003876 Trace.traceEnd(Trace.TRACE_TAG_POWER);
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07003877 decrementAlarmCount(alarm.uid, 1);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07003878 }
3879 }
3880
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08003881 private boolean isExemptFromAppStandby(Alarm a) {
3882 return a.alarmClock != null || UserHandle.isCore(a.creatorUid)
3883 || (a.flags & FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED) != 0;
3884 }
3885
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003886 @VisibleForTesting
3887 static class Injector {
3888 private long mNativeData;
3889 private Context mContext;
3890
3891 Injector(Context context) {
3892 mContext = context;
3893 }
3894
3895 void init() {
3896 mNativeData = AlarmManagerService.init();
3897 }
3898
3899 int waitForAlarm() {
3900 return AlarmManagerService.waitForAlarm(mNativeData);
3901 }
3902
3903 boolean isAlarmDriverPresent() {
3904 return mNativeData != 0;
3905 }
3906
3907 void setAlarm(int type, long millis) {
3908 // The kernel never triggers alarms with negative wakeup times
3909 // so we ensure they are positive.
3910 final long alarmSeconds, alarmNanoseconds;
3911 if (millis < 0) {
3912 alarmSeconds = 0;
3913 alarmNanoseconds = 0;
3914 } else {
3915 alarmSeconds = millis / 1000;
3916 alarmNanoseconds = (millis % 1000) * 1000 * 1000;
3917 }
3918
3919 final int result = AlarmManagerService.set(mNativeData, type, alarmSeconds,
3920 alarmNanoseconds);
3921 if (result != 0) {
3922 final long nowElapsed = SystemClock.elapsedRealtime();
3923 Slog.wtf(TAG, "Unable to set kernel alarm, now=" + nowElapsed
3924 + " type=" + type + " @ (" + alarmSeconds + "," + alarmNanoseconds
3925 + "), ret = " + result + " = " + Os.strerror(result));
3926 }
3927 }
3928
3929 long getNextAlarm(int type) {
3930 return AlarmManagerService.getNextAlarm(mNativeData, type);
3931 }
3932
3933 void setKernelTimezone(int minutesWest) {
3934 AlarmManagerService.setKernelTimezone(mNativeData, minutesWest);
3935 }
3936
3937 void setKernelTime(long millis) {
3938 if (mNativeData != 0) {
3939 AlarmManagerService.setKernelTime(mNativeData, millis);
3940 }
3941 }
3942
3943 void close() {
3944 AlarmManagerService.close(mNativeData);
3945 }
3946
3947 long getElapsedRealtime() {
3948 return SystemClock.elapsedRealtime();
3949 }
3950
3951 long getCurrentTimeMillis() {
3952 return System.currentTimeMillis();
3953 }
3954
3955 PowerManager.WakeLock getAlarmWakeLock() {
3956 final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
3957 return pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
3958 }
3959
3960 int getSystemUiUid() {
Winson Chungf2b41772019-11-06 15:00:48 -08003961 PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
3962 return pm.getPackageUid(pm.getSystemUiServiceComponent().getPackageName(),
3963 MATCH_SYSTEM_ONLY, USER_SYSTEM);
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003964 }
3965
3966 ClockReceiver getClockReceiver(AlarmManagerService service) {
3967 return service.new ClockReceiver();
3968 }
3969 }
3970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003971 private class AlarmThread extends Thread
3972 {
Suprabh Shukla1d6a4032018-07-09 16:59:27 -07003973 private int mFalseWakeups;
3974 private int mWtfThreshold;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003975 public AlarmThread()
3976 {
3977 super("AlarmManager");
Suprabh Shukla1d6a4032018-07-09 16:59:27 -07003978 mFalseWakeups = 0;
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003979 mWtfThreshold = 100;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003980 }
Kweku Adams61e03292017-10-19 14:27:12 -07003981
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003982 public void run()
3983 {
Dianne Hackborn390517b2013-05-30 15:03:32 -07003984 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
3985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003986 while (true)
3987 {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003988 int result = mInjector.waitForAlarm();
3989 final long nowRTC = mInjector.getCurrentTimeMillis();
3990 final long nowELAPSED = mInjector.getElapsedRealtime();
Christopher Tate8b98ade2018-02-09 11:13:19 -08003991 synchronized (mLock) {
3992 mLastWakeup = nowELAPSED;
3993 }
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07003994 if (result == 0) {
3995 Slog.wtf(TAG, "waitForAlarm returned 0, nowRTC = " + nowRTC
3996 + ", nowElapsed = " + nowELAPSED);
3997 }
Christopher Tate8b98ade2018-02-09 11:13:19 -08003998 triggerList.clear();
Dianne Hackbornc3527222015-05-13 14:03:20 -07003999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 if ((result & TIME_CHANGED_MASK) != 0) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07004001 // The kernel can give us spurious time change notifications due to
4002 // small adjustments it makes internally; we want to filter those out.
4003 final long lastTimeChangeClockTime;
4004 final long expectedClockTime;
Dianne Hackborn998e6082014-09-11 19:13:23 -07004005 synchronized (mLock) {
Dianne Hackbornc3527222015-05-13 14:03:20 -07004006 lastTimeChangeClockTime = mLastTimeChangeClockTime;
4007 expectedClockTime = lastTimeChangeClockTime
4008 + (nowELAPSED - mLastTimeChangeRealtime);
Dianne Hackborn998e6082014-09-11 19:13:23 -07004009 }
Christopher Tate2b6e459e2017-02-17 14:33:52 -08004010 if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime-1000)
4011 || nowRTC > (expectedClockTime+1000)) {
4012 // The change is by at least +/- 1000 ms (or this is the first change),
Dianne Hackbornc3527222015-05-13 14:03:20 -07004013 // let's do it!
4014 if (DEBUG_BATCH) {
4015 Slog.v(TAG, "Time changed notification from kernel; rebatching");
4016 }
Bookatz7948c872018-09-04 12:58:33 -07004017 // StatsLog requires currentTimeMillis(), which == nowRTC to within usecs.
Muhammad Qureshie2b24322020-01-28 10:54:17 -08004018 FrameworkStatsLog.write(FrameworkStatsLog.WALL_CLOCK_TIME_SHIFTED, nowRTC);
Christopher Tatec8b7f432018-09-28 16:23:10 -07004019 removeImpl(null, mTimeTickTrigger);
4020 removeImpl(mDateChangeSender, null);
Dianne Hackbornc3527222015-05-13 14:03:20 -07004021 rebatchAllAlarms();
4022 mClockReceiver.scheduleTimeTickEvent();
Christopher Tatecf024712016-08-05 13:21:45 -07004023 mClockReceiver.scheduleDateChangedEvent();
Dianne Hackbornc3527222015-05-13 14:03:20 -07004024 synchronized (mLock) {
4025 mNumTimeChanged++;
4026 mLastTimeChangeClockTime = nowRTC;
4027 mLastTimeChangeRealtime = nowELAPSED;
4028 }
4029 Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
4030 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
Christopher Tate2b6e459e2017-02-17 14:33:52 -08004031 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
Chad Brubaker291df4f2017-03-14 10:23:02 -07004032 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
4033 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
Dianne Hackbornc3527222015-05-13 14:03:20 -07004034 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
4035
4036 // The world has changed on us, so we need to re-evaluate alarms
4037 // regardless of whether the kernel has told us one went off.
4038 result |= IS_WAKEUP_MASK;
4039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004041
Dianne Hackbornc3527222015-05-13 14:03:20 -07004042 if (result != TIME_CHANGED_MASK) {
4043 // If this was anything besides just a time change, then figure what if
4044 // anything to do about alarms.
4045 synchronized (mLock) {
4046 if (localLOGV) Slog.v(
4047 TAG, "Checking for alarms... rtc=" + nowRTC
4048 + ", elapsed=" + nowELAPSED);
Christopher Tate18a75f12013-07-01 18:18:59 -07004049
Dianne Hackbornc3527222015-05-13 14:03:20 -07004050 if (WAKEUP_STATS) {
4051 if ((result & IS_WAKEUP_MASK) != 0) {
4052 long newEarliest = nowRTC - RECENT_WAKEUP_PERIOD;
4053 int n = 0;
4054 for (WakeupEvent event : mRecentWakeups) {
4055 if (event.when > newEarliest) break;
4056 n++; // number of now-stale entries at the list head
4057 }
4058 for (int i = 0; i < n; i++) {
4059 mRecentWakeups.remove();
4060 }
Christopher Tate18a75f12013-07-01 18:18:59 -07004061
Dianne Hackbornc3527222015-05-13 14:03:20 -07004062 recordWakeupAlarms(mAlarmBatches, nowELAPSED, nowRTC);
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07004063 }
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07004064 }
Dianne Hackbornc3527222015-05-13 14:03:20 -07004065
Christopher Tate8b98ade2018-02-09 11:13:19 -08004066 mLastTrigger = nowELAPSED;
Suprabh Shukla0e49b642019-03-04 14:14:32 -08004067 boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED);
Dianne Hackbornc3527222015-05-13 14:03:20 -07004068 if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
4069 // if there are no wakeup alarms and the screen is off, we can
4070 // delay what we have so far until the future.
4071 if (mPendingNonWakeupAlarms.size() == 0) {
4072 mStartCurrentDelayTime = nowELAPSED;
4073 mNextNonWakeupDeliveryTime = nowELAPSED
4074 + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
4075 }
4076 mPendingNonWakeupAlarms.addAll(triggerList);
4077 mNumDelayedAlarms += triggerList.size();
4078 rescheduleKernelAlarmsLocked();
4079 updateNextAlarmClockLocked();
4080 } else {
4081 // now deliver the alarm intents; if there are pending non-wakeup
4082 // alarms, we need to merge them in to the list. note we don't
4083 // just deliver them first because we generally want non-wakeup
4084 // alarms delivered after wakeup alarms.
Dianne Hackbornc3527222015-05-13 14:03:20 -07004085 if (mPendingNonWakeupAlarms.size() > 0) {
4086 calculateDeliveryPriorities(mPendingNonWakeupAlarms);
4087 triggerList.addAll(mPendingNonWakeupAlarms);
4088 Collections.sort(triggerList, mAlarmDispatchComparator);
4089 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
4090 mTotalDelayTime += thisDelayTime;
4091 if (mMaxDelayTime < thisDelayTime) {
4092 mMaxDelayTime = thisDelayTime;
4093 }
4094 mPendingNonWakeupAlarms.clear();
4095 }
Suprabh Shukla1d6a4032018-07-09 16:59:27 -07004096 if (mLastTimeChangeRealtime != nowELAPSED && triggerList.isEmpty()) {
4097 if (++mFalseWakeups >= mWtfThreshold) {
4098 Slog.wtf(TAG, "Too many (" + mFalseWakeups
4099 + ") false wakeups, nowElapsed=" + nowELAPSED);
4100 if (mWtfThreshold < 100_000) {
4101 mWtfThreshold *= 10;
4102 } else {
4103 mFalseWakeups = 0;
4104 }
4105 }
4106 }
Suprabh Shukla92994ab2018-01-31 17:39:30 -08004107 final ArraySet<Pair<String, Integer>> triggerPackages =
4108 new ArraySet<>();
4109 for (int i = 0; i < triggerList.size(); i++) {
4110 final Alarm a = triggerList.get(i);
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08004111 if (!isExemptFromAppStandby(a)) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08004112 triggerPackages.add(Pair.create(
4113 a.sourcePackage, UserHandle.getUserId(a.creatorUid)));
Suprabh Shukla75edab12018-01-29 14:09:06 -08004114 }
4115 }
Dianne Hackbornc3527222015-05-13 14:03:20 -07004116 deliverAlarmsLocked(triggerList, nowELAPSED);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08004117 reorderAlarmsBasedOnStandbyBuckets(triggerPackages);
4118 rescheduleKernelAlarmsLocked();
4119 updateNextAlarmClockLocked();
Dianne Hackbornc3527222015-05-13 14:03:20 -07004120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 }
Dianne Hackbornaa9a59d2016-05-23 15:59:18 -07004122
4123 } else {
4124 // Just in case -- even though no wakeup flag was set, make sure
4125 // we have updated the kernel to the next alarm time.
Christopher Tate7b5b7cb2016-07-07 14:41:36 -07004126 synchronized (mLock) {
4127 rescheduleKernelAlarmsLocked();
4128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004129 }
4130 }
4131 }
4132 }
Christopher Tatec4a07d12012-04-06 14:19:13 -07004133
David Christieebe51fc2013-07-26 13:23:29 -07004134 /**
4135 * Attribute blame for a WakeLock.
David Christieebe51fc2013-07-26 13:23:29 -07004136 * @param ws WorkSource to attribute blame.
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004137 * @param knownUid attribution uid; < 0 values are ignored.
David Christieebe51fc2013-07-26 13:23:29 -07004138 */
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004139 void setWakelockWorkSource(WorkSource ws, int knownUid, String tag, boolean first) {
Christopher Tatec4a07d12012-04-06 14:19:13 -07004140 try {
Christopher Tatec8b7f432018-09-28 16:23:10 -07004141 mWakeLock.setHistoryTag(first ? tag : null);
4142
David Christieebe51fc2013-07-26 13:23:29 -07004143 if (ws != null) {
4144 mWakeLock.setWorkSource(ws);
4145 return;
4146 }
4147
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004148 if (knownUid >= 0) {
4149 mWakeLock.setWorkSource(new WorkSource(knownUid));
Christopher Tatec4a07d12012-04-06 14:19:13 -07004150 return;
4151 }
4152 } catch (Exception e) {
4153 }
4154
4155 // Something went wrong; fall back to attributing the lock to the OS
4156 mWakeLock.setWorkSource(null);
4157 }
4158
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004159 private static int getAlarmAttributionUid(Alarm alarm) {
4160 if (alarm.workSource != null && !alarm.workSource.isEmpty()) {
4161 return alarm.workSource.getAttributionUid();
4162 }
4163
4164 return alarm.creatorUid;
4165 }
4166
Suprabh Shukla12bd0162018-11-12 18:00:18 -08004167 @VisibleForTesting
4168 class AlarmHandler extends Handler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 public static final int ALARM_EVENT = 1;
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004170 public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2;
4171 public static final int LISTENER_TIMEOUT = 3;
4172 public static final int REPORT_ALARMS_ACTIVE = 4;
Suprabh Shukla75edab12018-01-29 14:09:06 -08004173 public static final int APP_STANDBY_BUCKET_CHANGED = 5;
Kweku Adamsdf33ae12019-10-08 11:51:41 -07004174 public static final int CHARGING_STATUS_CHANGED = 6;
Makoto Onuki4d298b52018-02-05 10:54:58 -08004175 public static final int REMOVE_FOR_STOPPED = 7;
Suprabh Shukla0d51a8b2019-10-30 18:56:44 -07004176 public static final int REMOVE_FOR_CANCELED = 8;
Kweku Adams61e03292017-10-19 14:27:12 -07004177
Suprabh Shukla12bd0162018-11-12 18:00:18 -08004178 AlarmHandler() {
4179 super(Looper.myLooper());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004180 }
Kweku Adams61e03292017-10-19 14:27:12 -07004181
Makoto Onuki4d298b52018-02-05 10:54:58 -08004182 public void postRemoveForStopped(int uid) {
4183 obtainMessage(REMOVE_FOR_STOPPED, uid, 0).sendToTarget();
4184 }
4185
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08004186 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004187 public void handleMessage(Message msg) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004188 switch (msg.what) {
4189 case ALARM_EVENT: {
Suprabh Shukla5b22e6b2019-03-25 18:24:59 -07004190 // This code is used when the kernel timer driver is not available, which
4191 // shouldn't happen. Here, we try our best to simulate it, which may be useful
4192 // when porting Android to a new device. Note that we can't wake up a device
4193 // this way, so WAKE_UP alarms will be delivered only when the device is awake.
Christopher Tate14a7bb02015-10-01 10:24:31 -07004194 ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
4195 synchronized (mLock) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07004196 final long nowELAPSED = mInjector.getElapsedRealtime();
Suprabh Shukla0e49b642019-03-04 14:14:32 -08004197 triggerAlarmsLocked(triggerList, nowELAPSED);
Christopher Tate14a7bb02015-10-01 10:24:31 -07004198 updateNextAlarmClockLocked();
4199 }
Adrian Roosc42a1e12014-07-07 23:35:53 +02004200
Christopher Tate14a7bb02015-10-01 10:24:31 -07004201 // now trigger the alarms without the lock held
4202 for (int i=0; i<triggerList.size(); i++) {
4203 Alarm alarm = triggerList.get(i);
4204 try {
4205 alarm.operation.send();
4206 } catch (PendingIntent.CanceledException e) {
4207 if (alarm.repeatInterval > 0) {
4208 // This IntentSender is no longer valid, but this
4209 // is a repeating alarm, so toss the hoser.
Christopher Tatec8b7f432018-09-28 16:23:10 -07004210 removeImpl(alarm.operation, null);
Christopher Tate14a7bb02015-10-01 10:24:31 -07004211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004212 }
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07004213 decrementAlarmCount(alarm.uid, 1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004214 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004215 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004216 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004217
4218 case SEND_NEXT_ALARM_CLOCK_CHANGED:
4219 sendNextAlarmClockChanged();
4220 break;
4221
4222 case LISTENER_TIMEOUT:
4223 mDeliveryTracker.alarmTimedOut((IBinder) msg.obj);
4224 break;
4225
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004226 case REPORT_ALARMS_ACTIVE:
4227 if (mLocalDeviceIdleController != null) {
4228 mLocalDeviceIdleController.setAlarmsActive(msg.arg1 != 0);
4229 }
4230 break;
4231
Kweku Adamsdf33ae12019-10-08 11:51:41 -07004232 case CHARGING_STATUS_CHANGED:
Suprabh Shukla75edab12018-01-29 14:09:06 -08004233 synchronized (mLock) {
4234 mAppStandbyParole = (Boolean) msg.obj;
Suprabh Shukla92994ab2018-01-31 17:39:30 -08004235 if (reorderAlarmsBasedOnStandbyBuckets(null)) {
4236 rescheduleKernelAlarmsLocked();
4237 updateNextAlarmClockLocked();
4238 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08004239 }
4240 break;
4241
4242 case APP_STANDBY_BUCKET_CHANGED:
4243 synchronized (mLock) {
Suprabh Shukla92994ab2018-01-31 17:39:30 -08004244 final ArraySet<Pair<String, Integer>> filterPackages = new ArraySet<>();
4245 filterPackages.add(Pair.create((String) msg.obj, msg.arg1));
4246 if (reorderAlarmsBasedOnStandbyBuckets(filterPackages)) {
4247 rescheduleKernelAlarmsLocked();
4248 updateNextAlarmClockLocked();
4249 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08004250 }
4251 break;
4252
Makoto Onuki4d298b52018-02-05 10:54:58 -08004253 case REMOVE_FOR_STOPPED:
4254 synchronized (mLock) {
4255 removeForStoppedLocked(msg.arg1);
4256 }
4257 break;
4258
Suprabh Shukla0d51a8b2019-10-30 18:56:44 -07004259 case REMOVE_FOR_CANCELED:
4260 final PendingIntent operation = (PendingIntent) msg.obj;
4261 synchronized (mLock) {
4262 removeLocked(operation, null);
Suprabh Shuklafaa198b2019-05-31 15:57:05 -07004263 }
4264 break;
4265
Christopher Tate14a7bb02015-10-01 10:24:31 -07004266 default:
4267 // nope, just ignore it
4268 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 }
4270 }
4271 }
Kweku Adams61e03292017-10-19 14:27:12 -07004272
Kweku Adamsdf33ae12019-10-08 11:51:41 -07004273 @VisibleForTesting
4274 class ChargingReceiver extends BroadcastReceiver {
4275 ChargingReceiver() {
4276 IntentFilter filter = new IntentFilter();
4277 filter.addAction(BatteryManager.ACTION_CHARGING);
4278 filter.addAction(BatteryManager.ACTION_DISCHARGING);
4279 getContext().registerReceiver(this, filter);
4280 }
4281
4282 @Override
4283 public void onReceive(Context context, Intent intent) {
4284 final String action = intent.getAction();
4285 final boolean charging;
4286 if (BatteryManager.ACTION_CHARGING.equals(action)) {
4287 if (DEBUG_STANDBY) {
4288 Slog.d(TAG, "Device is charging.");
4289 }
4290 charging = true;
4291 } else {
4292 if (DEBUG_STANDBY) {
4293 Slog.d(TAG, "Disconnected from power.");
4294 }
4295 charging = false;
4296 }
4297 mHandler.removeMessages(AlarmHandler.CHARGING_STATUS_CHANGED);
4298 mHandler.obtainMessage(AlarmHandler.CHARGING_STATUS_CHANGED, charging)
4299 .sendToTarget();
4300 }
4301 }
4302
4303 @VisibleForTesting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 class ClockReceiver extends BroadcastReceiver {
4305 public ClockReceiver() {
4306 IntentFilter filter = new IntentFilter();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 filter.addAction(Intent.ACTION_DATE_CHANGED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08004308 getContext().registerReceiver(this, filter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004309 }
Kweku Adams61e03292017-10-19 14:27:12 -07004310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 @Override
4312 public void onReceive(Context context, Intent intent) {
Christopher Tatec8b7f432018-09-28 16:23:10 -07004313 if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004314 // Since the kernel does not keep track of DST, we need to
4315 // reset the TZ information at the beginning of each day
4316 // based off of the current Zone gmt offset + userspace tracked
4317 // daylight savings information.
4318 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07004319 int gmtOffset = zone.getOffset(mInjector.getCurrentTimeMillis());
4320 mInjector.setKernelTimezone(-(gmtOffset / 60000));
Christopher Tate385e4982013-07-23 18:22:29 -07004321 scheduleDateChangedEvent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004322 }
4323 }
Kweku Adams61e03292017-10-19 14:27:12 -07004324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004325 public void scheduleTimeTickEvent() {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07004326 final long currentTime = mInjector.getCurrentTimeMillis();
Sungmin Choi563914a2013-01-10 17:28:40 +09004327 final long nextTime = 60000 * ((currentTime / 60000) + 1);
Paul Westbrook51608a52011-08-25 13:18:54 -07004328
4329 // Schedule this event for the amount of time that it would take to get to
4330 // the top of the next minute.
Sungmin Choi563914a2013-01-10 17:28:40 +09004331 final long tickEventDelay = nextTime - currentTime;
Paul Westbrook51608a52011-08-25 13:18:54 -07004332
David Christieebe51fc2013-07-26 13:23:29 -07004333 final WorkSource workSource = null; // Let system take blame for time tick events.
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07004334 setImpl(ELAPSED_REALTIME, mInjector.getElapsedRealtime() + tickEventDelay, 0,
Suprabh Shukla12bd0162018-11-12 18:00:18 -08004335 0, null, mTimeTickTrigger, "TIME_TICK", AlarmManager.FLAG_STANDALONE,
4336 workSource, null, Process.myUid(), "android");
Christopher Tate12cf0b62018-01-05 18:40:14 -08004337
4338 // Finally, remember when we set the tick alarm
4339 synchronized (mLock) {
4340 mLastTickSet = currentTime;
4341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004342 }
Christopher Tate385e4982013-07-23 18:22:29 -07004343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 public void scheduleDateChangedEvent() {
4345 Calendar calendar = Calendar.getInstance();
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07004346 calendar.setTimeInMillis(mInjector.getCurrentTimeMillis());
Christopher Tateafa8b982016-08-10 16:15:48 -07004347 calendar.set(Calendar.HOUR_OF_DAY, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 calendar.set(Calendar.MINUTE, 0);
4349 calendar.set(Calendar.SECOND, 0);
4350 calendar.set(Calendar.MILLISECOND, 0);
4351 calendar.add(Calendar.DAY_OF_MONTH, 1);
David Christieebe51fc2013-07-26 13:23:29 -07004352
4353 final WorkSource workSource = null; // Let system take blame for date change events.
Christopher Tate14a7bb02015-10-01 10:24:31 -07004354 setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
4355 AlarmManager.FLAG_STANDALONE, workSource, null,
4356 Process.myUid(), "android");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 }
4358 }
Kweku Adams61e03292017-10-19 14:27:12 -07004359
Dianne Hackbornd4e6d462014-05-16 16:32:37 -07004360 class InteractiveStateReceiver extends BroadcastReceiver {
4361 public InteractiveStateReceiver() {
4362 IntentFilter filter = new IntentFilter();
4363 filter.addAction(Intent.ACTION_SCREEN_OFF);
4364 filter.addAction(Intent.ACTION_SCREEN_ON);
4365 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
4366 getContext().registerReceiver(this, filter);
4367 }
4368
4369 @Override
4370 public void onReceive(Context context, Intent intent) {
4371 synchronized (mLock) {
4372 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
4373 }
4374 }
4375 }
4376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004377 class UninstallReceiver extends BroadcastReceiver {
4378 public UninstallReceiver() {
4379 IntentFilter filter = new IntentFilter();
4380 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
4381 filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004382 filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383 filter.addDataScheme("package");
Adam Lesinski182f73f2013-12-05 16:48:06 -08004384 getContext().registerReceiver(this, filter);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004385 // Register for events related to sdcard installation.
4386 IntentFilter sdFilter = new IntentFilter();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08004387 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07004388 sdFilter.addAction(Intent.ACTION_USER_STOPPED);
Dianne Hackborn3d1933c42015-06-10 16:25:57 -07004389 sdFilter.addAction(Intent.ACTION_UID_REMOVED);
Adam Lesinski182f73f2013-12-05 16:48:06 -08004390 getContext().registerReceiver(this, sdFilter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 }
Kweku Adams61e03292017-10-19 14:27:12 -07004392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004393 @Override
4394 public void onReceive(Context context, Intent intent) {
Christopher Tate1d99c392017-12-07 16:54:04 -08004395 final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 synchronized (mLock) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004397 String pkgList[] = null;
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08004398 switch (intent.getAction()) {
4399 case Intent.ACTION_QUERY_PACKAGE_RESTART:
4400 pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
4401 for (String packageName : pkgList) {
4402 if (lookForPackageLocked(packageName)) {
4403 setResultCode(Activity.RESULT_OK);
4404 return;
Suprabh Shukla75edab12018-01-29 14:09:06 -08004405 }
4406 }
Dianne Hackborn409578f2010-03-10 17:23:43 -08004407 return;
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08004408 case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
4409 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
4410 break;
4411 case Intent.ACTION_USER_STOPPED:
4412 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
4413 if (userHandle >= 0) {
4414 removeUserLocked(userHandle);
4415 mAppWakeupHistory.removeForUser(userHandle);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004416 }
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08004417 return;
4418 case Intent.ACTION_UID_REMOVED:
4419 if (uid >= 0) {
4420 mLastAllowWhileIdleDispatch.delete(uid);
4421 mUseAllowWhileIdleShortTime.delete(uid);
4422 }
4423 return;
4424 case Intent.ACTION_PACKAGE_REMOVED:
4425 if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
4426 // This package is being updated; don't kill its alarms.
4427 return;
4428 }
4429 // Intentional fall-through.
4430 case Intent.ACTION_PACKAGE_RESTARTED:
4431 final Uri data = intent.getData();
4432 if (data != null) {
4433 final String pkg = data.getSchemeSpecificPart();
4434 if (pkg != null) {
4435 pkgList = new String[]{pkg};
4436 }
4437 }
4438 break;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004439 }
4440 if (pkgList != null && (pkgList.length > 0)) {
4441 for (String pkg : pkgList) {
Christopher Tate1d99c392017-12-07 16:54:04 -08004442 if (uid >= 0) {
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08004443 // package-removed and package-restarted case
4444 mAppWakeupHistory.removeForPackage(pkg, UserHandle.getUserId(uid));
Christopher Tate1d99c392017-12-07 16:54:04 -08004445 removeLocked(uid);
4446 } else {
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08004447 // external-applications-unavailable case
Christopher Tate1d99c392017-12-07 16:54:04 -08004448 removeLocked(pkg);
4449 }
Christopher Tate1590f1e2014-10-02 17:27:57 -07004450 mPriorities.remove(pkg);
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08004451 for (int i=mBroadcastStats.size()-1; i>=0; i--) {
4452 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
4453 if (uidStats.remove(pkg) != null) {
4454 if (uidStats.size() <= 0) {
4455 mBroadcastStats.removeAt(i);
4456 }
4457 }
4458 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004460 }
4461 }
4462 }
4463 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004464
4465 final class UidObserver extends IUidObserver.Stub {
Hui Yu26969322019-08-21 14:56:35 -07004466 @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
4467 int capability) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004468 }
4469
Dianne Hackborn3e99f652017-07-05 16:33:56 -07004470 @Override public void onUidGone(int uid, boolean disabled) {
Makoto Onuki4d298b52018-02-05 10:54:58 -08004471 if (disabled) {
4472 mHandler.postRemoveForStopped(uid);
Dianne Hackborne07641d2016-11-09 15:07:23 -08004473 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004474 }
4475
Dianne Hackborn3e99f652017-07-05 16:33:56 -07004476 @Override public void onUidActive(int uid) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004477 }
4478
Dianne Hackborn3e99f652017-07-05 16:33:56 -07004479 @Override public void onUidIdle(int uid, boolean disabled) {
Makoto Onuki4d298b52018-02-05 10:54:58 -08004480 if (disabled) {
4481 mHandler.postRemoveForStopped(uid);
Dianne Hackbornde9c48b2015-11-20 14:49:59 -08004482 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004483 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -07004484
4485 @Override public void onUidCachedChanged(int uid, boolean cached) {
4486 }
Kweku Adamsdf33ae12019-10-08 11:51:41 -07004487 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -07004488
Suprabh Shukla75edab12018-01-29 14:09:06 -08004489 /**
4490 * Tracking of app assignments to standby buckets
4491 */
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08004492 private final class AppStandbyTracker extends
Christopher Tateb909c4d52019-10-21 12:50:37 -07004493 AppIdleStateChangeListener {
Suprabh Shukla75edab12018-01-29 14:09:06 -08004494 @Override
4495 public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
Amith Yamasani119be9a2018-02-18 22:23:00 -08004496 boolean idle, int bucket, int reason) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08004497 if (DEBUG_STANDBY) {
4498 Slog.d(TAG, "Package " + packageName + " for user " + userId + " now in bucket " +
4499 bucket);
4500 }
4501 mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
Suprabh Shukla92994ab2018-01-31 17:39:30 -08004502 mHandler.obtainMessage(AlarmHandler.APP_STANDBY_BUCKET_CHANGED, userId, -1, packageName)
4503 .sendToTarget();
Suprabh Shukla75edab12018-01-29 14:09:06 -08004504 }
Kweku Adamsdf33ae12019-10-08 11:51:41 -07004505 }
Suprabh Shukla75edab12018-01-29 14:09:06 -08004506
Makoto Onuki2206af32017-11-21 16:25:35 -08004507 private final Listener mForceAppStandbyListener = new Listener() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07004508 @Override
Makoto Onuki2206af32017-11-21 16:25:35 -08004509 public void unblockAllUnrestrictedAlarms() {
Suprabh Shukladb6bf662017-08-30 15:41:53 -07004510 synchronized (mLock) {
Makoto Onuki2206af32017-11-21 16:25:35 -08004511 sendAllUnrestrictedPendingBackgroundAlarmsLocked();
Suprabh Shukladb6bf662017-08-30 15:41:53 -07004512 }
4513 }
Makoto Onuki2206af32017-11-21 16:25:35 -08004514
4515 @Override
4516 public void unblockAlarmsForUid(int uid) {
4517 synchronized (mLock) {
4518 sendPendingBackgroundAlarmsLocked(uid, null);
4519 }
4520 }
4521
4522 @Override
4523 public void unblockAlarmsForUidPackage(int uid, String packageName) {
4524 synchronized (mLock) {
4525 sendPendingBackgroundAlarmsLocked(uid, packageName);
4526 }
4527 }
Makoto Onukiadb50d82018-01-29 16:20:30 -08004528
4529 @Override
4530 public void onUidForeground(int uid, boolean foreground) {
4531 synchronized (mLock) {
4532 if (foreground) {
4533 mUseAllowWhileIdleShortTime.put(uid, true);
4534
4535 // Note we don't have to drain the pending while-idle alarms here, because
4536 // this event should coincide with unblockAlarmsForUid().
4537 }
4538 }
4539 }
Makoto Onuki2206af32017-11-21 16:25:35 -08004540 };
Suprabh Shukladb6bf662017-08-30 15:41:53 -07004541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004542 private final BroadcastStats getStatsLocked(PendingIntent pi) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08004543 String pkg = pi.getCreatorPackage();
4544 int uid = pi.getCreatorUid();
Christopher Tate14a7bb02015-10-01 10:24:31 -07004545 return getStatsLocked(uid, pkg);
4546 }
4547
4548 private final BroadcastStats getStatsLocked(int uid, String pkgName) {
Dianne Hackborn3d658bf2014-02-05 13:38:56 -08004549 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
4550 if (uidStats == null) {
4551 uidStats = new ArrayMap<String, BroadcastStats>();
4552 mBroadcastStats.put(uid, uidStats);
4553 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004554 BroadcastStats bs = uidStats.get(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004555 if (bs == null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004556 bs = new BroadcastStats(uid, pkgName);
4557 uidStats.put(pkgName, bs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004558 }
4559 return bs;
4560 }
Dianne Hackborn81038902012-11-26 17:04:09 -08004561
Christopher Tate21e9f192017-08-08 13:49:11 -07004562 /**
4563 * Canonical count of (operation.send() - onSendFinished()) and
4564 * listener send/complete/timeout invocations.
4565 * Guarded by the usual lock.
4566 */
4567 @GuardedBy("mLock")
4568 private int mSendCount = 0;
4569 @GuardedBy("mLock")
Christopher Tateeabba732017-08-17 17:12:52 -07004570 private int mSendFinishCount = 0;
4571 @GuardedBy("mLock")
Christopher Tate21e9f192017-08-08 13:49:11 -07004572 private int mListenerCount = 0;
Christopher Tateeabba732017-08-17 17:12:52 -07004573 @GuardedBy("mLock")
4574 private int mListenerFinishCount = 0;
Christopher Tate21e9f192017-08-08 13:49:11 -07004575
Christopher Tate14a7bb02015-10-01 10:24:31 -07004576 class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished {
Christopher Tate21e9f192017-08-08 13:49:11 -07004577
Christopher Tate14a7bb02015-10-01 10:24:31 -07004578 private InFlight removeLocked(PendingIntent pi, Intent intent) {
4579 for (int i = 0; i < mInFlight.size(); i++) {
Christopher Tate2f558d22019-01-17 16:58:31 -08004580 final InFlight inflight = mInFlight.get(i);
4581 if (inflight.mPendingIntent == pi) {
4582 if (pi.isBroadcast()) {
4583 notifyBroadcastAlarmCompleteLocked(inflight.mUid);
4584 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004585 return mInFlight.remove(i);
4586 }
4587 }
4588 mLog.w("No in-flight alarm for " + pi + " " + intent);
4589 return null;
4590 }
4591
4592 private InFlight removeLocked(IBinder listener) {
4593 for (int i = 0; i < mInFlight.size(); i++) {
4594 if (mInFlight.get(i).mListener == listener) {
4595 return mInFlight.remove(i);
4596 }
4597 }
4598 mLog.w("No in-flight alarm for listener " + listener);
4599 return null;
4600 }
4601
4602 private void updateStatsLocked(InFlight inflight) {
Suprabh Shukla6226c2f2018-08-22 18:15:04 -07004603 final long nowELAPSED = mInjector.getElapsedRealtime();
Christopher Tate14a7bb02015-10-01 10:24:31 -07004604 BroadcastStats bs = inflight.mBroadcastStats;
4605 bs.nesting--;
4606 if (bs.nesting <= 0) {
4607 bs.nesting = 0;
4608 bs.aggregateTime += nowELAPSED - bs.startTime;
4609 }
4610 FilterStats fs = inflight.mFilterStats;
4611 fs.nesting--;
4612 if (fs.nesting <= 0) {
4613 fs.nesting = 0;
4614 fs.aggregateTime += nowELAPSED - fs.startTime;
4615 }
4616 if (RECORD_ALARMS_IN_HISTORY) {
Narayan Kamath695cf722017-12-21 18:32:47 +00004617 ActivityManager.noteAlarmFinish(inflight.mPendingIntent, inflight.mWorkSource,
4618 inflight.mUid, inflight.mTag);
Christopher Tate14a7bb02015-10-01 10:24:31 -07004619 }
4620 }
4621
4622 private void updateTrackingLocked(InFlight inflight) {
4623 if (inflight != null) {
4624 updateStatsLocked(inflight);
4625 }
4626 mBroadcastRefCount--;
Makoto Onuki3e7d8452017-03-02 15:33:17 -08004627 if (DEBUG_WAKELOCK) {
4628 Slog.d(TAG, "mBroadcastRefCount -> " + mBroadcastRefCount);
4629 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004630 if (mBroadcastRefCount == 0) {
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004631 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07004632 mWakeLock.release();
4633 if (mInFlight.size() > 0) {
4634 mLog.w("Finished all dispatches with " + mInFlight.size()
4635 + " remaining inflights");
4636 for (int i=0; i<mInFlight.size(); i++) {
4637 mLog.w(" Remaining #" + i + ": " + mInFlight.get(i));
4638 }
4639 mInFlight.clear();
4640 }
4641 } else {
4642 // the next of our alarms is now in flight. reattribute the wakelock.
4643 if (mInFlight.size() > 0) {
4644 InFlight inFlight = mInFlight.get(0);
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004645 setWakelockWorkSource(inFlight.mWorkSource, inFlight.mCreatorUid, inFlight.mTag,
4646 false);
Christopher Tate14a7bb02015-10-01 10:24:31 -07004647 } else {
4648 // should never happen
4649 mLog.w("Alarm wakelock still held but sent queue empty");
4650 mWakeLock.setWorkSource(null);
4651 }
4652 }
4653 }
4654
4655 /**
4656 * Callback that arrives when a direct-call alarm reports that delivery has finished
4657 */
4658 @Override
4659 public void alarmComplete(IBinder who) {
4660 if (who == null) {
Christopher Tate21e9f192017-08-08 13:49:11 -07004661 mLog.w("Invalid alarmComplete: uid=" + Binder.getCallingUid()
Christopher Tate14a7bb02015-10-01 10:24:31 -07004662 + " pid=" + Binder.getCallingPid());
4663 return;
4664 }
4665
4666 final long ident = Binder.clearCallingIdentity();
4667 try {
4668 synchronized (mLock) {
4669 mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who);
4670 InFlight inflight = removeLocked(who);
4671 if (inflight != null) {
4672 if (DEBUG_LISTENER_CALLBACK) {
4673 Slog.i(TAG, "alarmComplete() from " + who);
4674 }
4675 updateTrackingLocked(inflight);
Christopher Tateeabba732017-08-17 17:12:52 -07004676 mListenerFinishCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004677 } else {
4678 // Delivery timed out, and the timeout handling already took care of
4679 // updating our tracking here, so we needn't do anything further.
4680 if (DEBUG_LISTENER_CALLBACK) {
4681 Slog.i(TAG, "Late alarmComplete() from " + who);
4682 }
4683 }
4684 }
4685 } finally {
4686 Binder.restoreCallingIdentity(ident);
4687 }
4688 }
4689
4690 /**
4691 * Callback that arrives when a PendingIntent alarm has finished delivery
4692 */
4693 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
4695 String resultData, Bundle resultExtras) {
4696 synchronized (mLock) {
Christopher Tateeabba732017-08-17 17:12:52 -07004697 mSendFinishCount++;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004698 updateTrackingLocked(removeLocked(pi, intent));
4699 }
4700 }
4701
4702 /**
4703 * Timeout of a direct-call alarm delivery
4704 */
4705 public void alarmTimedOut(IBinder who) {
4706 synchronized (mLock) {
4707 InFlight inflight = removeLocked(who);
Dianne Hackborn81038902012-11-26 17:04:09 -08004708 if (inflight != null) {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004709 // TODO: implement ANR policy for the target
4710 if (DEBUG_LISTENER_CALLBACK) {
4711 Slog.i(TAG, "Alarm listener " + who + " timed out in delivery");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004713 updateTrackingLocked(inflight);
Christopher Tateeabba732017-08-17 17:12:52 -07004714 mListenerFinishCount++;
Dianne Hackborn81038902012-11-26 17:04:09 -08004715 } else {
Christopher Tate14a7bb02015-10-01 10:24:31 -07004716 if (DEBUG_LISTENER_CALLBACK) {
4717 Slog.i(TAG, "Spurious timeout of listener " + who);
4718 }
Christopher Tate21e9f192017-08-08 13:49:11 -07004719 mLog.w("Spurious timeout of listener " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004721 }
4722 }
4723
4724 /**
4725 * Deliver an alarm and set up the post-delivery handling appropriately
4726 */
Andreas Gampea36dc622018-02-05 17:19:22 -08004727 @GuardedBy("mLock")
Christopher Tate14a7bb02015-10-01 10:24:31 -07004728 public void deliverLocked(Alarm alarm, long nowELAPSED, boolean allowWhileIdle) {
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004729 final long workSourceToken = ThreadLocalWorkSource.setUid(
4730 getAlarmAttributionUid(alarm));
4731 try {
4732 if (alarm.operation != null) {
4733 // PendingIntent alarm
4734 mSendCount++;
Christopher Tate12cf0b62018-01-05 18:40:14 -08004735
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004736 try {
4737 alarm.operation.send(getContext(), 0,
4738 mBackgroundIntent.putExtra(
4739 Intent.EXTRA_ALARM_COUNT, alarm.count),
4740 mDeliveryTracker, mHandler, null,
4741 allowWhileIdle ? mIdleOptions : null);
4742 } catch (PendingIntent.CanceledException e) {
4743 if (alarm.repeatInterval > 0) {
4744 // This IntentSender is no longer valid, but this
4745 // is a repeating alarm, so toss it
4746 removeImpl(alarm.operation, null);
4747 }
4748 // No actual delivery was possible, so the delivery tracker's
4749 // 'finished' callback won't be invoked. We also don't need
4750 // to do any wakelock or stats tracking, so we have nothing
4751 // left to do here but go on to the next thing.
4752 mSendFinishCount++;
4753 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004754 }
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004755 } else {
4756 // Direct listener callback alarm
4757 mListenerCount++;
Christopher Tatec8b7f432018-09-28 16:23:10 -07004758
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004759 if (RECORD_ALARMS_IN_HISTORY) {
4760 if (alarm.listener == mTimeTickTrigger) {
4761 mTickHistory[mNextTickHistory++] = nowELAPSED;
4762 if (mNextTickHistory >= TICK_HISTORY_DEPTH) {
4763 mNextTickHistory = 0;
4764 }
Christopher Tatec8b7f432018-09-28 16:23:10 -07004765 }
4766 }
Christopher Tatec8b7f432018-09-28 16:23:10 -07004767
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004768 try {
4769 if (DEBUG_LISTENER_CALLBACK) {
4770 Slog.v(TAG, "Alarm to uid=" + alarm.uid
4771 + " listener=" + alarm.listener.asBinder());
4772 }
4773 alarm.listener.doAlarm(this);
4774 mHandler.sendMessageDelayed(
4775 mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
4776 alarm.listener.asBinder()),
4777 mConstants.LISTENER_TIMEOUT);
4778 } catch (Exception e) {
4779 if (DEBUG_LISTENER_CALLBACK) {
4780 Slog.i(TAG, "Alarm undeliverable to listener "
4781 + alarm.listener.asBinder(), e);
4782 }
4783 // As in the PendingIntent.CanceledException case, delivery of the
4784 // alarm was not possible, so we have no wakelock or timeout or
4785 // stats management to do. It threw before we posted the delayed
4786 // timeout message, so we're done here.
4787 mListenerFinishCount++;
4788 return;
Christopher Tate14a7bb02015-10-01 10:24:31 -07004789 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004790 }
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004791 } finally {
4792 ThreadLocalWorkSource.restore(workSourceToken);
Christopher Tate14a7bb02015-10-01 10:24:31 -07004793 }
4794
4795 // The alarm is now in flight; now arrange wakelock and stats tracking
Makoto Onuki3e7d8452017-03-02 15:33:17 -08004796 if (DEBUG_WAKELOCK) {
4797 Slog.d(TAG, "mBroadcastRefCount -> " + (mBroadcastRefCount + 1));
4798 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004799 if (mBroadcastRefCount == 0) {
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004800 setWakelockWorkSource(alarm.workSource, alarm.creatorUid, alarm.statsTag, true);
Christopher Tate14a7bb02015-10-01 10:24:31 -07004801 mWakeLock.acquire();
Dianne Hackborn627dfa12015-11-11 18:10:30 -08004802 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget();
Christopher Tate14a7bb02015-10-01 10:24:31 -07004803 }
Marcin Oczeretko735b19b2018-12-14 15:38:15 +00004804 final InFlight inflight = new InFlight(AlarmManagerService.this, alarm, nowELAPSED);
Christopher Tate14a7bb02015-10-01 10:24:31 -07004805 mInFlight.add(inflight);
4806 mBroadcastRefCount++;
Christopher Tate2f558d22019-01-17 16:58:31 -08004807 if (inflight.isBroadcast()) {
4808 notifyBroadcastAlarmPendingLocked(alarm.uid);
4809 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004810 if (allowWhileIdle) {
4811 // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
Suprabh Shuklac25447d2018-01-19 16:43:35 -08004812 mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED);
Makoto Onukie4918212018-02-06 11:30:15 -08004813 if ((mAppStateTracker == null)
4814 || mAppStateTracker.isUidInForeground(alarm.creatorUid)) {
Suprabh Shuklac25447d2018-01-19 16:43:35 -08004815 mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true);
4816 } else {
4817 mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false);
4818 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004819 if (RECORD_DEVICE_IDLE_ALARMS) {
4820 IdleDispatchEntry ent = new IdleDispatchEntry();
4821 ent.uid = alarm.uid;
4822 ent.pkg = alarm.packageName;
4823 ent.tag = alarm.statsTag;
4824 ent.op = "DELIVER";
4825 ent.elapsedRealtime = nowELAPSED;
4826 mAllowWhileIdleDispatches.add(ent);
4827 }
4828 }
Suprabh Shuklad65e58a2018-02-05 20:36:08 -08004829 if (!isExemptFromAppStandby(alarm)) {
Suprabh Shukla75edab12018-01-29 14:09:06 -08004830 final Pair<String, Integer> packageUser = Pair.create(alarm.sourcePackage,
4831 UserHandle.getUserId(alarm.creatorUid));
Suprabh Shukla47ca6fc2019-01-15 18:15:10 -08004832 mAppWakeupHistory.recordAlarmForPackage(alarm.sourcePackage,
4833 UserHandle.getUserId(alarm.creatorUid), nowELAPSED);
Suprabh Shukla75edab12018-01-29 14:09:06 -08004834 }
Christopher Tate14a7bb02015-10-01 10:24:31 -07004835 final BroadcastStats bs = inflight.mBroadcastStats;
4836 bs.count++;
4837 if (bs.nesting == 0) {
4838 bs.nesting = 1;
4839 bs.startTime = nowELAPSED;
4840 } else {
4841 bs.nesting++;
4842 }
4843 final FilterStats fs = inflight.mFilterStats;
4844 fs.count++;
4845 if (fs.nesting == 0) {
4846 fs.nesting = 1;
4847 fs.startTime = nowELAPSED;
4848 } else {
4849 fs.nesting++;
4850 }
4851 if (alarm.type == ELAPSED_REALTIME_WAKEUP
4852 || alarm.type == RTC_WAKEUP) {
4853 bs.numWakeup++;
4854 fs.numWakeup++;
Narayan Kamath695cf722017-12-21 18:32:47 +00004855 ActivityManager.noteWakeupAlarm(
4856 alarm.operation, alarm.workSource, alarm.uid, alarm.packageName,
4857 alarm.statsTag);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 }
4859 }
4860 }
mswest463f4c99d2018-02-01 10:13:10 -08004861
Suprabh Shukla0e49b642019-03-04 14:14:32 -08004862 private void incrementAlarmCount(int uid) {
4863 final int uidIndex = mAlarmsPerUid.indexOfKey(uid);
4864 if (uidIndex >= 0) {
4865 mAlarmsPerUid.setValueAt(uidIndex, mAlarmsPerUid.valueAt(uidIndex) + 1);
4866 } else {
4867 mAlarmsPerUid.put(uid, 1);
4868 }
4869 }
4870
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07004871 private void decrementAlarmCount(int uid, int decrement) {
4872 int oldCount = 0;
Suprabh Shukla0e49b642019-03-04 14:14:32 -08004873 final int uidIndex = mAlarmsPerUid.indexOfKey(uid);
4874 if (uidIndex >= 0) {
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07004875 oldCount = mAlarmsPerUid.valueAt(uidIndex);
4876 if (oldCount > decrement) {
4877 mAlarmsPerUid.setValueAt(uidIndex, oldCount - decrement);
Suprabh Shukla0e49b642019-03-04 14:14:32 -08004878 } else {
4879 mAlarmsPerUid.removeAt(uidIndex);
4880 }
4881 }
Suprabh Shukla5afe2f312019-04-12 17:19:30 -07004882 if (oldCount < decrement) {
4883 Slog.wtf(TAG, "Attempt to decrement existing alarm count " + oldCount + " by "
4884 + decrement + " for uid " + uid);
4885 }
Suprabh Shukla0e49b642019-03-04 14:14:32 -08004886 }
4887
mswest463f4c99d2018-02-01 10:13:10 -08004888 private class ShellCmd extends ShellCommand {
4889
4890 IAlarmManager getBinderService() {
4891 return IAlarmManager.Stub.asInterface(mService);
4892 }
4893
4894 @Override
4895 public int onCommand(String cmd) {
4896 if (cmd == null) {
4897 return handleDefaultCommands(cmd);
4898 }
4899
4900 final PrintWriter pw = getOutPrintWriter();
4901 try {
4902 switch (cmd) {
4903 case "set-time":
4904 final long millis = Long.parseLong(getNextArgRequired());
4905 return (getBinderService().setTime(millis)) ? 0 : -1;
4906 case "set-timezone":
4907 final String tz = getNextArgRequired();
4908 getBinderService().setTimeZone(tz);
4909 return 0;
4910 default:
4911 return handleDefaultCommands(cmd);
4912 }
4913 } catch (Exception e) {
4914 pw.println(e);
4915 }
4916 return -1;
4917 }
4918
4919 @Override
4920 public void onHelp() {
4921 PrintWriter pw = getOutPrintWriter();
4922 pw.println("Alarm manager service (alarm) commands:");
4923 pw.println(" help");
4924 pw.println(" Print this help text.");
4925 pw.println(" set-time TIME");
4926 pw.println(" Set the system clock time to TIME where TIME is milliseconds");
4927 pw.println(" since the Epoch.");
4928 pw.println(" set-timezone TZ");
4929 pw.println(" Set the system timezone to TZ where TZ is an Olson id.");
4930 }
4931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004932}