• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.server.alarm;
18 
19 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
20 import static android.app.AlarmManager.ELAPSED_REALTIME;
21 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
22 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE;
23 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_COMPAT;
24 import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
25 import static android.app.AlarmManager.FLAG_IDLE_UNTIL;
26 import static android.app.AlarmManager.FLAG_PRIORITIZE;
27 import static android.app.AlarmManager.FLAG_WAKE_FROM_IDLE;
28 import static android.app.AlarmManager.INTERVAL_DAY;
29 import static android.app.AlarmManager.INTERVAL_HOUR;
30 import static android.app.AlarmManager.RTC;
31 import static android.app.AlarmManager.RTC_WAKEUP;
32 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
33 import static android.os.PowerExemptionManager.REASON_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED;
34 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
35 import static android.os.PowerWhitelistManager.REASON_ALARM_MANAGER_WHILE_IDLE;
36 import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
37 import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
38 import static android.os.UserHandle.USER_SYSTEM;
39 
40 import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX;
41 import static com.android.server.alarm.Alarm.BATTERY_SAVER_POLICY_INDEX;
42 import static com.android.server.alarm.Alarm.DEVICE_IDLE_POLICY_INDEX;
43 import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST;
44 import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT;
45 import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE;
46 import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION;
47 import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX;
48 import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_ALARM_CANCELLED;
49 import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_DATA_CLEARED;
50 import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_EXACT_PERMISSION_REVOKED;
51 import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_PI_CANCELLED;
52 import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_UNDEFINED;
53 
54 import android.Manifest;
55 import android.annotation.NonNull;
56 import android.annotation.UserIdInt;
57 import android.app.Activity;
58 import android.app.ActivityManagerInternal;
59 import android.app.AlarmManager;
60 import android.app.AppOpsManager;
61 import android.app.BroadcastOptions;
62 import android.app.IAlarmCompleteListener;
63 import android.app.IAlarmListener;
64 import android.app.IAlarmManager;
65 import android.app.PendingIntent;
66 import android.app.compat.CompatChanges;
67 import android.app.usage.UsageStatsManager;
68 import android.app.usage.UsageStatsManagerInternal;
69 import android.content.BroadcastReceiver;
70 import android.content.Context;
71 import android.content.Intent;
72 import android.content.IntentFilter;
73 import android.content.pm.PackageManager;
74 import android.content.pm.PackageManagerInternal;
75 import android.net.Uri;
76 import android.os.BatteryManager;
77 import android.os.Binder;
78 import android.os.Build;
79 import android.os.Bundle;
80 import android.os.Environment;
81 import android.os.Handler;
82 import android.os.IBinder;
83 import android.os.Looper;
84 import android.os.Message;
85 import android.os.ParcelableException;
86 import android.os.PowerExemptionManager;
87 import android.os.PowerManager;
88 import android.os.Process;
89 import android.os.RemoteException;
90 import android.os.ResultReceiver;
91 import android.os.ServiceManager;
92 import android.os.ShellCallback;
93 import android.os.ShellCommand;
94 import android.os.SystemClock;
95 import android.os.SystemProperties;
96 import android.os.ThreadLocalWorkSource;
97 import android.os.Trace;
98 import android.os.UserHandle;
99 import android.os.WorkSource;
100 import android.provider.DeviceConfig;
101 import android.provider.Settings;
102 import android.system.Os;
103 import android.text.TextUtils;
104 import android.text.format.DateFormat;
105 import android.util.ArrayMap;
106 import android.util.ArraySet;
107 import android.util.IndentingPrintWriter;
108 import android.util.Log;
109 import android.util.LongArrayQueue;
110 import android.util.NtpTrustedTime;
111 import android.util.Pair;
112 import android.util.Slog;
113 import android.util.SparseArray;
114 import android.util.SparseBooleanArray;
115 import android.util.SparseIntArray;
116 import android.util.SparseLongArray;
117 import android.util.TimeUtils;
118 import android.util.proto.ProtoOutputStream;
119 
120 import com.android.internal.annotations.GuardedBy;
121 import com.android.internal.annotations.VisibleForTesting;
122 import com.android.internal.app.IAppOpsCallback;
123 import com.android.internal.app.IAppOpsService;
124 import com.android.internal.util.DumpUtils;
125 import com.android.internal.util.FrameworkStatsLog;
126 import com.android.internal.util.LocalLog;
127 import com.android.internal.util.RingBuffer;
128 import com.android.internal.util.StatLogger;
129 import com.android.server.AlarmManagerInternal;
130 import com.android.server.AppStateTracker;
131 import com.android.server.AppStateTrackerImpl;
132 import com.android.server.AppStateTrackerImpl.Listener;
133 import com.android.server.DeviceIdleInternal;
134 import com.android.server.EventLogTags;
135 import com.android.server.JobSchedulerBackgroundThread;
136 import com.android.server.LocalServices;
137 import com.android.server.SystemService;
138 import com.android.server.SystemServiceManager;
139 import com.android.server.pm.parsing.pkg.AndroidPackage;
140 import com.android.server.pm.permission.PermissionManagerService;
141 import com.android.server.pm.permission.PermissionManagerServiceInternal;
142 import com.android.server.usage.AppStandbyInternal;
143 import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
144 
145 import libcore.util.EmptyArray;
146 
147 import java.io.FileDescriptor;
148 import java.io.PrintWriter;
149 import java.text.SimpleDateFormat;
150 import java.time.DateTimeException;
151 import java.util.ArrayList;
152 import java.util.Arrays;
153 import java.util.Calendar;
154 import java.util.Collections;
155 import java.util.Comparator;
156 import java.util.Date;
157 import java.util.HashMap;
158 import java.util.Locale;
159 import java.util.Set;
160 import java.util.TimeZone;
161 import java.util.TreeSet;
162 import java.util.concurrent.ThreadLocalRandom;
163 import java.util.function.Predicate;
164 
165 /**
166  * Alarm manager implementation.
167  *
168  * Unit test:
169  * atest FrameworksMockingServicesTests:com.android.server.alarm.AlarmManagerServiceTest
170  */
171 public class AlarmManagerService extends SystemService {
172     private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
173     private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
174     private static final int REMOVAL_HISTORY_SIZE_PER_UID = 10;
175     static final int TIME_CHANGED_MASK = 1 << 16;
176     static final int IS_WAKEUP_MASK = RTC_WAKEUP_MASK | ELAPSED_REALTIME_WAKEUP_MASK;
177 
178     static final String TAG = "AlarmManager";
179     static final String TIME_TICK_TAG = "TIME_TICK";
180     static final boolean localLOGV = false;
181     static final boolean DEBUG_BATCH = localLOGV || false;
182     static final boolean DEBUG_ALARM_CLOCK = localLOGV || false;
183     static final boolean DEBUG_LISTENER_CALLBACK = localLOGV || false;
184     static final boolean DEBUG_WAKELOCK = localLOGV || false;
185     static final boolean DEBUG_BG_LIMIT = localLOGV || false;
186     static final boolean DEBUG_STANDBY = localLOGV || false;
187     static final boolean RECORD_ALARMS_IN_HISTORY = true;
188     static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
189     static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
190 
191     static final int TICK_HISTORY_DEPTH = 10;
192     static final long INDEFINITE_DELAY = 365 * INTERVAL_DAY;
193 
194     // Indices into the KEYS_APP_STANDBY_QUOTAS array.
195     static final int ACTIVE_INDEX = 0;
196     static final int WORKING_INDEX = 1;
197     static final int FREQUENT_INDEX = 2;
198     static final int RARE_INDEX = 3;
199     static final int NEVER_INDEX = 4;
200 
201     private final Intent mBackgroundIntent
202             = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
203 
204     private static final Intent NEXT_ALARM_CLOCK_CHANGED_INTENT =
205             new Intent(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)
206                     .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
207                             | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
208 
209     final LocalLog mLog = new LocalLog(TAG);
210 
211     AppOpsManager mAppOps;
212     DeviceIdleInternal mLocalDeviceIdleController;
213     private UsageStatsManagerInternal mUsageStatsManagerInternal;
214     private ActivityManagerInternal mActivityManagerInternal;
215     private PackageManagerInternal mPackageManagerInternal;
216     private volatile PermissionManagerServiceInternal mLocalPermissionManager;
217 
218     final Object mLock = new Object();
219 
220     /** Immutable set of app ids requesting {@link Manifest.permission#SCHEDULE_EXACT_ALARM} */
221     @VisibleForTesting
222     volatile Set<Integer> mExactAlarmCandidates = Collections.emptySet();
223 
224     /**
225      * A map from uid to the last op-mode we have seen for
226      * {@link AppOpsManager#OP_SCHEDULE_EXACT_ALARM}
227      */
228     @VisibleForTesting
229     @GuardedBy("mLock")
230     SparseIntArray mLastOpScheduleExactAlarm = new SparseIntArray();
231 
232     // List of alarms per uid deferred due to user applied background restrictions on the source app
233     SparseArray<ArrayList<Alarm>> mPendingBackgroundAlarms = new SparseArray<>();
234     private long mNextWakeup;
235     private long mNextNonWakeup;
236     private long mNextWakeUpSetAt;
237     private long mNextNonWakeUpSetAt;
238     private long mLastWakeup;
239     private long mLastTrigger;
240 
241     private long mLastTickSet;
242     private long mLastTickReceived;
243     // ring buffer of recent TIME_TICK issuance, in the elapsed timebase
244     private final long[] mTickHistory = new long[TICK_HISTORY_DEPTH];
245     private int mNextTickHistory;
246 
247     private final Injector mInjector;
248     int mBroadcastRefCount = 0;
249     MetricsHelper mMetricsHelper;
250     PowerManager.WakeLock mWakeLock;
251     SparseIntArray mAlarmsPerUid = new SparseIntArray();
252     ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
253     ArrayList<InFlight> mInFlight = new ArrayList<>();
254     private final ArrayList<AlarmManagerInternal.InFlightListener> mInFlightListeners =
255             new ArrayList<>();
256     AlarmHandler mHandler;
257     AppWakeupHistory mAppWakeupHistory;
258     AppWakeupHistory mAllowWhileIdleHistory;
259     AppWakeupHistory mAllowWhileIdleCompatHistory;
260     private final SparseLongArray mLastPriorityAlarmDispatch = new SparseLongArray();
261     private final SparseArray<RingBuffer<RemovedAlarm>> mRemovalHistory = new SparseArray<>();
262     ClockReceiver mClockReceiver;
263     final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
264     IBinder.DeathRecipient mListenerDeathRecipient;
265     Intent mTimeTickIntent;
266     IAlarmListener mTimeTickTrigger;
267     PendingIntent mDateChangeSender;
268     boolean mInteractive = true;
269     long mNonInteractiveStartTime;
270     long mNonInteractiveTime;
271     long mLastAlarmDeliveryTime;
272     long mStartCurrentDelayTime;
273     long mNextNonWakeupDeliveryTime;
274     long mLastTimeChangeClockTime;
275     long mLastTimeChangeRealtime;
276     int mNumTimeChanged;
277 
278     /**
279      * At boot we use SYSTEM_UI_SELF_PERMISSION to look up the definer's uid.
280      */
281     int mSystemUiUid;
282 
isTimeTickAlarm(Alarm a)283     static boolean isTimeTickAlarm(Alarm a) {
284         return a.uid == Process.SYSTEM_UID && TIME_TICK_TAG.equals(a.listenerTag);
285     }
286 
287     final static class IdleDispatchEntry {
288         int uid;
289         String pkg;
290         String tag;
291         String op;
292         long elapsedRealtime;
293         long argRealtime;
294     }
295     final ArrayList<IdleDispatchEntry> mAllowWhileIdleDispatches = new ArrayList();
296 
297     interface Stats {
298         int REORDER_ALARMS_FOR_STANDBY = 0;
299         int HAS_SCHEDULE_EXACT_ALARM = 1;
300     }
301 
302     private final StatLogger mStatLogger = new StatLogger("Alarm manager stats", new String[]{
303             "REORDER_ALARMS_FOR_STANDBY",
304             "HAS_SCHEDULE_EXACT_ALARM",
305     });
306 
307     BroadcastOptions mOptsWithFgs = BroadcastOptions.makeBasic();
308     BroadcastOptions mOptsWithoutFgs = BroadcastOptions.makeBasic();
309     BroadcastOptions mOptsTimeBroadcast = BroadcastOptions.makeBasic();
310 
311     // TODO(b/172085676): Move inside alarm store.
312     private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
313             new SparseArray<>();
314     private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
315             new SparseArray<>();
316     private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
317             new SparseBooleanArray();
318     private boolean mNextAlarmClockMayChange;
319 
320     @GuardedBy("mLock")
321     private final Runnable mAlarmClockUpdater = () -> mNextAlarmClockMayChange = true;
322 
323     // May only use on mHandler's thread, locking not required.
324     private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
325             new SparseArray<>();
326 
327     private AppStateTrackerImpl mAppStateTracker;
328     private boolean mAppStandbyParole;
329 
330     /**
331      * A container to keep rolling window history of previous times when an alarm was sent to
332      * a package.
333      */
334     @VisibleForTesting
335     static class AppWakeupHistory {
336         private ArrayMap<Pair<String, Integer>, LongArrayQueue> mPackageHistory =
337                 new ArrayMap<>();
338         private long mWindowSize;
339 
AppWakeupHistory(long windowSize)340         AppWakeupHistory(long windowSize) {
341             mWindowSize = windowSize;
342         }
343 
recordAlarmForPackage(String packageName, int userId, long nowElapsed)344         void recordAlarmForPackage(String packageName, int userId, long nowElapsed) {
345             final Pair<String, Integer> packageUser = Pair.create(packageName, userId);
346             LongArrayQueue history = mPackageHistory.get(packageUser);
347             if (history == null) {
348                 history = new LongArrayQueue();
349                 mPackageHistory.put(packageUser, history);
350             }
351             if (history.size() == 0 || history.peekLast() < nowElapsed) {
352                 history.addLast(nowElapsed);
353             }
354             snapToWindow(history);
355         }
356 
removeForUser(int userId)357         void removeForUser(int userId) {
358             for (int i = mPackageHistory.size() - 1; i >= 0; i--) {
359                 final Pair<String, Integer> packageUserKey = mPackageHistory.keyAt(i);
360                 if (packageUserKey.second == userId) {
361                     mPackageHistory.removeAt(i);
362                 }
363             }
364         }
365 
removeForPackage(String packageName, int userId)366         void removeForPackage(String packageName, int userId) {
367             final Pair<String, Integer> packageUser = Pair.create(packageName, userId);
368             mPackageHistory.remove(packageUser);
369         }
370 
snapToWindow(LongArrayQueue history)371         private void snapToWindow(LongArrayQueue history) {
372             while (history.peekFirst() + mWindowSize < history.peekLast()) {
373                 history.removeFirst();
374             }
375         }
376 
getTotalWakeupsInWindow(String packageName, int userId)377         int getTotalWakeupsInWindow(String packageName, int userId) {
378             final LongArrayQueue history = mPackageHistory.get(Pair.create(packageName, userId));
379             return (history == null) ? 0 : history.size();
380         }
381 
382         /**
383          * @param n The desired nth-last wakeup
384          *          (1=1st-last=the ultimate wakeup and 2=2nd-last=the penultimate wakeup)
385          */
getNthLastWakeupForPackage(String packageName, int userId, int n)386         long getNthLastWakeupForPackage(String packageName, int userId, int n) {
387             final LongArrayQueue history = mPackageHistory.get(Pair.create(packageName, userId));
388             if (history == null) {
389                 return 0;
390             }
391             final int i = history.size() - n;
392             return (i < 0) ? 0 : history.get(i);
393         }
394 
dump(IndentingPrintWriter pw, long nowElapsed)395         void dump(IndentingPrintWriter pw, long nowElapsed) {
396             pw.increaseIndent();
397             for (int i = 0; i < mPackageHistory.size(); i++) {
398                 final Pair<String, Integer> packageUser = mPackageHistory.keyAt(i);
399                 final LongArrayQueue timestamps = mPackageHistory.valueAt(i);
400                 pw.print(packageUser.first);
401                 pw.print(", u");
402                 pw.print(packageUser.second);
403                 pw.print(": ");
404                 // limit dumping to a max of 100 values
405                 final int lastIdx = Math.max(0, timestamps.size() - 100);
406                 for (int j = timestamps.size() - 1; j >= lastIdx; j--) {
407                     TimeUtils.formatDuration(timestamps.get(j), nowElapsed, pw);
408                     pw.print(", ");
409                 }
410                 pw.println();
411             }
412             pw.decreaseIndent();
413         }
414     }
415 
416     static class RemovedAlarm {
417         static final int REMOVE_REASON_UNDEFINED = 0;
418         static final int REMOVE_REASON_ALARM_CANCELLED = 1;
419         static final int REMOVE_REASON_EXACT_PERMISSION_REVOKED = 2;
420         static final int REMOVE_REASON_DATA_CLEARED = 3;
421         static final int REMOVE_REASON_PI_CANCELLED = 4;
422 
423         final String mTag;
424         final long mWhenRemovedElapsed;
425         final long mWhenRemovedRtc;
426         final int mRemoveReason;
427 
RemovedAlarm(Alarm a, int removeReason, long nowRtc, long nowElapsed)428         RemovedAlarm(Alarm a, int removeReason, long nowRtc, long nowElapsed) {
429             mTag = a.statsTag;
430             mRemoveReason = removeReason;
431             mWhenRemovedRtc = nowRtc;
432             mWhenRemovedElapsed = nowElapsed;
433         }
434 
isLoggable(int reason)435         static final boolean isLoggable(int reason) {
436             // We don't want to log meaningless reasons. This also gives a way for callers to
437             // opt out of logging, e.g. when replacing an alarm.
438             return reason != REMOVE_REASON_UNDEFINED;
439         }
440 
removeReasonToString(int reason)441         static final String removeReasonToString(int reason) {
442             switch (reason) {
443                 case REMOVE_REASON_ALARM_CANCELLED:
444                     return "alarm_cancelled";
445                 case REMOVE_REASON_EXACT_PERMISSION_REVOKED:
446                     return "exact_alarm_permission_revoked";
447                 case REMOVE_REASON_DATA_CLEARED:
448                     return "data_cleared";
449                 case REMOVE_REASON_PI_CANCELLED:
450                     return "pi_cancelled";
451                 default:
452                     return "unknown:" + reason;
453             }
454         }
455 
dump(IndentingPrintWriter pw, long nowElapsed, SimpleDateFormat sdf)456         void dump(IndentingPrintWriter pw, long nowElapsed, SimpleDateFormat sdf) {
457             pw.print("[tag", mTag);
458             pw.print("reason", removeReasonToString(mRemoveReason));
459             pw.print("elapsed=");
460             TimeUtils.formatDuration(mWhenRemovedElapsed, nowElapsed, pw);
461             pw.print(" rtc=");
462             pw.print(sdf.format(new Date(mWhenRemovedRtc)));
463             pw.println("]");
464         }
465     }
466 
467     /**
468      * All times are in milliseconds. These constants are kept synchronized with the system
469      * global Settings. Any access to this class or its fields should be done while
470      * holding the AlarmManagerService.mLock lock.
471      */
472     @VisibleForTesting
473     final class Constants implements DeviceConfig.OnPropertiesChangedListener {
474         @VisibleForTesting
475         static final int MAX_EXACT_ALARM_DENY_LIST_SIZE = 250;
476 
477         // Key names stored in the settings value.
478         @VisibleForTesting
479         static final String KEY_MIN_FUTURITY = "min_futurity";
480         @VisibleForTesting
481         static final String KEY_MIN_INTERVAL = "min_interval";
482         @VisibleForTesting
483         static final String KEY_MAX_INTERVAL = "max_interval";
484         @VisibleForTesting
485         static final String KEY_MIN_WINDOW = "min_window";
486         @VisibleForTesting
487         static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
488                 = "allow_while_idle_whitelist_duration";
489         @VisibleForTesting
490         static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
491         @VisibleForTesting
492         static final String KEY_MAX_ALARMS_PER_UID = "max_alarms_per_uid";
493         private static final String KEY_APP_STANDBY_WINDOW = "app_standby_window";
494         private static final String KEY_PREFIX_STANDBY_QUOTA = "standby_quota_";
495         @VisibleForTesting
496         final String[] KEYS_APP_STANDBY_QUOTAS = {
497                 KEY_PREFIX_STANDBY_QUOTA + "active",
498                 KEY_PREFIX_STANDBY_QUOTA + "working",
499                 KEY_PREFIX_STANDBY_QUOTA + "frequent",
500                 KEY_PREFIX_STANDBY_QUOTA + "rare",
501                 KEY_PREFIX_STANDBY_QUOTA + "never",
502         };
503         // Not putting this in the KEYS_APP_STANDBY_QUOTAS array because this uses a different
504         // window size.
505         private static final String KEY_APP_STANDBY_RESTRICTED_QUOTA =
506                 KEY_PREFIX_STANDBY_QUOTA + "restricted";
507         private static final String KEY_APP_STANDBY_RESTRICTED_WINDOW =
508                 "app_standby_restricted_window";
509 
510         @VisibleForTesting
511         static final String KEY_LAZY_BATCHING = "lazy_batching";
512 
513         private static final String KEY_TIME_TICK_ALLOWED_WHILE_IDLE =
514                 "time_tick_allowed_while_idle";
515 
516         @VisibleForTesting
517         static final String KEY_ALLOW_WHILE_IDLE_QUOTA = "allow_while_idle_quota";
518 
519         @VisibleForTesting
520         static final String KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA = "allow_while_idle_compat_quota";
521 
522         @VisibleForTesting
523         static final String KEY_ALLOW_WHILE_IDLE_WINDOW = "allow_while_idle_window";
524         @VisibleForTesting
525         static final String KEY_ALLOW_WHILE_IDLE_COMPAT_WINDOW = "allow_while_idle_compat_window";
526 
527         @VisibleForTesting
528         static final String KEY_CRASH_NON_CLOCK_APPS = "crash_non_clock_apps";
529         @VisibleForTesting
530         static final String KEY_PRIORITY_ALARM_DELAY = "priority_alarm_delay";
531         @VisibleForTesting
532         static final String KEY_EXACT_ALARM_DENY_LIST = "exact_alarm_deny_list";
533         @VisibleForTesting
534         static final String KEY_MIN_DEVICE_IDLE_FUZZ = "min_device_idle_fuzz";
535         @VisibleForTesting
536         static final String KEY_MAX_DEVICE_IDLE_FUZZ = "max_device_idle_fuzz";
537         @VisibleForTesting
538         static final String KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED =
539                 "kill_on_schedule_exact_alarm_revoked";
540 
541         private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
542         private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
543         private static final long DEFAULT_MAX_INTERVAL = 365 * INTERVAL_DAY;
544         private static final long DEFAULT_MIN_WINDOW = 10 * 60 * 1000;
545         private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10 * 1000;
546         private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
547         private static final int DEFAULT_MAX_ALARMS_PER_UID = 500;
548         private static final long DEFAULT_APP_STANDBY_WINDOW = 60 * 60 * 1000;  // 1 hr
549         /**
550          * Max number of times an app can receive alarms in {@link #APP_STANDBY_WINDOW}
551          */
552         private final int[] DEFAULT_APP_STANDBY_QUOTAS = {
553                 720,    // Active
554                 10,     // Working
555                 2,      // Frequent
556                 1,      // Rare
557                 0       // Never
558         };
559         private static final int DEFAULT_APP_STANDBY_RESTRICTED_QUOTA = 1;
560         private static final long DEFAULT_APP_STANDBY_RESTRICTED_WINDOW = INTERVAL_DAY;
561 
562         private static final boolean DEFAULT_LAZY_BATCHING = true;
563         private static final boolean DEFAULT_TIME_TICK_ALLOWED_WHILE_IDLE = true;
564 
565         /**
566          * Default quota for pre-S apps. The same as allowing an alarm slot once
567          * every ALLOW_WHILE_IDLE_LONG_DELAY, which was 9 minutes.
568          */
569         private static final int DEFAULT_ALLOW_WHILE_IDLE_COMPAT_QUOTA = 1;
570         private static final int DEFAULT_ALLOW_WHILE_IDLE_QUOTA = 72;
571 
572         private static final long DEFAULT_ALLOW_WHILE_IDLE_WINDOW = 60 * 60 * 1000; // 1 hour.
573         private static final long DEFAULT_ALLOW_WHILE_IDLE_COMPAT_WINDOW = 9 * 60 * 1000; // 9 mins.
574 
575         private static final boolean DEFAULT_CRASH_NON_CLOCK_APPS = true;
576 
577         private static final long DEFAULT_PRIORITY_ALARM_DELAY = 9 * 60_000;
578 
579         private static final long DEFAULT_MIN_DEVICE_IDLE_FUZZ = 2 * 60_000;
580         private static final long DEFAULT_MAX_DEVICE_IDLE_FUZZ = 15 * 60_000;
581 
582         private static final boolean DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED = true;
583 
584         // Minimum futurity of a new alarm
585         public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
586 
587         // Minimum alarm recurrence interval
588         public long MIN_INTERVAL = DEFAULT_MIN_INTERVAL;
589 
590         // Maximum alarm recurrence interval
591         public long MAX_INTERVAL = DEFAULT_MAX_INTERVAL;
592 
593         // Minimum window size for inexact alarms
594         public long MIN_WINDOW = DEFAULT_MIN_WINDOW;
595 
596         // BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
597         public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
598                 = DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
599 
600         // Direct alarm listener callback timeout
601         public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
602         public int MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID;
603 
604         public long APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW;
605         public int[] APP_STANDBY_QUOTAS = new int[DEFAULT_APP_STANDBY_QUOTAS.length];
606         public int APP_STANDBY_RESTRICTED_QUOTA = DEFAULT_APP_STANDBY_RESTRICTED_QUOTA;
607         public long APP_STANDBY_RESTRICTED_WINDOW = DEFAULT_APP_STANDBY_RESTRICTED_WINDOW;
608 
609         public boolean LAZY_BATCHING = DEFAULT_LAZY_BATCHING;
610         public boolean TIME_TICK_ALLOWED_WHILE_IDLE = DEFAULT_TIME_TICK_ALLOWED_WHILE_IDLE;
611 
612         public int ALLOW_WHILE_IDLE_QUOTA = DEFAULT_ALLOW_WHILE_IDLE_QUOTA;
613 
614         /**
615          * Used to provide backwards compatibility to pre-S apps with a quota equivalent to the
616          * earlier delay throttling mechanism.
617          */
618         public int ALLOW_WHILE_IDLE_COMPAT_QUOTA = DEFAULT_ALLOW_WHILE_IDLE_COMPAT_QUOTA;
619 
620         /**
621          * The window used for enforcing {@link #ALLOW_WHILE_IDLE_COMPAT_QUOTA}.
622          * Can be configured, but only recommended for testing.
623          */
624         public long ALLOW_WHILE_IDLE_COMPAT_WINDOW = DEFAULT_ALLOW_WHILE_IDLE_COMPAT_WINDOW;
625 
626         /**
627          * The window used for enforcing {@link #ALLOW_WHILE_IDLE_COMPAT_QUOTA}.
628          * Can be configured, but only recommended for testing.
629          */
630         public long ALLOW_WHILE_IDLE_WINDOW = DEFAULT_ALLOW_WHILE_IDLE_WINDOW;
631 
632         /**
633          * Whether or not to crash callers that use setExactAndAllowWhileIdle or setAlarmClock
634          * but don't hold the required permission. This is useful to catch broken
635          * apps and reverting to a softer failure in case of broken apps.
636          */
637         public boolean CRASH_NON_CLOCK_APPS = DEFAULT_CRASH_NON_CLOCK_APPS;
638 
639         /**
640          * Minimum delay between two slots that an app can get for their prioritized alarms, while
641          * the device is in doze.
642          */
643         public long PRIORITY_ALARM_DELAY = DEFAULT_PRIORITY_ALARM_DELAY;
644 
645         /**
646          * Read-only set of apps that won't get SCHEDULE_EXACT_ALARM when the app-op mode for
647          * OP_SCHEDULE_EXACT_ALARM is MODE_DEFAULT. Since this is read-only and volatile, this can
648          * be accessed without synchronizing on {@link #mLock}.
649          */
650         public volatile Set<String> EXACT_ALARM_DENY_LIST = Collections.emptySet();
651 
652         /**
653          * Minimum time interval that an IDLE_UNTIL will be pulled earlier to a subsequent
654          * WAKE_FROM_IDLE alarm.
655          */
656         public long MIN_DEVICE_IDLE_FUZZ = DEFAULT_MIN_DEVICE_IDLE_FUZZ;
657 
658         /**
659          * Maximum time interval that an IDLE_UNTIL will be pulled earlier to a subsequent
660          * WAKE_FROM_IDLE alarm.
661          */
662         public long MAX_DEVICE_IDLE_FUZZ = DEFAULT_MAX_DEVICE_IDLE_FUZZ;
663 
664         /**
665          * Whether or not to kill app when the permission
666          * {@link Manifest.permission#SCHEDULE_EXACT_ALARM} is revoked.
667          */
668         public boolean KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED =
669                 DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED;
670 
671         private long mLastAllowWhileIdleWhitelistDuration = -1;
672         private int mVersion = 0;
673 
Constants()674         Constants() {
675             updateAllowWhileIdleWhitelistDurationLocked();
676             for (int i = 0; i < APP_STANDBY_QUOTAS.length; i++) {
677                 APP_STANDBY_QUOTAS[i] = DEFAULT_APP_STANDBY_QUOTAS[i];
678             }
679         }
680 
getVersion()681         public int getVersion() {
682             synchronized (mLock) {
683                 return mVersion;
684             }
685         }
686 
start()687         public void start() {
688             mInjector.registerDeviceConfigListener(this);
689             onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_ALARM_MANAGER));
690         }
691 
updateAllowWhileIdleWhitelistDurationLocked()692         public void updateAllowWhileIdleWhitelistDurationLocked() {
693             if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) {
694                 mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION;
695 
696                 mOptsWithFgs.setTemporaryAppAllowlist(ALLOW_WHILE_IDLE_WHITELIST_DURATION,
697                         TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
698                         REASON_ALARM_MANAGER_WHILE_IDLE, "");
699                 mOptsWithoutFgs.setTemporaryAppAllowlist(ALLOW_WHILE_IDLE_WHITELIST_DURATION,
700                         TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED,
701                         REASON_ALARM_MANAGER_WHILE_IDLE, "");
702             }
703         }
704 
705         @Override
onPropertiesChanged(@onNull DeviceConfig.Properties properties)706         public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
707             boolean standbyQuotaUpdated = false;
708             boolean deviceIdleFuzzBoundariesUpdated = false;
709             synchronized (mLock) {
710                 mVersion++;
711                 for (String name : properties.getKeyset()) {
712                     if (name == null) {
713                         continue;
714                     }
715 
716                     switch (name) {
717                         case KEY_MIN_FUTURITY:
718                             MIN_FUTURITY = properties.getLong(
719                                     KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
720                             break;
721                         case KEY_MIN_INTERVAL:
722                             MIN_INTERVAL = properties.getLong(
723                                     KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
724                             break;
725                         case KEY_MAX_INTERVAL:
726                             MAX_INTERVAL = properties.getLong(
727                                     KEY_MAX_INTERVAL, DEFAULT_MAX_INTERVAL);
728                             break;
729                         case KEY_ALLOW_WHILE_IDLE_QUOTA:
730                             ALLOW_WHILE_IDLE_QUOTA = properties.getInt(KEY_ALLOW_WHILE_IDLE_QUOTA,
731                                     DEFAULT_ALLOW_WHILE_IDLE_QUOTA);
732                             if (ALLOW_WHILE_IDLE_QUOTA <= 0) {
733                                 Slog.w(TAG, "Must have positive allow_while_idle quota");
734                                 ALLOW_WHILE_IDLE_QUOTA = 1;
735                             }
736                             break;
737                         case KEY_MIN_WINDOW:
738                             MIN_WINDOW = properties.getLong(KEY_MIN_WINDOW, DEFAULT_MIN_WINDOW);
739                             break;
740                         case KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA:
741                             ALLOW_WHILE_IDLE_COMPAT_QUOTA = properties.getInt(
742                                     KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA,
743                                     DEFAULT_ALLOW_WHILE_IDLE_COMPAT_QUOTA);
744                             if (ALLOW_WHILE_IDLE_COMPAT_QUOTA <= 0) {
745                                 Slog.w(TAG, "Must have positive allow_while_idle_compat quota");
746                                 ALLOW_WHILE_IDLE_COMPAT_QUOTA = 1;
747                             }
748                             break;
749                         case KEY_ALLOW_WHILE_IDLE_WINDOW:
750                             ALLOW_WHILE_IDLE_WINDOW = properties.getLong(
751                                     KEY_ALLOW_WHILE_IDLE_WINDOW, DEFAULT_ALLOW_WHILE_IDLE_WINDOW);
752 
753                             if (ALLOW_WHILE_IDLE_WINDOW > INTERVAL_HOUR) {
754                                 Slog.w(TAG, "Cannot have allow_while_idle_window > "
755                                         + INTERVAL_HOUR);
756                                 ALLOW_WHILE_IDLE_WINDOW = INTERVAL_HOUR;
757                             } else if (ALLOW_WHILE_IDLE_WINDOW != DEFAULT_ALLOW_WHILE_IDLE_WINDOW) {
758                                 Slog.w(TAG, "Using a non-default allow_while_idle_window = "
759                                         + ALLOW_WHILE_IDLE_WINDOW);
760                             }
761                             break;
762                         case KEY_ALLOW_WHILE_IDLE_COMPAT_WINDOW:
763                             ALLOW_WHILE_IDLE_COMPAT_WINDOW = properties.getLong(
764                                     KEY_ALLOW_WHILE_IDLE_COMPAT_WINDOW,
765                                     DEFAULT_ALLOW_WHILE_IDLE_COMPAT_WINDOW);
766 
767                             if (ALLOW_WHILE_IDLE_COMPAT_WINDOW > INTERVAL_HOUR) {
768                                 Slog.w(TAG, "Cannot have allow_while_idle_compat_window > "
769                                         + INTERVAL_HOUR);
770                                 ALLOW_WHILE_IDLE_COMPAT_WINDOW = INTERVAL_HOUR;
771                             } else if (ALLOW_WHILE_IDLE_COMPAT_WINDOW
772                                     != DEFAULT_ALLOW_WHILE_IDLE_COMPAT_WINDOW) {
773                                 Slog.w(TAG, "Using a non-default allow_while_idle_compat_window = "
774                                         + ALLOW_WHILE_IDLE_COMPAT_WINDOW);
775                             }
776                             break;
777                         case KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION:
778                             ALLOW_WHILE_IDLE_WHITELIST_DURATION = properties.getLong(
779                                     KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
780                                     DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
781                             updateAllowWhileIdleWhitelistDurationLocked();
782                             break;
783                         case KEY_LISTENER_TIMEOUT:
784                             LISTENER_TIMEOUT = properties.getLong(
785                                     KEY_LISTENER_TIMEOUT, DEFAULT_LISTENER_TIMEOUT);
786                             break;
787                         case KEY_MAX_ALARMS_PER_UID:
788                             MAX_ALARMS_PER_UID = properties.getInt(
789                                     KEY_MAX_ALARMS_PER_UID, DEFAULT_MAX_ALARMS_PER_UID);
790                             if (MAX_ALARMS_PER_UID < DEFAULT_MAX_ALARMS_PER_UID) {
791                                 Slog.w(TAG, "Cannot set " + KEY_MAX_ALARMS_PER_UID + " lower than "
792                                         + DEFAULT_MAX_ALARMS_PER_UID);
793                                 MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID;
794                             }
795                             break;
796                         case KEY_APP_STANDBY_WINDOW:
797                         case KEY_APP_STANDBY_RESTRICTED_WINDOW:
798                             updateStandbyWindowsLocked();
799                             break;
800                         case KEY_LAZY_BATCHING:
801                             final boolean oldLazyBatching = LAZY_BATCHING;
802                             LAZY_BATCHING = properties.getBoolean(
803                                     KEY_LAZY_BATCHING, DEFAULT_LAZY_BATCHING);
804                             if (oldLazyBatching != LAZY_BATCHING) {
805                                 migrateAlarmsToNewStoreLocked();
806                             }
807                             break;
808                         case KEY_TIME_TICK_ALLOWED_WHILE_IDLE:
809                             TIME_TICK_ALLOWED_WHILE_IDLE = properties.getBoolean(
810                                     KEY_TIME_TICK_ALLOWED_WHILE_IDLE,
811                                     DEFAULT_TIME_TICK_ALLOWED_WHILE_IDLE);
812                             break;
813                         case KEY_CRASH_NON_CLOCK_APPS:
814                             CRASH_NON_CLOCK_APPS = properties.getBoolean(KEY_CRASH_NON_CLOCK_APPS,
815                                     DEFAULT_CRASH_NON_CLOCK_APPS);
816                             break;
817                         case KEY_PRIORITY_ALARM_DELAY:
818                             PRIORITY_ALARM_DELAY = properties.getLong(KEY_PRIORITY_ALARM_DELAY,
819                                     DEFAULT_PRIORITY_ALARM_DELAY);
820                             break;
821                         case KEY_EXACT_ALARM_DENY_LIST:
822                             final String rawValue = properties.getString(KEY_EXACT_ALARM_DENY_LIST,
823                                     "");
824                             final String[] values = rawValue.isEmpty()
825                                     ? EmptyArray.STRING
826                                     : rawValue.split(",", MAX_EXACT_ALARM_DENY_LIST_SIZE + 1);
827                             if (values.length > MAX_EXACT_ALARM_DENY_LIST_SIZE) {
828                                 Slog.w(TAG, "Deny list too long, truncating to "
829                                         + MAX_EXACT_ALARM_DENY_LIST_SIZE + " elements.");
830                                 updateExactAlarmDenyList(
831                                         Arrays.copyOf(values, MAX_EXACT_ALARM_DENY_LIST_SIZE));
832                             } else {
833                                 updateExactAlarmDenyList(values);
834                             }
835                             break;
836                         case KEY_MIN_DEVICE_IDLE_FUZZ:
837                         case KEY_MAX_DEVICE_IDLE_FUZZ:
838                             if (!deviceIdleFuzzBoundariesUpdated) {
839                                 updateDeviceIdleFuzzBoundaries();
840                                 deviceIdleFuzzBoundariesUpdated = true;
841                             }
842                             break;
843                         case KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED:
844                             KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED = properties.getBoolean(
845                                     KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED,
846                                     DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED);
847                             break;
848                         default:
849                             if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) {
850                                 // The quotas need to be updated in order, so we can't just rely
851                                 // on the property iteration order.
852                                 updateStandbyQuotasLocked();
853                                 standbyQuotaUpdated = true;
854                             }
855                             break;
856                     }
857                 }
858             }
859         }
860 
updateExactAlarmDenyList(String[] newDenyList)861         private void updateExactAlarmDenyList(String[] newDenyList) {
862             final Set<String> newSet = Collections.unmodifiableSet(new ArraySet<>(newDenyList));
863             final Set<String> removed = new ArraySet<>(EXACT_ALARM_DENY_LIST);
864             final Set<String> added = new ArraySet<>(newDenyList);
865 
866             added.removeAll(EXACT_ALARM_DENY_LIST);
867             removed.removeAll(newSet);
868             if (added.size() > 0) {
869                 mHandler.obtainMessage(AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_ADDED, added)
870                         .sendToTarget();
871             }
872             if (removed.size() > 0) {
873                 mHandler.obtainMessage(AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED, removed)
874                         .sendToTarget();
875             }
876             if (newDenyList.length == 0) {
877                 EXACT_ALARM_DENY_LIST = Collections.emptySet();
878             } else {
879                 EXACT_ALARM_DENY_LIST = newSet;
880             }
881         }
882 
migrateAlarmsToNewStoreLocked()883         private void migrateAlarmsToNewStoreLocked() {
884             final AlarmStore newStore = LAZY_BATCHING ? new LazyAlarmStore()
885                     : new BatchingAlarmStore();
886             final ArrayList<Alarm> allAlarms = mAlarmStore.remove((unused) -> true);
887             newStore.addAll(allAlarms);
888             mAlarmStore = newStore;
889             mAlarmStore.setAlarmClockRemovalListener(mAlarmClockUpdater);
890         }
891 
updateDeviceIdleFuzzBoundaries()892         private void updateDeviceIdleFuzzBoundaries() {
893             final DeviceConfig.Properties properties = DeviceConfig.getProperties(
894                     DeviceConfig.NAMESPACE_ALARM_MANAGER,
895                     KEY_MIN_DEVICE_IDLE_FUZZ, KEY_MAX_DEVICE_IDLE_FUZZ);
896 
897             MIN_DEVICE_IDLE_FUZZ = properties.getLong(KEY_MIN_DEVICE_IDLE_FUZZ,
898                     DEFAULT_MIN_DEVICE_IDLE_FUZZ);
899             MAX_DEVICE_IDLE_FUZZ = properties.getLong(KEY_MAX_DEVICE_IDLE_FUZZ,
900                     DEFAULT_MAX_DEVICE_IDLE_FUZZ);
901 
902             if (MAX_DEVICE_IDLE_FUZZ < MIN_DEVICE_IDLE_FUZZ) {
903                 Slog.w(TAG, "max_device_idle_fuzz cannot be smaller than"
904                         + " min_device_idle_fuzz! Increasing to "
905                         + MIN_DEVICE_IDLE_FUZZ);
906                 MAX_DEVICE_IDLE_FUZZ = MIN_DEVICE_IDLE_FUZZ;
907             }
908         }
909 
updateStandbyQuotasLocked()910         private void updateStandbyQuotasLocked() {
911             // The bucket quotas need to be read as an atomic unit but the properties passed to
912             // onPropertiesChanged may only have one key populated at a time.
913             final DeviceConfig.Properties properties = DeviceConfig.getProperties(
914                     DeviceConfig.NAMESPACE_ALARM_MANAGER, KEYS_APP_STANDBY_QUOTAS);
915 
916             APP_STANDBY_QUOTAS[ACTIVE_INDEX] = properties.getInt(
917                     KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX],
918                     DEFAULT_APP_STANDBY_QUOTAS[ACTIVE_INDEX]);
919             for (int i = WORKING_INDEX; i < KEYS_APP_STANDBY_QUOTAS.length; i++) {
920                 APP_STANDBY_QUOTAS[i] = properties.getInt(
921                         KEYS_APP_STANDBY_QUOTAS[i],
922                         Math.min(APP_STANDBY_QUOTAS[i - 1], DEFAULT_APP_STANDBY_QUOTAS[i]));
923             }
924 
925             APP_STANDBY_RESTRICTED_QUOTA = Math.max(1,
926                     DeviceConfig.getInt(DeviceConfig.NAMESPACE_ALARM_MANAGER,
927                             KEY_APP_STANDBY_RESTRICTED_QUOTA,
928                             DEFAULT_APP_STANDBY_RESTRICTED_QUOTA));
929         }
930 
updateStandbyWindowsLocked()931         private void updateStandbyWindowsLocked() {
932             // The bucket windows need to be read as an atomic unit but the properties passed to
933             // onPropertiesChanged may only have one key populated at a time.
934             final DeviceConfig.Properties properties = DeviceConfig.getProperties(
935                     DeviceConfig.NAMESPACE_ALARM_MANAGER,
936                     KEY_APP_STANDBY_WINDOW, KEY_APP_STANDBY_RESTRICTED_WINDOW);
937             APP_STANDBY_WINDOW = properties.getLong(
938                     KEY_APP_STANDBY_WINDOW, DEFAULT_APP_STANDBY_WINDOW);
939             if (APP_STANDBY_WINDOW > DEFAULT_APP_STANDBY_WINDOW) {
940                 Slog.w(TAG, "Cannot exceed the app_standby_window size of "
941                         + DEFAULT_APP_STANDBY_WINDOW);
942                 APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW;
943             } else if (APP_STANDBY_WINDOW < DEFAULT_APP_STANDBY_WINDOW) {
944                 // Not recommended outside of testing.
945                 Slog.w(TAG, "Using a non-default app_standby_window of " + APP_STANDBY_WINDOW);
946             }
947 
948             APP_STANDBY_RESTRICTED_WINDOW = Math.max(APP_STANDBY_WINDOW,
949                     properties.getLong(
950                             KEY_APP_STANDBY_RESTRICTED_WINDOW,
951                             DEFAULT_APP_STANDBY_RESTRICTED_WINDOW));
952         }
953 
dump(IndentingPrintWriter pw)954         void dump(IndentingPrintWriter pw) {
955             pw.println("Settings:");
956 
957             pw.increaseIndent();
958 
959             pw.print("version", mVersion);
960             pw.println();
961 
962             pw.print(KEY_MIN_FUTURITY);
963             pw.print("=");
964             TimeUtils.formatDuration(MIN_FUTURITY, pw);
965             pw.println();
966 
967             pw.print(KEY_MIN_INTERVAL);
968             pw.print("=");
969             TimeUtils.formatDuration(MIN_INTERVAL, pw);
970             pw.println();
971 
972             pw.print(KEY_MAX_INTERVAL);
973             pw.print("=");
974             TimeUtils.formatDuration(MAX_INTERVAL, pw);
975             pw.println();
976 
977             pw.print(KEY_MIN_WINDOW);
978             pw.print("=");
979             TimeUtils.formatDuration(MIN_WINDOW, pw);
980             pw.println();
981 
982             pw.print(KEY_LISTENER_TIMEOUT);
983             pw.print("=");
984             TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
985             pw.println();
986 
987             pw.print(KEY_ALLOW_WHILE_IDLE_QUOTA, ALLOW_WHILE_IDLE_QUOTA);
988             pw.println();
989 
990             pw.print(KEY_ALLOW_WHILE_IDLE_WINDOW);
991             pw.print("=");
992             TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WINDOW, pw);
993             pw.println();
994 
995             pw.print(KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA, ALLOW_WHILE_IDLE_COMPAT_QUOTA);
996             pw.println();
997 
998             pw.print(KEY_ALLOW_WHILE_IDLE_COMPAT_WINDOW);
999             pw.print("=");
1000             TimeUtils.formatDuration(ALLOW_WHILE_IDLE_COMPAT_WINDOW, pw);
1001             pw.println();
1002 
1003             pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
1004             pw.print("=");
1005             TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
1006             pw.println();
1007 
1008             pw.print(KEY_MAX_ALARMS_PER_UID, MAX_ALARMS_PER_UID);
1009             pw.println();
1010 
1011             pw.print(KEY_APP_STANDBY_WINDOW);
1012             pw.print("=");
1013             TimeUtils.formatDuration(APP_STANDBY_WINDOW, pw);
1014             pw.println();
1015 
1016             for (int i = 0; i < KEYS_APP_STANDBY_QUOTAS.length; i++) {
1017                 pw.print(KEYS_APP_STANDBY_QUOTAS[i], APP_STANDBY_QUOTAS[i]);
1018                 pw.println();
1019             }
1020 
1021             pw.print(KEY_APP_STANDBY_RESTRICTED_QUOTA, APP_STANDBY_RESTRICTED_QUOTA);
1022             pw.println();
1023 
1024             pw.print(KEY_APP_STANDBY_RESTRICTED_WINDOW);
1025             pw.print("=");
1026             TimeUtils.formatDuration(APP_STANDBY_RESTRICTED_WINDOW, pw);
1027             pw.println();
1028 
1029             pw.print(KEY_LAZY_BATCHING, LAZY_BATCHING);
1030             pw.println();
1031 
1032             pw.print(KEY_TIME_TICK_ALLOWED_WHILE_IDLE, TIME_TICK_ALLOWED_WHILE_IDLE);
1033             pw.println();
1034 
1035             pw.print(KEY_CRASH_NON_CLOCK_APPS, CRASH_NON_CLOCK_APPS);
1036             pw.println();
1037 
1038             pw.print(KEY_PRIORITY_ALARM_DELAY);
1039             pw.print("=");
1040             TimeUtils.formatDuration(PRIORITY_ALARM_DELAY, pw);
1041             pw.println();
1042 
1043             pw.print(KEY_EXACT_ALARM_DENY_LIST, EXACT_ALARM_DENY_LIST);
1044             pw.println();
1045 
1046             pw.print(KEY_MIN_DEVICE_IDLE_FUZZ);
1047             pw.print("=");
1048             TimeUtils.formatDuration(MIN_DEVICE_IDLE_FUZZ, pw);
1049             pw.println();
1050 
1051             pw.print(KEY_MAX_DEVICE_IDLE_FUZZ);
1052             pw.print("=");
1053             TimeUtils.formatDuration(MAX_DEVICE_IDLE_FUZZ, pw);
1054             pw.println();
1055 
1056             pw.print(KEY_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED,
1057                     KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED);
1058             pw.println();
1059 
1060             pw.decreaseIndent();
1061         }
1062 
dumpProto(ProtoOutputStream proto, long fieldId)1063         void dumpProto(ProtoOutputStream proto, long fieldId) {
1064             final long token = proto.start(fieldId);
1065 
1066             proto.write(ConstantsProto.MIN_FUTURITY_DURATION_MS, MIN_FUTURITY);
1067             proto.write(ConstantsProto.MIN_INTERVAL_DURATION_MS, MIN_INTERVAL);
1068             proto.write(ConstantsProto.MAX_INTERVAL_DURATION_MS, MAX_INTERVAL);
1069             proto.write(ConstantsProto.LISTENER_TIMEOUT_DURATION_MS, LISTENER_TIMEOUT);
1070             proto.write(ConstantsProto.ALLOW_WHILE_IDLE_WHITELIST_DURATION_MS,
1071                     ALLOW_WHILE_IDLE_WHITELIST_DURATION);
1072 
1073             proto.end(token);
1074         }
1075     }
1076 
1077     Constants mConstants;
1078 
1079     // Alarm delivery ordering bookkeeping
1080     static final int PRIO_TICK = 0;
1081     static final int PRIO_WAKEUP = 1;
1082     static final int PRIO_NORMAL = 2;
1083 
1084     final class PriorityClass {
1085         int seq;
1086         int priority;
1087 
PriorityClass()1088         PriorityClass() {
1089             seq = mCurrentSeq - 1;
1090             priority = PRIO_NORMAL;
1091         }
1092     }
1093 
1094     final HashMap<String, PriorityClass> mPriorities = new HashMap<>();
1095     int mCurrentSeq = 0;
1096 
1097     final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
1098         @Override
1099         public int compare(Alarm lhs, Alarm rhs) {
1100 
1101             // Alarm to exit device_idle should go out first.
1102             final boolean lhsIdleUntil = (lhs.flags & FLAG_IDLE_UNTIL) != 0;
1103             final boolean rhsIdleUntil = (rhs.flags & FLAG_IDLE_UNTIL) != 0;
1104             if (lhsIdleUntil != rhsIdleUntil) {
1105                 return lhsIdleUntil ? -1 : 1;
1106             }
1107 
1108             // Then, priority class trumps everything.  TICK < WAKEUP < NORMAL
1109             if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
1110                 return -1;
1111             } else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
1112                 return 1;
1113             }
1114 
1115             // within each class, sort by requested delivery time
1116             if (lhs.getRequestedElapsed() < rhs.getRequestedElapsed()) {
1117                 return -1;
1118             } else if (lhs.getRequestedElapsed() > rhs.getRequestedElapsed()) {
1119                 return 1;
1120             }
1121 
1122             return 0;
1123         }
1124     };
1125 
calculateDeliveryPriorities(ArrayList<Alarm> alarms)1126     void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
1127         final int N = alarms.size();
1128         for (int i = 0; i < N; i++) {
1129             Alarm a = alarms.get(i);
1130 
1131             final int alarmPrio;
1132             if (a.listener == mTimeTickTrigger) {
1133                 alarmPrio = PRIO_TICK;
1134             } else if (a.wakeup) {
1135                 alarmPrio = PRIO_WAKEUP;
1136             } else {
1137                 alarmPrio = PRIO_NORMAL;
1138             }
1139 
1140             PriorityClass packagePrio = a.priorityClass;
1141             String alarmPackage = a.sourcePackage;
1142             if (packagePrio == null) packagePrio = mPriorities.get(alarmPackage);
1143             if (packagePrio == null) {
1144                 packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
1145                 mPriorities.put(alarmPackage, packagePrio);
1146             }
1147             a.priorityClass = packagePrio;
1148 
1149             if (packagePrio.seq != mCurrentSeq) {
1150                 // first alarm we've seen in the current delivery generation from this package
1151                 packagePrio.priority = alarmPrio;
1152                 packagePrio.seq = mCurrentSeq;
1153             } else {
1154                 // Multiple alarms from this package being delivered in this generation;
1155                 // bump the package's delivery class if it's warranted.
1156                 // TICK < WAKEUP < NORMAL
1157                 if (alarmPrio < packagePrio.priority) {
1158                     packagePrio.priority = alarmPrio;
1159                 }
1160             }
1161         }
1162     }
1163 
1164     // minimum recurrence period or alarm futurity for us to be able to fuzz it
1165     static final long MIN_FUZZABLE_INTERVAL = 10000;
1166     @GuardedBy("mLock")
1167     AlarmStore mAlarmStore;
1168 
1169     // set to non-null if in idle mode; while in this mode, any alarms we don't want
1170     // to run during this time are rescehduled to go off after this alarm.
1171     Alarm mPendingIdleUntil = null;
1172     Alarm mNextWakeFromIdle = null;
1173 
1174     @VisibleForTesting
AlarmManagerService(Context context, Injector injector)1175     AlarmManagerService(Context context, Injector injector) {
1176         super(context);
1177         mInjector = injector;
1178     }
1179 
AlarmManagerService(Context context)1180     public AlarmManagerService(Context context) {
1181         this(context, new Injector(context));
1182     }
1183 
isRtc(int type)1184     static boolean isRtc(int type) {
1185         return (type == RTC || type == RTC_WAKEUP);
1186     }
1187 
convertToElapsed(long when, int type)1188     private long convertToElapsed(long when, int type) {
1189         if (isRtc(type)) {
1190             when -= mInjector.getCurrentTimeMillis() - mInjector.getElapsedRealtime();
1191         }
1192         return when;
1193     }
1194 
1195     /**
1196      * This is the minimum window that can be requested for the given alarm. Windows smaller than
1197      * this value will be elongated to match it.
1198      * Current heuristic is similar to {@link #maxTriggerTime(long, long, long)}, the minimum
1199      * allowed window is either {@link Constants#MIN_WINDOW} or 75% of the alarm's futurity,
1200      * whichever is smaller.
1201      */
getMinimumAllowedWindow(long nowElapsed, long triggerElapsed)1202     long getMinimumAllowedWindow(long nowElapsed, long triggerElapsed) {
1203         final long futurity = triggerElapsed - nowElapsed;
1204         return Math.min((long) (futurity * 0.75), mConstants.MIN_WINDOW);
1205     }
1206 
1207     // Apply a heuristic to { recurrence interval, futurity of the trigger time } to
1208     // calculate the end of our nominal delivery window for the alarm.
maxTriggerTime(long now, long triggerAtTime, long interval)1209     static long maxTriggerTime(long now, long triggerAtTime, long interval) {
1210         // Current heuristic: batchable window is 75% of either the recurrence interval
1211         // [for a periodic alarm] or of the time from now to the desired delivery time,
1212         // with a minimum delay/interval of 10 seconds, under which we will simply not
1213         // defer the alarm.
1214         long futurity = (interval == 0)
1215                 ? (triggerAtTime - now)
1216                 : interval;
1217         if (futurity < MIN_FUZZABLE_INTERVAL) {
1218             futurity = 0;
1219         }
1220         long maxElapsed = triggerAtTime + (long) (0.75 * futurity);
1221         // For non-repeating alarms, window is capped at a maximum of one hour from the requested
1222         // delivery time. This allows for inexact-while-idle alarms to be slightly more reliable.
1223         // In practice, the delivery window should generally be much smaller than that
1224         // when the device is not idling.
1225         if (interval == 0) {
1226             maxElapsed = Math.min(maxElapsed, triggerAtTime + INTERVAL_HOUR);
1227         }
1228         return clampPositive(maxElapsed);
1229     }
1230 
1231     // The RTC clock has moved arbitrarily, so we need to recalculate all the RTC alarm deliveries.
reevaluateRtcAlarms()1232     void reevaluateRtcAlarms() {
1233         synchronized (mLock) {
1234             boolean changed = mAlarmStore.updateAlarmDeliveries(a -> {
1235                 if (!isRtc(a.type)) {
1236                     return false;
1237                 }
1238                 return restoreRequestedTime(a);
1239             });
1240 
1241             if (changed && mPendingIdleUntil != null) {
1242                 if (mNextWakeFromIdle != null && isRtc(mNextWakeFromIdle.type)) {
1243                     // The next wake from idle got updated due to the rtc time change, so we need
1244                     // to update the time we have to come out of idle too.
1245                     final boolean idleUntilUpdated = mAlarmStore.updateAlarmDeliveries(
1246                             a -> (a == mPendingIdleUntil) && adjustIdleUntilTime(a));
1247                     if (idleUntilUpdated) {
1248                         mAlarmStore.updateAlarmDeliveries(
1249                                 alarm -> adjustDeliveryTimeBasedOnDeviceIdle(alarm));
1250                     }
1251                 }
1252             }
1253 
1254             if (changed) {
1255                 rescheduleKernelAlarmsLocked();
1256                 // Only time shifted, so the next alarm clock will not change
1257             }
1258         }
1259     }
1260 
1261     /**
1262      * Recalculates alarm send times based on the current app-standby buckets
1263      *
1264      * @param targetPackages [Package, User] pairs for which alarms need to be re-evaluated,
1265      *                       null indicates all
1266      * @return True if there was any reordering done to the current list.
1267      */
reorderAlarmsBasedOnStandbyBuckets(ArraySet<Pair<String, Integer>> targetPackages)1268     boolean reorderAlarmsBasedOnStandbyBuckets(ArraySet<Pair<String, Integer>> targetPackages) {
1269         final long start = mStatLogger.getTime();
1270 
1271         final boolean changed = mAlarmStore.updateAlarmDeliveries(a -> {
1272             final Pair<String, Integer> packageUser =
1273                     Pair.create(a.sourcePackage, UserHandle.getUserId(a.creatorUid));
1274             if (targetPackages != null && !targetPackages.contains(packageUser)) {
1275                 return false;
1276             }
1277             return adjustDeliveryTimeBasedOnBucketLocked(a);
1278         });
1279 
1280         mStatLogger.logDurationStat(Stats.REORDER_ALARMS_FOR_STANDBY, start);
1281         return changed;
1282     }
1283 
restoreRequestedTime(Alarm a)1284     private boolean restoreRequestedTime(Alarm a) {
1285         return a.setPolicyElapsed(REQUESTER_POLICY_INDEX, convertToElapsed(a.origWhen, a.type));
1286     }
1287 
clampPositive(long val)1288     static long clampPositive(long val) {
1289         return (val >= 0) ? val : Long.MAX_VALUE;
1290     }
1291 
1292     /**
1293      * Sends alarms that were blocked due to user applied background restrictions - either because
1294      * the user lifted those or the uid came to foreground.
1295      *
1296      * @param uid         uid to filter on
1297      * @param packageName package to filter on, or null for all packages in uid
1298      */
sendPendingBackgroundAlarmsLocked(int uid, String packageName)1299     void sendPendingBackgroundAlarmsLocked(int uid, String packageName) {
1300         final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(uid);
1301         if (alarmsForUid == null || alarmsForUid.size() == 0) {
1302             return;
1303         }
1304         final ArrayList<Alarm> alarmsToDeliver;
1305         if (packageName != null) {
1306             if (DEBUG_BG_LIMIT) {
1307                 Slog.d(TAG, "Sending blocked alarms for uid " + uid + ", package " + packageName);
1308             }
1309             alarmsToDeliver = new ArrayList<>();
1310             for (int i = alarmsForUid.size() - 1; i >= 0; i--) {
1311                 final Alarm a = alarmsForUid.get(i);
1312                 if (a.matches(packageName)) {
1313                     alarmsToDeliver.add(alarmsForUid.remove(i));
1314                 }
1315             }
1316             if (alarmsForUid.size() == 0) {
1317                 mPendingBackgroundAlarms.remove(uid);
1318             }
1319         } else {
1320             if (DEBUG_BG_LIMIT) {
1321                 Slog.d(TAG, "Sending blocked alarms for uid " + uid);
1322             }
1323             alarmsToDeliver = alarmsForUid;
1324             mPendingBackgroundAlarms.remove(uid);
1325         }
1326         deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
1327     }
1328 
1329     /**
1330      * Check all alarms in {@link #mPendingBackgroundAlarms} and send the ones that are not
1331      * restricted.
1332      *
1333      * This is only called when the power save whitelist changes, so it's okay to be slow.
1334      */
sendAllUnrestrictedPendingBackgroundAlarmsLocked()1335     void sendAllUnrestrictedPendingBackgroundAlarmsLocked() {
1336         final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>();
1337 
1338         findAllUnrestrictedPendingBackgroundAlarmsLockedInner(
1339                 mPendingBackgroundAlarms, alarmsToDeliver, this::isBackgroundRestricted);
1340 
1341         if (alarmsToDeliver.size() > 0) {
1342             deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
1343         }
1344     }
1345 
1346     @VisibleForTesting
findAllUnrestrictedPendingBackgroundAlarmsLockedInner( SparseArray<ArrayList<Alarm>> pendingAlarms, ArrayList<Alarm> unrestrictedAlarms, Predicate<Alarm> isBackgroundRestricted)1347     static void findAllUnrestrictedPendingBackgroundAlarmsLockedInner(
1348             SparseArray<ArrayList<Alarm>> pendingAlarms, ArrayList<Alarm> unrestrictedAlarms,
1349             Predicate<Alarm> isBackgroundRestricted) {
1350 
1351         for (int uidIndex = pendingAlarms.size() - 1; uidIndex >= 0; uidIndex--) {
1352             final ArrayList<Alarm> alarmsForUid = pendingAlarms.valueAt(uidIndex);
1353 
1354             for (int alarmIndex = alarmsForUid.size() - 1; alarmIndex >= 0; alarmIndex--) {
1355                 final Alarm alarm = alarmsForUid.get(alarmIndex);
1356 
1357                 if (isBackgroundRestricted.test(alarm)) {
1358                     continue;
1359                 }
1360 
1361                 unrestrictedAlarms.add(alarm);
1362                 alarmsForUid.remove(alarmIndex);
1363             }
1364 
1365             if (alarmsForUid.size() == 0) {
1366                 pendingAlarms.removeAt(uidIndex);
1367             }
1368         }
1369     }
1370 
deliverPendingBackgroundAlarmsLocked(ArrayList<Alarm> alarms, long nowELAPSED)1371     private void deliverPendingBackgroundAlarmsLocked(ArrayList<Alarm> alarms, long nowELAPSED) {
1372         final int N = alarms.size();
1373         boolean hasWakeup = false;
1374         for (int i = 0; i < N; i++) {
1375             final Alarm alarm = alarms.get(i);
1376             if (alarm.wakeup) {
1377                 hasWakeup = true;
1378             }
1379             alarm.count = 1;
1380             // Recurring alarms may have passed several alarm intervals while the
1381             // alarm was kept pending. Send the appropriate trigger count.
1382             if (alarm.repeatInterval > 0) {
1383                 alarm.count += (nowELAPSED - alarm.getRequestedElapsed()) / alarm.repeatInterval;
1384                 // Also schedule its next recurrence
1385                 final long delta = alarm.count * alarm.repeatInterval;
1386                 final long nextElapsed = alarm.getRequestedElapsed() + delta;
1387                 final long nextMaxElapsed = maxTriggerTime(nowELAPSED, nextElapsed,
1388                         alarm.repeatInterval);
1389                 setImplLocked(alarm.type, alarm.origWhen + delta, nextElapsed,
1390                         nextMaxElapsed - nextElapsed, alarm.repeatInterval, alarm.operation, null,
1391                         null, alarm.flags, alarm.workSource, alarm.alarmClock, alarm.uid,
1392                         alarm.packageName, null, EXACT_ALLOW_REASON_NOT_APPLICABLE);
1393                 // Kernel alarms will be rescheduled as needed in setImplLocked
1394             }
1395         }
1396         if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
1397             // No need to wakeup for non wakeup alarms
1398             if (mPendingNonWakeupAlarms.size() == 0) {
1399                 mStartCurrentDelayTime = nowELAPSED;
1400                 mNextNonWakeupDeliveryTime = nowELAPSED
1401                         + ((currentNonWakeupFuzzLocked(nowELAPSED) * 3) / 2);
1402             }
1403             mPendingNonWakeupAlarms.addAll(alarms);
1404             mNumDelayedAlarms += alarms.size();
1405         } else {
1406             if (DEBUG_BG_LIMIT) {
1407                 Slog.d(TAG, "Waking up to deliver pending blocked alarms");
1408             }
1409             // Since we are waking up, also deliver any pending non wakeup alarms we have.
1410             if (mPendingNonWakeupAlarms.size() > 0) {
1411                 alarms.addAll(mPendingNonWakeupAlarms);
1412                 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
1413                 mTotalDelayTime += thisDelayTime;
1414                 if (mMaxDelayTime < thisDelayTime) {
1415                     mMaxDelayTime = thisDelayTime;
1416                 }
1417                 mPendingNonWakeupAlarms.clear();
1418             }
1419             calculateDeliveryPriorities(alarms);
1420             Collections.sort(alarms, mAlarmDispatchComparator);
1421             deliverAlarmsLocked(alarms, nowELAPSED);
1422         }
1423     }
1424 
1425     static final class InFlight {
1426         final PendingIntent mPendingIntent;
1427         final long mWhenElapsed;
1428         final IBinder mListener;
1429         final WorkSource mWorkSource;
1430         final int mUid;
1431         final int mCreatorUid;
1432         final String mTag;
1433         final BroadcastStats mBroadcastStats;
1434         final FilterStats mFilterStats;
1435         final int mAlarmType;
1436 
InFlight(AlarmManagerService service, Alarm alarm, long nowELAPSED)1437         InFlight(AlarmManagerService service, Alarm alarm, long nowELAPSED) {
1438             mPendingIntent = alarm.operation;
1439             mWhenElapsed = nowELAPSED;
1440             mListener = alarm.listener != null ? alarm.listener.asBinder() : null;
1441             mWorkSource = alarm.workSource;
1442             mUid = alarm.uid;
1443             mCreatorUid = alarm.creatorUid;
1444             mTag = alarm.statsTag;
1445             mBroadcastStats = (alarm.operation != null)
1446                     ? service.getStatsLocked(alarm.operation)
1447                     : service.getStatsLocked(alarm.uid, alarm.packageName);
1448             FilterStats fs = mBroadcastStats.filterStats.get(mTag);
1449             if (fs == null) {
1450                 fs = new FilterStats(mBroadcastStats, mTag);
1451                 mBroadcastStats.filterStats.put(mTag, fs);
1452             }
1453             fs.lastTime = nowELAPSED;
1454             mFilterStats = fs;
1455             mAlarmType = alarm.type;
1456         }
1457 
isBroadcast()1458         boolean isBroadcast() {
1459             return mPendingIntent != null && mPendingIntent.isBroadcast();
1460         }
1461 
1462         @Override
toString()1463         public String toString() {
1464             return "InFlight{"
1465                     + "pendingIntent=" + mPendingIntent
1466                     + ", when=" + mWhenElapsed
1467                     + ", workSource=" + mWorkSource
1468                     + ", uid=" + mUid
1469                     + ", creatorUid=" + mCreatorUid
1470                     + ", tag=" + mTag
1471                     + ", broadcastStats=" + mBroadcastStats
1472                     + ", filterStats=" + mFilterStats
1473                     + ", alarmType=" + mAlarmType
1474                     + "}";
1475         }
1476 
dumpDebug(ProtoOutputStream proto, long fieldId)1477         public void dumpDebug(ProtoOutputStream proto, long fieldId) {
1478             final long token = proto.start(fieldId);
1479 
1480             proto.write(InFlightProto.UID, mUid);
1481             proto.write(InFlightProto.TAG, mTag);
1482             proto.write(InFlightProto.WHEN_ELAPSED_MS, mWhenElapsed);
1483             proto.write(InFlightProto.ALARM_TYPE, mAlarmType);
1484             if (mPendingIntent != null) {
1485                 mPendingIntent.dumpDebug(proto, InFlightProto.PENDING_INTENT);
1486             }
1487             if (mBroadcastStats != null) {
1488                 mBroadcastStats.dumpDebug(proto, InFlightProto.BROADCAST_STATS);
1489             }
1490             if (mFilterStats != null) {
1491                 mFilterStats.dumpDebug(proto, InFlightProto.FILTER_STATS);
1492             }
1493             if (mWorkSource != null) {
1494                 mWorkSource.dumpDebug(proto, InFlightProto.WORK_SOURCE);
1495             }
1496 
1497             proto.end(token);
1498         }
1499     }
1500 
notifyBroadcastAlarmPendingLocked(int uid)1501     private void notifyBroadcastAlarmPendingLocked(int uid) {
1502         final int numListeners = mInFlightListeners.size();
1503         for (int i = 0; i < numListeners; i++) {
1504             mInFlightListeners.get(i).broadcastAlarmPending(uid);
1505         }
1506     }
1507 
notifyBroadcastAlarmCompleteLocked(int uid)1508     private void notifyBroadcastAlarmCompleteLocked(int uid) {
1509         final int numListeners = mInFlightListeners.size();
1510         for (int i = 0; i < numListeners; i++) {
1511             mInFlightListeners.get(i).broadcastAlarmComplete(uid);
1512         }
1513     }
1514 
1515     static final class FilterStats {
1516         final BroadcastStats mBroadcastStats;
1517         final String mTag;
1518 
1519         long lastTime;
1520         long aggregateTime;
1521         int count;
1522         int numWakeup;
1523         long startTime;
1524         int nesting;
1525 
FilterStats(BroadcastStats broadcastStats, String tag)1526         FilterStats(BroadcastStats broadcastStats, String tag) {
1527             mBroadcastStats = broadcastStats;
1528             mTag = tag;
1529         }
1530 
1531         @Override
toString()1532         public String toString() {
1533             return "FilterStats{"
1534                     + "tag=" + mTag
1535                     + ", lastTime=" + lastTime
1536                     + ", aggregateTime=" + aggregateTime
1537                     + ", count=" + count
1538                     + ", numWakeup=" + numWakeup
1539                     + ", startTime=" + startTime
1540                     + ", nesting=" + nesting
1541                     + "}";
1542         }
1543 
dumpDebug(ProtoOutputStream proto, long fieldId)1544         public void dumpDebug(ProtoOutputStream proto, long fieldId) {
1545             final long token = proto.start(fieldId);
1546 
1547             proto.write(FilterStatsProto.TAG, mTag);
1548             proto.write(FilterStatsProto.LAST_FLIGHT_TIME_REALTIME, lastTime);
1549             proto.write(FilterStatsProto.TOTAL_FLIGHT_DURATION_MS, aggregateTime);
1550             proto.write(FilterStatsProto.COUNT, count);
1551             proto.write(FilterStatsProto.WAKEUP_COUNT, numWakeup);
1552             proto.write(FilterStatsProto.START_TIME_REALTIME, startTime);
1553             proto.write(FilterStatsProto.NESTING, nesting);
1554 
1555             proto.end(token);
1556         }
1557     }
1558 
1559     static final class BroadcastStats {
1560         final int mUid;
1561         final String mPackageName;
1562 
1563         long aggregateTime;
1564         int count;
1565         int numWakeup;
1566         long startTime;
1567         int nesting;
1568         final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
1569 
BroadcastStats(int uid, String packageName)1570         BroadcastStats(int uid, String packageName) {
1571             mUid = uid;
1572             mPackageName = packageName;
1573         }
1574 
1575         @Override
toString()1576         public String toString() {
1577             return "BroadcastStats{"
1578                     + "uid=" + mUid
1579                     + ", packageName=" + mPackageName
1580                     + ", aggregateTime=" + aggregateTime
1581                     + ", count=" + count
1582                     + ", numWakeup=" + numWakeup
1583                     + ", startTime=" + startTime
1584                     + ", nesting=" + nesting
1585                     + "}";
1586         }
1587 
dumpDebug(ProtoOutputStream proto, long fieldId)1588         public void dumpDebug(ProtoOutputStream proto, long fieldId) {
1589             final long token = proto.start(fieldId);
1590 
1591             proto.write(BroadcastStatsProto.UID, mUid);
1592             proto.write(BroadcastStatsProto.PACKAGE_NAME, mPackageName);
1593             proto.write(BroadcastStatsProto.TOTAL_FLIGHT_DURATION_MS, aggregateTime);
1594             proto.write(BroadcastStatsProto.COUNT, count);
1595             proto.write(BroadcastStatsProto.WAKEUP_COUNT, numWakeup);
1596             proto.write(BroadcastStatsProto.START_TIME_REALTIME, startTime);
1597             proto.write(BroadcastStatsProto.NESTING, nesting);
1598 
1599             proto.end(token);
1600         }
1601     }
1602 
1603     final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
1604             = new SparseArray<ArrayMap<String, BroadcastStats>>();
1605 
1606     int mNumDelayedAlarms = 0;
1607     long mTotalDelayTime = 0;
1608     long mMaxDelayTime = 0;
1609 
1610     @Override
onStart()1611     public void onStart() {
1612         mInjector.init();
1613         mMetricsHelper = new MetricsHelper(getContext(), mLock);
1614 
1615         mListenerDeathRecipient = new IBinder.DeathRecipient() {
1616             @Override
1617             public void binderDied() {
1618             }
1619 
1620             @Override
1621             public void binderDied(IBinder who) {
1622                 final IAlarmListener listener = IAlarmListener.Stub.asInterface(who);
1623                 removeImpl(null, listener);
1624             }
1625         };
1626 
1627         synchronized (mLock) {
1628             mHandler = new AlarmHandler();
1629             mConstants = new Constants();
1630 
1631             mAlarmStore = mConstants.LAZY_BATCHING ? new LazyAlarmStore()
1632                     : new BatchingAlarmStore();
1633             mAlarmStore.setAlarmClockRemovalListener(mAlarmClockUpdater);
1634 
1635             mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW);
1636             mAllowWhileIdleHistory = new AppWakeupHistory(INTERVAL_HOUR);
1637             mAllowWhileIdleCompatHistory = new AppWakeupHistory(INTERVAL_HOUR);
1638 
1639             mNextWakeup = mNextNonWakeup = 0;
1640 
1641             // We have to set current TimeZone info to kernel
1642             // because kernel doesn't keep this after reboot
1643             setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
1644 
1645             // Ensure that we're booting with a halfway sensible current time.  Use the
1646             // most recent of Build.TIME, the root file system's timestamp, and the
1647             // value of the ro.build.date.utc system property (which is in seconds).
1648             final long systemBuildTime = Long.max(
1649                     1000L * SystemProperties.getLong("ro.build.date.utc", -1L),
1650                     Long.max(Environment.getRootDirectory().lastModified(), Build.TIME));
1651             if (mInjector.getCurrentTimeMillis() < systemBuildTime) {
1652                 Slog.i(TAG, "Current time only " + mInjector.getCurrentTimeMillis()
1653                         + ", advancing to build time " + systemBuildTime);
1654                 mInjector.setKernelTime(systemBuildTime);
1655             }
1656 
1657             mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
1658             // Determine SysUI's uid
1659             mSystemUiUid = mInjector.getSystemUiUid(mPackageManagerInternal);
1660             if (mSystemUiUid <= 0) {
1661                 Slog.wtf(TAG, "SysUI package not found!");
1662             }
1663             mWakeLock = mInjector.getAlarmWakeLock();
1664 
1665             mTimeTickIntent = new Intent(Intent.ACTION_TIME_TICK).addFlags(
1666                     Intent.FLAG_RECEIVER_REGISTERED_ONLY
1667                             | Intent.FLAG_RECEIVER_FOREGROUND
1668                             | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
1669 
1670             mTimeTickTrigger = new IAlarmListener.Stub() {
1671                 @Override
1672                 public void doAlarm(final IAlarmCompleteListener callback) throws RemoteException {
1673                     if (DEBUG_BATCH) {
1674                         Slog.v(TAG, "Received TIME_TICK alarm; rescheduling");
1675                     }
1676 
1677                     // Via handler because dispatch invokes this within its lock.  OnAlarmListener
1678                     // takes care of this automatically, but we're using the direct internal
1679                     // interface here rather than that client-side wrapper infrastructure.
1680                     mHandler.post(() -> {
1681                         getContext().sendBroadcastAsUser(mTimeTickIntent, UserHandle.ALL);
1682 
1683                         try {
1684                             callback.alarmComplete(this);
1685                         } catch (RemoteException e) { /* local method call */ }
1686                     });
1687 
1688                     synchronized (mLock) {
1689                         mLastTickReceived = mInjector.getCurrentTimeMillis();
1690                     }
1691                     mClockReceiver.scheduleTimeTickEvent();
1692                 }
1693             };
1694 
1695             Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
1696             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
1697                     | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
1698             mDateChangeSender = PendingIntent.getBroadcastAsUser(getContext(), 0, intent,
1699                     Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
1700 
1701             mClockReceiver = mInjector.getClockReceiver(this);
1702             new ChargingReceiver();
1703             new InteractiveStateReceiver();
1704             new UninstallReceiver();
1705 
1706             if (mInjector.isAlarmDriverPresent()) {
1707                 AlarmThread waitThread = new AlarmThread();
1708                 waitThread.start();
1709             } else {
1710                 Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
1711             }
1712         }
1713         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
1714         publishLocalService(AlarmManagerInternal.class, new LocalService());
1715         publishBinderService(Context.ALARM_SERVICE, mService);
1716     }
1717 
refreshExactAlarmCandidates()1718     void refreshExactAlarmCandidates() {
1719         final String[] candidates = mLocalPermissionManager.getAppOpPermissionPackages(
1720                 Manifest.permission.SCHEDULE_EXACT_ALARM);
1721         final Set<Integer> newAppIds = new ArraySet<>(candidates.length);
1722         for (final String candidate : candidates) {
1723             final int uid = mPackageManagerInternal.getPackageUid(candidate,
1724                     PackageManager.MATCH_ANY_USER, USER_SYSTEM);
1725             if (uid > 0) {
1726                 newAppIds.add(UserHandle.getAppId(uid));
1727             }
1728         }
1729         final ArraySet<Integer> removed = new ArraySet<>(mExactAlarmCandidates);
1730         removed.removeAll(newAppIds);
1731         // This code is only called on package_added and boot. The set {removed} is only expected to
1732         // be non-empty when a package was updated and it removed the permission from its manifest.
1733         for (int i = 0; i < removed.size(); i++) {
1734             final int removedAppId = removed.valueAt(i);
1735             synchronized (mLock) {
1736                 Slog.i(TAG, "App id " + removedAppId + " lost SCHEDULE_EXACT_ALARM on update");
1737 
1738                 final Predicate<Alarm> whichAlarms = a -> {
1739                     if (UserHandle.getAppId(a.uid) != removedAppId || a.windowLength != 0) {
1740                         return false;
1741                     }
1742                     if (!isExactAlarmChangeEnabled(a.packageName, UserHandle.getUserId(a.uid))) {
1743                         return false;
1744                     }
1745                     return !isExemptFromExactAlarmPermission(a.uid);
1746                 };
1747                 removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_EXACT_PERMISSION_REVOKED);
1748             }
1749         }
1750         // No need to lock. Assignment is always atomic.
1751         mExactAlarmCandidates = Collections.unmodifiableSet(newAppIds);
1752     }
1753 
1754     @Override
onUserStarting(TargetUser user)1755     public void onUserStarting(TargetUser user) {
1756         super.onUserStarting(user);
1757         final int userId = user.getUserIdentifier();
1758         mHandler.post(() -> {
1759             for (final int appId : mExactAlarmCandidates) {
1760                 final int uid = UserHandle.getUid(userId, appId);
1761                 final AndroidPackage androidPackage = mPackageManagerInternal.getPackage(uid);
1762                 // It will be null if it is not installed on the starting user.
1763                 if (androidPackage != null) {
1764                     final int mode = mAppOps.checkOpNoThrow(AppOpsManager.OP_SCHEDULE_EXACT_ALARM,
1765                             uid, androidPackage.getPackageName());
1766                     synchronized (mLock) {
1767                         mLastOpScheduleExactAlarm.put(uid, mode);
1768                     }
1769                 }
1770             }
1771         });
1772     }
1773 
1774     @Override
onBootPhase(int phase)1775     public void onBootPhase(int phase) {
1776         if (phase == PHASE_SYSTEM_SERVICES_READY) {
1777             synchronized (mLock) {
1778                 mConstants.start();
1779 
1780                 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
1781 
1782                 mLocalDeviceIdleController =
1783                         LocalServices.getService(DeviceIdleInternal.class);
1784                 mUsageStatsManagerInternal =
1785                         LocalServices.getService(UsageStatsManagerInternal.class);
1786 
1787                 mAppStateTracker =
1788                         (AppStateTrackerImpl) LocalServices.getService(AppStateTracker.class);
1789                 mAppStateTracker.addListener(mForceAppStandbyListener);
1790 
1791                 mClockReceiver.scheduleTimeTickEvent();
1792                 mClockReceiver.scheduleDateChangedEvent();
1793             }
1794             IAppOpsService iAppOpsService = mInjector.getAppOpsService();
1795             try {
1796                 iAppOpsService.startWatchingMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM, null,
1797                         new IAppOpsCallback.Stub() {
1798                             @Override
1799                             public void opChanged(int op, int uid, String packageName)
1800                                     throws RemoteException {
1801                                 final int userId = UserHandle.getUserId(uid);
1802                                 if (op != AppOpsManager.OP_SCHEDULE_EXACT_ALARM
1803                                         || !isExactAlarmChangeEnabled(packageName, userId)) {
1804                                     return;
1805                                 }
1806 
1807                                 final boolean requested = mExactAlarmCandidates.contains(
1808                                         UserHandle.getAppId(uid));
1809                                 final boolean denyListed =
1810                                         mConstants.EXACT_ALARM_DENY_LIST.contains(packageName);
1811 
1812                                 final int newMode = mAppOps.checkOpNoThrow(
1813                                         AppOpsManager.OP_SCHEDULE_EXACT_ALARM, uid, packageName);
1814 
1815                                 final int oldMode;
1816                                 synchronized (mLock) {
1817                                     final int index = mLastOpScheduleExactAlarm.indexOfKey(uid);
1818                                     if (index < 0) {
1819                                         oldMode = AppOpsManager.opToDefaultMode(
1820                                                 AppOpsManager.OP_SCHEDULE_EXACT_ALARM);
1821                                         mLastOpScheduleExactAlarm.put(uid, newMode);
1822                                     } else {
1823                                         oldMode = mLastOpScheduleExactAlarm.valueAt(index);
1824                                         mLastOpScheduleExactAlarm.setValueAt(index, newMode);
1825                                     }
1826                                 }
1827 
1828                                 final boolean hadPermission = getScheduleExactAlarmState(requested,
1829                                         denyListed, oldMode);
1830                                 final boolean hasPermission = getScheduleExactAlarmState(requested,
1831                                         denyListed, newMode);
1832 
1833                                 if (hadPermission && !hasPermission) {
1834                                     mHandler.obtainMessage(AlarmHandler.REMOVE_EXACT_ALARMS,
1835                                             uid, 0, packageName).sendToTarget();
1836                                 } else if (!hadPermission && hasPermission) {
1837                                     sendScheduleExactAlarmPermissionStateChangedBroadcast(
1838                                             packageName, userId);
1839                                 }
1840                             }
1841                         });
1842             } catch (RemoteException e) {
1843             }
1844 
1845             mLocalPermissionManager = LocalServices.getService(
1846                     PermissionManagerServiceInternal.class);
1847             refreshExactAlarmCandidates();
1848 
1849             AppStandbyInternal appStandbyInternal =
1850                     LocalServices.getService(AppStandbyInternal.class);
1851             appStandbyInternal.addListener(new AppStandbyTracker());
1852 
1853             mMetricsHelper.registerPuller(() -> mAlarmStore);
1854         }
1855     }
1856 
1857     @Override
finalize()1858     protected void finalize() throws Throwable {
1859         try {
1860             mInjector.close();
1861         } finally {
1862             super.finalize();
1863         }
1864     }
1865 
setTimeImpl(long millis)1866     boolean setTimeImpl(long millis) {
1867         if (!mInjector.isAlarmDriverPresent()) {
1868             Slog.w(TAG, "Not setting time since no alarm driver is available.");
1869             return false;
1870         }
1871 
1872         synchronized (mLock) {
1873             final long currentTimeMillis = mInjector.getCurrentTimeMillis();
1874             mInjector.setKernelTime(millis);
1875             final TimeZone timeZone = TimeZone.getDefault();
1876             final int currentTzOffset = timeZone.getOffset(currentTimeMillis);
1877             final int newTzOffset = timeZone.getOffset(millis);
1878             if (currentTzOffset != newTzOffset) {
1879                 Slog.i(TAG, "Timezone offset has changed, updating kernel timezone");
1880                 mInjector.setKernelTimezone(-(newTzOffset / 60000));
1881             }
1882             // The native implementation of setKernelTime can return -1 even when the kernel
1883             // time was set correctly, so assume setting kernel time was successful and always
1884             // return true.
1885             return true;
1886         }
1887     }
1888 
setTimeZoneImpl(String tz)1889     void setTimeZoneImpl(String tz) {
1890         if (TextUtils.isEmpty(tz)) {
1891             return;
1892         }
1893 
1894         TimeZone zone = TimeZone.getTimeZone(tz);
1895         // Prevent reentrant calls from stepping on each other when writing
1896         // the time zone property
1897         boolean timeZoneWasChanged = false;
1898         synchronized (this) {
1899             String current = SystemProperties.get(TIMEZONE_PROPERTY);
1900             if (current == null || !current.equals(zone.getID())) {
1901                 if (localLOGV) {
1902                     Slog.v(TAG, "timezone changed: " + current + ", new=" + zone.getID());
1903                 }
1904                 timeZoneWasChanged = true;
1905                 SystemProperties.set(TIMEZONE_PROPERTY, zone.getID());
1906             }
1907 
1908             // Update the kernel timezone information
1909             // Kernel tracks time offsets as 'minutes west of GMT'
1910             int gmtOffset = zone.getOffset(mInjector.getCurrentTimeMillis());
1911             mInjector.setKernelTimezone(-(gmtOffset / 60000));
1912         }
1913 
1914         TimeZone.setDefault(null);
1915 
1916         if (timeZoneWasChanged) {
1917             // Don't wait for broadcasts to update our midnight alarm
1918             mClockReceiver.scheduleDateChangedEvent();
1919 
1920             // And now let everyone else know
1921             Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
1922             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
1923                     | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
1924                     | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
1925                     | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
1926             intent.putExtra(Intent.EXTRA_TIMEZONE, zone.getID());
1927             mOptsTimeBroadcast.setTemporaryAppAllowlist(
1928                     mActivityManagerInternal.getBootTimeTempAllowListDuration(),
1929                     TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
1930                     PowerExemptionManager.REASON_TIMEZONE_CHANGED, "");
1931             getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
1932                     null /* receiverPermission */, mOptsTimeBroadcast.toBundle());
1933         }
1934     }
1935 
removeImpl(PendingIntent operation, IAlarmListener listener)1936     void removeImpl(PendingIntent operation, IAlarmListener listener) {
1937         synchronized (mLock) {
1938             removeLocked(operation, listener, REMOVE_REASON_UNDEFINED);
1939         }
1940     }
1941 
setImpl(int type, long triggerAtTime, long windowLength, long interval, PendingIntent operation, IAlarmListener directReceiver, String listenerTag, int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage, Bundle idleOptions, int exactAllowReason)1942     void setImpl(int type, long triggerAtTime, long windowLength, long interval,
1943             PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
1944             int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
1945             int callingUid, String callingPackage, Bundle idleOptions, int exactAllowReason) {
1946         if ((operation == null && directReceiver == null)
1947                 || (operation != null && directReceiver != null)) {
1948             Slog.w(TAG, "Alarms must either supply a PendingIntent or an AlarmReceiver");
1949             // NB: previous releases failed silently here, so we are continuing to do the same
1950             // rather than throw an IllegalArgumentException.
1951             return;
1952         }
1953 
1954         if (directReceiver != null) {
1955             try {
1956                 directReceiver.asBinder().linkToDeath(mListenerDeathRecipient, 0);
1957             } catch (RemoteException e) {
1958                 Slog.w(TAG, "Dropping unreachable alarm listener " + listenerTag);
1959                 return;
1960             }
1961         }
1962 
1963         // Sanity check the recurrence interval.  This will catch people who supply
1964         // seconds when the API expects milliseconds, or apps trying shenanigans
1965         // around intentional period overflow, etc.
1966         final long minInterval = mConstants.MIN_INTERVAL;
1967         if (interval > 0 && interval < minInterval) {
1968             Slog.w(TAG, "Suspiciously short interval " + interval
1969                     + " millis; expanding to " + (minInterval / 1000)
1970                     + " seconds");
1971             interval = minInterval;
1972         } else if (interval > mConstants.MAX_INTERVAL) {
1973             Slog.w(TAG, "Suspiciously long interval " + interval
1974                     + " millis; clamping");
1975             interval = mConstants.MAX_INTERVAL;
1976         }
1977 
1978         if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
1979             throw new IllegalArgumentException("Invalid alarm type " + type);
1980         }
1981 
1982         if (triggerAtTime < 0) {
1983             final long what = Binder.getCallingPid();
1984             Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
1985                     + " pid=" + what);
1986             triggerAtTime = 0;
1987         }
1988 
1989         final long nowElapsed = mInjector.getElapsedRealtime();
1990         final long nominalTrigger = convertToElapsed(triggerAtTime, type);
1991         // Try to prevent spamming by making sure apps aren't firing alarms in the immediate future
1992         final long minTrigger = nowElapsed
1993                 + (UserHandle.isCore(callingUid) ? 0L : mConstants.MIN_FUTURITY);
1994         final long triggerElapsed = Math.max(minTrigger, nominalTrigger);
1995 
1996         final long maxElapsed;
1997         if (windowLength == 0) {
1998             maxElapsed = triggerElapsed;
1999         } else if (windowLength < 0) {
2000             maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
2001             // Fix this window in place, so that as time approaches we don't collapse it.
2002             windowLength = maxElapsed - triggerElapsed;
2003         } else {
2004             // The window was explicitly requested. Snap it to allowable limits.
2005             final long minAllowedWindow = getMinimumAllowedWindow(nowElapsed, triggerElapsed);
2006             if (windowLength > INTERVAL_DAY) {
2007                 Slog.w(TAG, "Window length " + windowLength + "ms too long; limiting to 1 day");
2008                 windowLength = INTERVAL_DAY;
2009             } else if ((flags & FLAG_PRIORITIZE) == 0 && windowLength < minAllowedWindow) {
2010                 // Prioritized alarms are exempt from minimum window limits.
2011                 if (!isExemptFromMinWindowRestrictions(callingUid) && CompatChanges.isChangeEnabled(
2012                         AlarmManager.ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS, callingPackage,
2013                         UserHandle.getUserHandleForUid(callingUid))) {
2014                     Slog.w(TAG, "Window length " + windowLength + "ms too short; expanding to "
2015                             + minAllowedWindow + "ms.");
2016                     windowLength = minAllowedWindow;
2017                 }
2018             }
2019             maxElapsed = triggerElapsed + windowLength;
2020         }
2021         synchronized (mLock) {
2022             if (DEBUG_BATCH) {
2023                 Slog.v(TAG, "set(" + operation + ") : type=" + type
2024                         + " triggerAtTime=" + triggerAtTime + " win=" + windowLength
2025                         + " tElapsed=" + triggerElapsed + " maxElapsed=" + maxElapsed
2026                         + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
2027             }
2028             if (mAlarmsPerUid.get(callingUid, 0) >= mConstants.MAX_ALARMS_PER_UID) {
2029                 final String errorMsg =
2030                         "Maximum limit of concurrent alarms " + mConstants.MAX_ALARMS_PER_UID
2031                                 + " reached for uid: " + UserHandle.formatUid(callingUid)
2032                                 + ", callingPackage: " + callingPackage;
2033                 Slog.w(TAG, errorMsg);
2034                 throw new IllegalStateException(errorMsg);
2035             }
2036             setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, interval, operation,
2037                     directReceiver, listenerTag, flags, workSource, alarmClock, callingUid,
2038                     callingPackage, idleOptions, exactAllowReason);
2039         }
2040     }
2041 
setImplLocked(int type, long when, long whenElapsed, long windowLength, long interval, PendingIntent operation, IAlarmListener directReceiver, String listenerTag, int flags, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage, Bundle idleOptions, int exactAllowReason)2042     private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
2043             long interval, PendingIntent operation, IAlarmListener directReceiver,
2044             String listenerTag, int flags, WorkSource workSource,
2045             AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage,
2046             Bundle idleOptions, int exactAllowReason) {
2047         final Alarm a = new Alarm(type, when, whenElapsed, windowLength, interval,
2048                 operation, directReceiver, listenerTag, workSource, flags, alarmClock,
2049                 callingUid, callingPackage, idleOptions, exactAllowReason);
2050         if (mActivityManagerInternal.isAppStartModeDisabled(callingUid, callingPackage)) {
2051             Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
2052                     + " -- package not allowed to start");
2053             return;
2054         }
2055         final int callerProcState = mActivityManagerInternal.getUidProcessState(callingUid);
2056         removeLocked(operation, directReceiver, REMOVE_REASON_UNDEFINED);
2057         incrementAlarmCount(a.uid);
2058         setImplLocked(a);
2059         MetricsHelper.pushAlarmScheduled(a, callerProcState);
2060     }
2061 
2062     /**
2063      * Returns the maximum alarms that an app in the specified bucket can receive in a rolling time
2064      * window given by {@link Constants#APP_STANDBY_WINDOW}
2065      */
2066     @VisibleForTesting
getQuotaForBucketLocked(int bucket)2067     int getQuotaForBucketLocked(int bucket) {
2068         final int index;
2069         if (bucket <= UsageStatsManager.STANDBY_BUCKET_ACTIVE) {
2070             index = ACTIVE_INDEX;
2071         } else if (bucket <= UsageStatsManager.STANDBY_BUCKET_WORKING_SET) {
2072             index = WORKING_INDEX;
2073         } else if (bucket <= UsageStatsManager.STANDBY_BUCKET_FREQUENT) {
2074             index = FREQUENT_INDEX;
2075         } else if (bucket < UsageStatsManager.STANDBY_BUCKET_NEVER) {
2076             index = RARE_INDEX;
2077         } else {
2078             index = NEVER_INDEX;
2079         }
2080         return mConstants.APP_STANDBY_QUOTAS[index];
2081     }
2082 
2083     /**
2084      * An alarm with {@link AlarmManager#FLAG_IDLE_UNTIL} is a special alarm that will put the
2085      * system into idle until it goes off. We need to pull it earlier if there are existing alarms
2086      * that have requested to bring us out of idle at an earlier time.
2087      *
2088      * @param alarm The alarm to adjust
2089      * @return true if the alarm delivery time was updated.
2090      */
adjustIdleUntilTime(Alarm alarm)2091     private boolean adjustIdleUntilTime(Alarm alarm) {
2092         if ((alarm.flags & AlarmManager.FLAG_IDLE_UNTIL) == 0) {
2093             return false;
2094         }
2095         final boolean changedBeforeFuzz = restoreRequestedTime(alarm);
2096         if (mNextWakeFromIdle == null) {
2097             // No need to change anything in the absence of a wake-from-idle request.
2098             return changedBeforeFuzz;
2099         }
2100         final long upcomingWakeFromIdle = mNextWakeFromIdle.getWhenElapsed();
2101         // Add fuzz to make the alarm go off some time before the next upcoming wake-from-idle, as
2102         // these alarms are usually wall-clock aligned.
2103         if (alarm.getWhenElapsed() < (upcomingWakeFromIdle - mConstants.MIN_DEVICE_IDLE_FUZZ)) {
2104             // No need to fuzz as this is already earlier than the coming wake-from-idle.
2105             return changedBeforeFuzz;
2106         }
2107         final long nowElapsed = mInjector.getElapsedRealtime();
2108         final long futurity = upcomingWakeFromIdle - nowElapsed;
2109 
2110         if (futurity <= mConstants.MIN_DEVICE_IDLE_FUZZ) {
2111             // No point in fuzzing as the minimum fuzz will take the time in the past.
2112             alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, nowElapsed);
2113         } else {
2114             final ThreadLocalRandom random = ThreadLocalRandom.current();
2115             final long upperBoundExcl = Math.min(mConstants.MAX_DEVICE_IDLE_FUZZ, futurity) + 1;
2116             final long fuzz = random.nextLong(mConstants.MIN_DEVICE_IDLE_FUZZ, upperBoundExcl);
2117             alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, upcomingWakeFromIdle - fuzz);
2118         }
2119         return true;
2120     }
2121 
2122     /**
2123      * Adjusts the delivery time of the alarm based on battery saver rules.
2124      *
2125      * @param alarm The alarm to adjust
2126      * @return {@code true} if the alarm delivery time was updated.
2127      */
adjustDeliveryTimeBasedOnBatterySaver(Alarm alarm)2128     private boolean adjustDeliveryTimeBasedOnBatterySaver(Alarm alarm) {
2129         final long nowElapsed = mInjector.getElapsedRealtime();
2130         if (isExemptFromBatterySaver(alarm)) {
2131             return false;
2132         }
2133 
2134         if (mAppStateTracker == null || !mAppStateTracker.areAlarmsRestrictedByBatterySaver(
2135                 alarm.creatorUid, alarm.sourcePackage)) {
2136             return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, nowElapsed);
2137         }
2138 
2139         final long batterySaverPolicyElapsed;
2140         if ((alarm.flags & (FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED)) != 0) {
2141             // Unrestricted.
2142             batterySaverPolicyElapsed = nowElapsed;
2143         } else if (isAllowedWhileIdleRestricted(alarm)) {
2144             // Allowed but limited.
2145             final int userId = UserHandle.getUserId(alarm.creatorUid);
2146             final int quota;
2147             final long window;
2148             final AppWakeupHistory history;
2149             if ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0) {
2150                 quota = mConstants.ALLOW_WHILE_IDLE_QUOTA;
2151                 window = mConstants.ALLOW_WHILE_IDLE_WINDOW;
2152                 history = mAllowWhileIdleHistory;
2153             } else {
2154                 quota = mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA;
2155                 window = mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW;
2156                 history = mAllowWhileIdleCompatHistory;
2157             }
2158             final int dispatchesInHistory = history.getTotalWakeupsInWindow(
2159                     alarm.sourcePackage, userId);
2160             if (dispatchesInHistory < quota) {
2161                 // fine to go out immediately.
2162                 batterySaverPolicyElapsed = nowElapsed;
2163             } else {
2164                 batterySaverPolicyElapsed = history.getNthLastWakeupForPackage(
2165                         alarm.sourcePackage, userId, quota) + window;
2166             }
2167         } else if ((alarm.flags & FLAG_PRIORITIZE) != 0) {
2168             final long lastDispatch = mLastPriorityAlarmDispatch.get(alarm.creatorUid, 0);
2169             batterySaverPolicyElapsed = (lastDispatch == 0)
2170                     ? nowElapsed
2171                     : lastDispatch + mConstants.PRIORITY_ALARM_DELAY;
2172         } else {
2173             // Not allowed.
2174             batterySaverPolicyElapsed = nowElapsed + INDEFINITE_DELAY;
2175         }
2176         return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, batterySaverPolicyElapsed);
2177     }
2178 
2179     /**
2180      * Returns {@code true} if the given alarm has the flag
2181      * {@link AlarmManager#FLAG_ALLOW_WHILE_IDLE} or
2182      * {@link AlarmManager#FLAG_ALLOW_WHILE_IDLE_COMPAT}
2183      *
2184      */
isAllowedWhileIdleRestricted(Alarm a)2185     private static boolean isAllowedWhileIdleRestricted(Alarm a) {
2186         return (a.flags & (FLAG_ALLOW_WHILE_IDLE | FLAG_ALLOW_WHILE_IDLE_COMPAT)) != 0;
2187     }
2188 
2189     /**
2190      * Adjusts the delivery time of the alarm based on device_idle (doze) rules.
2191      *
2192      * @param alarm The alarm to adjust
2193      * @return {@code true} if the alarm delivery time was updated.
2194      */
adjustDeliveryTimeBasedOnDeviceIdle(Alarm alarm)2195     private boolean adjustDeliveryTimeBasedOnDeviceIdle(Alarm alarm) {
2196         final long nowElapsed = mInjector.getElapsedRealtime();
2197         if (mPendingIdleUntil == null || mPendingIdleUntil == alarm) {
2198             return alarm.setPolicyElapsed(DEVICE_IDLE_POLICY_INDEX, nowElapsed);
2199         }
2200 
2201         final long deviceIdlePolicyTime;
2202         if ((alarm.flags & (FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED | FLAG_WAKE_FROM_IDLE)) != 0) {
2203             // Unrestricted.
2204             deviceIdlePolicyTime = nowElapsed;
2205         } else if (isAllowedWhileIdleRestricted(alarm)) {
2206             // Allowed but limited.
2207             final int userId = UserHandle.getUserId(alarm.creatorUid);
2208             final int quota;
2209             final long window;
2210             final AppWakeupHistory history;
2211             if ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0) {
2212                 quota = mConstants.ALLOW_WHILE_IDLE_QUOTA;
2213                 window = mConstants.ALLOW_WHILE_IDLE_WINDOW;
2214                 history = mAllowWhileIdleHistory;
2215             } else {
2216                 quota = mConstants.ALLOW_WHILE_IDLE_COMPAT_QUOTA;
2217                 window = mConstants.ALLOW_WHILE_IDLE_COMPAT_WINDOW;
2218                 history = mAllowWhileIdleCompatHistory;
2219             }
2220             final int dispatchesInHistory = history.getTotalWakeupsInWindow(
2221                     alarm.sourcePackage, userId);
2222             if (dispatchesInHistory < quota) {
2223                 // fine to go out immediately.
2224                 deviceIdlePolicyTime = nowElapsed;
2225             } else {
2226                 final long whenInQuota = history.getNthLastWakeupForPackage(
2227                         alarm.sourcePackage, userId, quota) + window;
2228                 deviceIdlePolicyTime = Math.min(whenInQuota, mPendingIdleUntil.getWhenElapsed());
2229             }
2230         } else if ((alarm.flags & FLAG_PRIORITIZE) != 0) {
2231             final long lastDispatch = mLastPriorityAlarmDispatch.get(alarm.creatorUid, 0);
2232             final long whenAllowed = (lastDispatch == 0)
2233                     ? nowElapsed
2234                     : lastDispatch + mConstants.PRIORITY_ALARM_DELAY;
2235             deviceIdlePolicyTime = Math.min(whenAllowed, mPendingIdleUntil.getWhenElapsed());
2236         } else {
2237             // Not allowed.
2238             deviceIdlePolicyTime = mPendingIdleUntil.getWhenElapsed();
2239         }
2240         return alarm.setPolicyElapsed(DEVICE_IDLE_POLICY_INDEX, deviceIdlePolicyTime);
2241     }
2242 
2243     /**
2244      * Adjusts the alarm's policy time for app_standby.
2245      *
2246      * @param alarm The alarm to update.
2247      * @return {@code true} if the actual delivery time of the given alarm was updated due to
2248      *         adjustments made in this call.
2249      */
adjustDeliveryTimeBasedOnBucketLocked(Alarm alarm)2250     private boolean adjustDeliveryTimeBasedOnBucketLocked(Alarm alarm) {
2251         final long nowElapsed = mInjector.getElapsedRealtime();
2252         if (isExemptFromAppStandby(alarm) || mAppStandbyParole) {
2253             return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, nowElapsed);
2254         }
2255 
2256         final String sourcePackage = alarm.sourcePackage;
2257         final int sourceUserId = UserHandle.getUserId(alarm.creatorUid);
2258         final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket(
2259                 sourcePackage, sourceUserId, nowElapsed);
2260 
2261         final int wakeupsInWindow = mAppWakeupHistory.getTotalWakeupsInWindow(sourcePackage,
2262                 sourceUserId);
2263         if (standbyBucket == UsageStatsManager.STANDBY_BUCKET_RESTRICTED) {
2264             // Special case because it's 1/day instead of 1/hour.
2265             // AppWakeupHistory doesn't delete old wakeup times until a new one is logged, so we
2266             // should always have the last wakeup available.
2267             if (wakeupsInWindow > 0) {
2268                 final long lastWakeupTime = mAppWakeupHistory.getNthLastWakeupForPackage(
2269                         sourcePackage, sourceUserId, mConstants.APP_STANDBY_RESTRICTED_QUOTA);
2270                 if ((nowElapsed - lastWakeupTime) < mConstants.APP_STANDBY_RESTRICTED_WINDOW) {
2271                     return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX,
2272                             lastWakeupTime + mConstants.APP_STANDBY_RESTRICTED_WINDOW);
2273                 }
2274             }
2275         } else {
2276             final int quotaForBucket = getQuotaForBucketLocked(standbyBucket);
2277             if (wakeupsInWindow >= quotaForBucket) {
2278                 final long minElapsed;
2279                 if (quotaForBucket <= 0) {
2280                     // Just keep deferring indefinitely till the quota changes.
2281                     minElapsed = nowElapsed + INDEFINITE_DELAY;
2282                 } else {
2283                     // Suppose the quota for window was q, and the qth last delivery time for this
2284                     // package was t(q) then the next delivery must be after t(q) + <window_size>.
2285                     final long t = mAppWakeupHistory.getNthLastWakeupForPackage(
2286                             sourcePackage, sourceUserId, quotaForBucket);
2287                     minElapsed = t + mConstants.APP_STANDBY_WINDOW;
2288                 }
2289                 return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, minElapsed);
2290             }
2291         }
2292         // wakeupsInWindow are less than the permitted quota, hence no deferring is needed.
2293         return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, nowElapsed);
2294     }
2295 
setImplLocked(Alarm a)2296     private void setImplLocked(Alarm a) {
2297         if ((a.flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) {
2298             adjustIdleUntilTime(a);
2299 
2300             if (RECORD_DEVICE_IDLE_ALARMS) {
2301                 IdleDispatchEntry ent = new IdleDispatchEntry();
2302                 ent.uid = a.uid;
2303                 ent.pkg = a.sourcePackage;
2304                 ent.tag = a.statsTag;
2305                 ent.op = "START IDLE";
2306                 ent.elapsedRealtime = mInjector.getElapsedRealtime();
2307                 ent.argRealtime = a.getWhenElapsed();
2308                 mAllowWhileIdleDispatches.add(ent);
2309             }
2310             if ((mPendingIdleUntil != a) && (mPendingIdleUntil != null)) {
2311                 Slog.wtfStack(TAG, "setImplLocked: idle until changed from " + mPendingIdleUntil
2312                         + " to " + a);
2313                 mAlarmStore.remove(mPendingIdleUntil::equals);
2314             }
2315             mPendingIdleUntil = a;
2316             mAlarmStore.updateAlarmDeliveries(alarm -> adjustDeliveryTimeBasedOnDeviceIdle(alarm));
2317         } else if (mPendingIdleUntil != null) {
2318             adjustDeliveryTimeBasedOnDeviceIdle(a);
2319         }
2320         if ((a.flags & FLAG_WAKE_FROM_IDLE) != 0) {
2321             if (mNextWakeFromIdle == null || mNextWakeFromIdle.getWhenElapsed()
2322                     > a.getWhenElapsed()) {
2323                 mNextWakeFromIdle = a;
2324                 // If this wake from idle is earlier than whatever was previously scheduled,
2325                 // and we are currently idling, then the idle-until time needs to be updated.
2326                 if (mPendingIdleUntil != null) {
2327                     final boolean updated = mAlarmStore.updateAlarmDeliveries(
2328                             alarm -> (alarm == mPendingIdleUntil) && adjustIdleUntilTime(alarm));
2329                     if (updated) {
2330                         // idle-until got updated, so also update all alarms not allowed while idle.
2331                         mAlarmStore.updateAlarmDeliveries(
2332                                 alarm -> adjustDeliveryTimeBasedOnDeviceIdle(alarm));
2333                     }
2334                 }
2335             }
2336         }
2337         if (a.alarmClock != null) {
2338             mNextAlarmClockMayChange = true;
2339         }
2340         adjustDeliveryTimeBasedOnBatterySaver(a);
2341         adjustDeliveryTimeBasedOnBucketLocked(a);
2342         mAlarmStore.add(a);
2343         rescheduleKernelAlarmsLocked();
2344         updateNextAlarmClockLocked();
2345     }
2346 
2347     /**
2348      * System-process internal API
2349      */
2350     private final class LocalService implements AlarmManagerInternal {
2351         @Override
isIdling()2352         public boolean isIdling() {
2353             return isIdlingImpl();
2354         }
2355 
2356         @Override
removeAlarmsForUid(int uid)2357         public void removeAlarmsForUid(int uid) {
2358             synchronized (mLock) {
2359                 removeLocked(uid, REMOVE_REASON_DATA_CLEARED);
2360             }
2361         }
2362 
2363         @Override
remove(PendingIntent pi)2364         public void remove(PendingIntent pi) {
2365             mHandler.obtainMessage(AlarmHandler.REMOVE_FOR_CANCELED, pi).sendToTarget();
2366         }
2367 
2368         @Override
hasScheduleExactAlarm(String packageName, int uid)2369         public boolean hasScheduleExactAlarm(String packageName, int uid) {
2370             return hasScheduleExactAlarmInternal(packageName, uid);
2371         }
2372 
2373         @Override
registerInFlightListener(InFlightListener callback)2374         public void registerInFlightListener(InFlightListener callback) {
2375             synchronized (mLock) {
2376                 mInFlightListeners.add(callback);
2377             }
2378         }
2379     }
2380 
getScheduleExactAlarmState(boolean requested, boolean denyListed, int appOpMode)2381     private static boolean getScheduleExactAlarmState(boolean requested, boolean denyListed,
2382             int appOpMode) {
2383         if (!requested) {
2384             return false;
2385         }
2386         if (appOpMode == AppOpsManager.MODE_DEFAULT) {
2387             return !denyListed;
2388         }
2389         return appOpMode == AppOpsManager.MODE_ALLOWED;
2390     }
2391 
hasScheduleExactAlarmInternal(String packageName, int uid)2392     boolean hasScheduleExactAlarmInternal(String packageName, int uid) {
2393         // Not using getScheduleExactAlarmState as this can avoid some calls to AppOpsService.
2394         // Not using #mLastOpScheduleExactAlarm as it may contain stale values.
2395         // No locking needed as all internal containers being queried are immutable.
2396 
2397         final long start = mStatLogger.getTime();
2398         final boolean hasPermission;
2399         if (!mExactAlarmCandidates.contains(UserHandle.getAppId(uid))) {
2400             hasPermission = false;
2401         } else if (!isExactAlarmChangeEnabled(packageName, UserHandle.getUserId(uid))) {
2402             hasPermission = false;
2403         } else {
2404             final int mode = mAppOps.checkOpNoThrow(AppOpsManager.OP_SCHEDULE_EXACT_ALARM, uid,
2405                     packageName);
2406             if (mode == AppOpsManager.MODE_DEFAULT) {
2407                 hasPermission = !mConstants.EXACT_ALARM_DENY_LIST.contains(packageName);
2408             } else {
2409                 hasPermission = (mode == AppOpsManager.MODE_ALLOWED);
2410             }
2411         }
2412         mStatLogger.logDurationStat(Stats.HAS_SCHEDULE_EXACT_ALARM, start);
2413         return hasPermission;
2414     }
2415 
2416     /**
2417      * Returns true if the given uid can set window to be as small as it wants.
2418      */
isExemptFromMinWindowRestrictions(int uid)2419     boolean isExemptFromMinWindowRestrictions(int uid) {
2420         return isExemptFromExactAlarmPermission(uid);
2421     }
2422 
2423     /**
2424      * Returns true if the given uid does not require SCHEDULE_EXACT_ALARM to set exact,
2425      * allow-while-idle alarms.
2426      * Note: It is ok to call this method without the lock {@link #mLock} held.
2427      */
isExemptFromExactAlarmPermission(int uid)2428     boolean isExemptFromExactAlarmPermission(int uid) {
2429         return (UserHandle.isSameApp(mSystemUiUid, uid)
2430                 || UserHandle.isCore(uid)
2431                 || mLocalDeviceIdleController == null
2432                 || mLocalDeviceIdleController.isAppOnWhitelist(UserHandle.getAppId(uid)));
2433     }
2434 
2435     /**
2436      * Public-facing binder interface
2437      */
2438     private final IBinder mService = new IAlarmManager.Stub() {
2439         @Override
2440         public void set(String callingPackage,
2441                 int type, long triggerAtTime, long windowLength, long interval, int flags,
2442                 PendingIntent operation, IAlarmListener directReceiver, String listenerTag,
2443                 WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock) {
2444             final int callingUid = mInjector.getCallingUid();
2445             final int callingUserId = UserHandle.getUserId(callingUid);
2446 
2447             // make sure the caller is not lying about which package should be blamed for
2448             // wakelock time spent in alarm delivery
2449             if (callingUid != mPackageManagerInternal.getPackageUid(callingPackage, 0,
2450                     callingUserId)) {
2451                 throw new SecurityException("Package " + callingPackage
2452                         + " does not belong to the calling uid " + callingUid);
2453             }
2454 
2455             // Repeating alarms must use PendingIntent, not direct listener
2456             if (interval != 0 && directReceiver != null) {
2457                 throw new IllegalArgumentException("Repeating alarms cannot use AlarmReceivers");
2458             }
2459 
2460             if (workSource != null) {
2461                 getContext().enforcePermission(
2462                         android.Manifest.permission.UPDATE_DEVICE_STATS,
2463                         Binder.getCallingPid(), callingUid, "AlarmManager.set");
2464             }
2465 
2466             if ((flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) {
2467                 // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
2468                 // manager when to come out of idle mode, which is only for DeviceIdleController.
2469                 if (callingUid != Process.SYSTEM_UID) {
2470                     // TODO (b/169463012): Throw instead of tolerating this mistake.
2471                     flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
2472                 } else {
2473                     // Do not support windows for idle-until alarms.
2474                     windowLength = 0;
2475                 }
2476             }
2477 
2478             // Remove flags reserved for the service, we will apply those later as appropriate.
2479             flags &= ~(FLAG_WAKE_FROM_IDLE | FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
2480                     | FLAG_ALLOW_WHILE_IDLE_COMPAT);
2481 
2482             // If this alarm is for an alarm clock, then it must be exact and we will
2483             // use it to wake early from idle if needed.
2484             if (alarmClock != null) {
2485                 flags |= FLAG_WAKE_FROM_IDLE;
2486                 windowLength = 0;
2487 
2488             // If the caller is a core system component or on the user's allowlist, and not calling
2489             // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
2490             // This means we will allow these alarms to go off as normal even while idle, with no
2491             // timing restrictions.
2492             } else if (workSource == null && (UserHandle.isCore(callingUid)
2493                     || UserHandle.isSameApp(callingUid, mSystemUiUid)
2494                     || ((mAppStateTracker != null)
2495                     && mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) {
2496                 flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
2497                 flags &= ~(FLAG_ALLOW_WHILE_IDLE | FLAG_PRIORITIZE);
2498             }
2499 
2500             final boolean allowWhileIdle = (flags & FLAG_ALLOW_WHILE_IDLE) != 0;
2501             final boolean exact = (windowLength == 0);
2502 
2503             // Make sure the caller is allowed to use the requested kind of alarm, and also
2504             // decide what quota and broadcast options to use.
2505             boolean allowListed = false;    // For logging the reason.
2506             boolean changeDisabled = false; // For logging the reason.
2507             Bundle idleOptions = null;
2508             if ((flags & FLAG_PRIORITIZE) != 0) {
2509                 getContext().enforcePermission(
2510                         Manifest.permission.SCHEDULE_PRIORITIZED_ALARM,
2511                         Binder.getCallingPid(), callingUid, "AlarmManager.setPrioritized");
2512                 // The API doesn't allow using both together.
2513                 flags &= ~FLAG_ALLOW_WHILE_IDLE;
2514                 // Prioritized alarms don't need any extra permission to be exact.
2515             } else if (exact || allowWhileIdle) {
2516                 final boolean needsPermission;
2517                 boolean lowerQuota;
2518                 if (isExactAlarmChangeEnabled(callingPackage, callingUserId)) {
2519                     needsPermission = exact;
2520                     lowerQuota = !exact;
2521                     idleOptions = exact ? mOptsWithFgs.toBundle() : mOptsWithoutFgs.toBundle();
2522                 } else {
2523                     changeDisabled = true;
2524                     needsPermission = false;
2525                     lowerQuota = allowWhileIdle;
2526                     idleOptions = allowWhileIdle ? mOptsWithFgs.toBundle() : null;
2527                 }
2528                 if (needsPermission && !hasScheduleExactAlarmInternal(callingPackage, callingUid)) {
2529                     if (!isExemptFromExactAlarmPermission(callingUid)) {
2530                         final String errorMessage = "Caller " + callingPackage + " needs to hold "
2531                                 + Manifest.permission.SCHEDULE_EXACT_ALARM + " to set "
2532                                 + "exact alarms.";
2533                         if (mConstants.CRASH_NON_CLOCK_APPS) {
2534                             throw new SecurityException(errorMessage);
2535                         } else {
2536                             Slog.wtf(TAG, errorMessage);
2537                         }
2538                     } else {
2539                         allowListed = true;
2540                     }
2541                     // If the app is on the full system power allow-list (not except-idle), or the
2542                     // user-elected allow-list, or we're in a soft failure mode, we still allow the
2543                     // alarms.
2544                     // In both cases, ALLOW_WHILE_IDLE alarms get a lower quota equivalent to what
2545                     // pre-S apps got. Note that user-allow-listed apps don't use the flag
2546                     // ALLOW_WHILE_IDLE.
2547                     // We grant temporary allow-list to allow-while-idle alarms but without FGS
2548                     // capability. AlarmClock alarms do not get the temporary allow-list. This is
2549                     // consistent with pre-S behavior. Note that apps that are in either of the
2550                     // power-save allow-lists do not need it.
2551                     idleOptions = allowWhileIdle ? mOptsWithoutFgs.toBundle() : null;
2552                     lowerQuota = allowWhileIdle;
2553                 }
2554                 if (lowerQuota) {
2555                     flags &= ~FLAG_ALLOW_WHILE_IDLE;
2556                     flags |= FLAG_ALLOW_WHILE_IDLE_COMPAT;
2557                 }
2558             }
2559             final int exactAllowReason;
2560             if (exact) {
2561                 // If this is an exact time alarm, then it can't be batched with other alarms.
2562                 flags |= AlarmManager.FLAG_STANDALONE;
2563 
2564                 if (changeDisabled) {
2565                     exactAllowReason = EXACT_ALLOW_REASON_COMPAT;
2566                 } else if (allowListed) {
2567                     exactAllowReason = EXACT_ALLOW_REASON_ALLOW_LIST;
2568                 } else {
2569                     exactAllowReason = EXACT_ALLOW_REASON_PERMISSION;
2570                 }
2571             } else {
2572                 exactAllowReason = EXACT_ALLOW_REASON_NOT_APPLICABLE;
2573             }
2574 
2575             setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
2576                     listenerTag, flags, workSource, alarmClock, callingUid, callingPackage,
2577                     idleOptions, exactAllowReason);
2578         }
2579 
2580         @Override
2581         public boolean canScheduleExactAlarms(String packageName) {
2582             final int callingUid = mInjector.getCallingUid();
2583             final int userId = UserHandle.getUserId(callingUid);
2584             final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
2585             if (callingUid != packageUid) {
2586                 throw new SecurityException("Uid " + callingUid
2587                         + " cannot query canScheduleExactAlarms for package " + packageName);
2588             }
2589             if (!isExactAlarmChangeEnabled(packageName, userId)) {
2590                 return true;
2591             }
2592             return isExemptFromExactAlarmPermission(packageUid)
2593                     || hasScheduleExactAlarmInternal(packageName, packageUid);
2594         }
2595 
2596         @Override
2597         public boolean hasScheduleExactAlarm(String packageName, int userId) {
2598             final int callingUid = mInjector.getCallingUid();
2599             if (UserHandle.getUserId(callingUid) != userId) {
2600                 getContext().enforceCallingOrSelfPermission(
2601                         Manifest.permission.INTERACT_ACROSS_USERS_FULL, "hasScheduleExactAlarm");
2602             }
2603             final int uid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
2604             if (callingUid != uid && !UserHandle.isCore(callingUid)) {
2605                 throw new SecurityException("Uid " + callingUid
2606                         + " cannot query hasScheduleExactAlarm for package " + packageName);
2607             }
2608             return (uid > 0) ? hasScheduleExactAlarmInternal(packageName, uid) : false;
2609         }
2610 
2611         @Override
2612         public boolean setTime(long millis) {
2613             getContext().enforceCallingOrSelfPermission(
2614                     "android.permission.SET_TIME",
2615                     "setTime");
2616 
2617             return setTimeImpl(millis);
2618         }
2619 
2620         @Override
2621         public void setTimeZone(String tz) {
2622             getContext().enforceCallingOrSelfPermission(
2623                     "android.permission.SET_TIME_ZONE",
2624                     "setTimeZone");
2625 
2626             final long oldId = Binder.clearCallingIdentity();
2627             try {
2628                 setTimeZoneImpl(tz);
2629             } finally {
2630                 Binder.restoreCallingIdentity(oldId);
2631             }
2632         }
2633 
2634         @Override
2635         public void remove(PendingIntent operation, IAlarmListener listener) {
2636             if (operation == null && listener == null) {
2637                 Slog.w(TAG, "remove() with no intent or listener");
2638                 return;
2639             }
2640             synchronized (mLock) {
2641                 removeLocked(operation, listener, REMOVE_REASON_ALARM_CANCELLED);
2642             }
2643         }
2644 
2645         @Override
2646         public long getNextWakeFromIdleTime() {
2647             return getNextWakeFromIdleTimeImpl();
2648         }
2649 
2650         @Override
2651         public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) {
2652             userId = mActivityManagerInternal.handleIncomingUser(Binder.getCallingPid(),
2653                     Binder.getCallingUid(), userId, /*allowAll=*/false, ALLOW_NON_FULL,
2654                     "getNextAlarmClock", null);
2655             return getNextAlarmClockImpl(userId);
2656         }
2657 
2658         @Override
2659         public long currentNetworkTimeMillis() {
2660             final NtpTrustedTime time = NtpTrustedTime.getInstance(getContext());
2661             NtpTrustedTime.TimeResult ntpResult = time.getCachedTimeResult();
2662             if (ntpResult != null) {
2663                 return ntpResult.currentTimeMillis();
2664             } else {
2665                 throw new ParcelableException(new DateTimeException("Missing NTP fix"));
2666             }
2667         }
2668 
2669         @Override
2670         public int getConfigVersion() {
2671             getContext().enforceCallingOrSelfPermission(Manifest.permission.DUMP,
2672                     "getConfigVersion");
2673             return mConstants.getVersion();
2674         }
2675 
2676         @Override
2677         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2678             if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
2679 
2680             if (args.length > 0 && "--proto".equals(args[0])) {
2681                 dumpProto(fd);
2682             } else {
2683                 dumpImpl(new IndentingPrintWriter(pw, "  "));
2684             }
2685         }
2686 
2687         @Override
2688         public void onShellCommand(FileDescriptor in, FileDescriptor out,
2689                 FileDescriptor err, String[] args, ShellCallback callback,
2690                 ResultReceiver resultReceiver) {
2691             (new ShellCmd()).exec(this, in, out, err, args, callback, resultReceiver);
2692         }
2693     };
2694 
isExactAlarmChangeEnabled(String packageName, int userId)2695     private static boolean isExactAlarmChangeEnabled(String packageName, int userId) {
2696         return CompatChanges.isChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION,
2697                 packageName, UserHandle.of(userId));
2698     }
2699 
dumpImpl(IndentingPrintWriter pw)2700     void dumpImpl(IndentingPrintWriter pw) {
2701         synchronized (mLock) {
2702             pw.println("Current Alarm Manager state:");
2703             pw.increaseIndent();
2704 
2705             mConstants.dump(pw);
2706             pw.println();
2707 
2708             if (mAppStateTracker != null) {
2709                 mAppStateTracker.dump(pw);
2710                 pw.println();
2711             }
2712 
2713             pw.println("App Standby Parole: " + mAppStandbyParole);
2714             pw.println();
2715 
2716             final long nowELAPSED = mInjector.getElapsedRealtime();
2717             final long nowUPTIME = SystemClock.uptimeMillis();
2718             final long nowRTC = mInjector.getCurrentTimeMillis();
2719             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
2720 
2721             pw.print("nowRTC=");
2722             pw.print(nowRTC);
2723             pw.print("=");
2724             pw.print(sdf.format(new Date(nowRTC)));
2725             pw.print(" nowELAPSED=");
2726             pw.print(nowELAPSED);
2727             pw.println();
2728 
2729             pw.print("mLastTimeChangeClockTime=");
2730             pw.print(mLastTimeChangeClockTime);
2731             pw.print("=");
2732             pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
2733 
2734             pw.print("mLastTimeChangeRealtime=");
2735             pw.println(mLastTimeChangeRealtime);
2736 
2737             pw.print("mLastTickReceived=");
2738             pw.println(sdf.format(new Date(mLastTickReceived)));
2739 
2740             pw.print("mLastTickSet=");
2741             pw.println(sdf.format(new Date(mLastTickSet)));
2742 
2743             if (RECORD_ALARMS_IN_HISTORY) {
2744                 pw.println();
2745                 pw.println("Recent TIME_TICK history:");
2746                 pw.increaseIndent();
2747                 int i = mNextTickHistory;
2748                 do {
2749                     i--;
2750                     if (i < 0) i = TICK_HISTORY_DEPTH - 1;
2751                     final long time = mTickHistory[i];
2752                     pw.println((time > 0)
2753                             ? sdf.format(new Date(nowRTC - (nowELAPSED - time)))
2754                             : "-");
2755                 } while (i != mNextTickHistory);
2756                 pw.decreaseIndent();
2757             }
2758 
2759             SystemServiceManager ssm = LocalServices.getService(SystemServiceManager.class);
2760             if (ssm != null) {
2761                 pw.println();
2762                 pw.print("RuntimeStarted=");
2763                 pw.print(sdf.format(
2764                         new Date(nowRTC - nowELAPSED + ssm.getRuntimeStartElapsedTime())));
2765                 if (ssm.isRuntimeRestarted()) {
2766                     pw.print("  (Runtime restarted)");
2767                 }
2768                 pw.println();
2769 
2770                 pw.print("Runtime uptime (elapsed): ");
2771                 TimeUtils.formatDuration(nowELAPSED, ssm.getRuntimeStartElapsedTime(), pw);
2772                 pw.println();
2773 
2774                 pw.print("Runtime uptime (uptime): ");
2775                 TimeUtils.formatDuration(nowUPTIME, ssm.getRuntimeStartUptime(), pw);
2776                 pw.println();
2777             }
2778 
2779             pw.println();
2780             if (!mInteractive) {
2781                 pw.print("Time since non-interactive: ");
2782                 TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
2783                 pw.println();
2784             }
2785             pw.print("Max wakeup delay: ");
2786             TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
2787             pw.println();
2788 
2789             pw.print("Time since last dispatch: ");
2790             TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
2791             pw.println();
2792 
2793             pw.print("Next non-wakeup delivery time: ");
2794             TimeUtils.formatDuration(mNextNonWakeupDeliveryTime, nowELAPSED, pw);
2795             pw.println();
2796 
2797             long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
2798             long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
2799             pw.print("Next non-wakeup alarm: ");
2800             TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
2801             pw.print(" = ");
2802             pw.print(mNextNonWakeup);
2803             pw.print(" = ");
2804             pw.println(sdf.format(new Date(nextNonWakeupRTC)));
2805 
2806             pw.increaseIndent();
2807             pw.print("set at ");
2808             TimeUtils.formatDuration(mNextNonWakeUpSetAt, nowELAPSED, pw);
2809             pw.decreaseIndent();
2810             pw.println();
2811 
2812             pw.print("Next wakeup alarm: ");
2813             TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
2814             pw.print(" = ");
2815             pw.print(mNextWakeup);
2816             pw.print(" = ");
2817             pw.println(sdf.format(new Date(nextWakeupRTC)));
2818 
2819             pw.increaseIndent();
2820             pw.print("set at ");
2821             TimeUtils.formatDuration(mNextWakeUpSetAt, nowELAPSED, pw);
2822             pw.decreaseIndent();
2823             pw.println();
2824 
2825             pw.print("Next kernel non-wakeup alarm: ");
2826             TimeUtils.formatDuration(mInjector.getNextAlarm(ELAPSED_REALTIME), pw);
2827             pw.println();
2828             pw.print("Next kernel wakeup alarm: ");
2829             TimeUtils.formatDuration(mInjector.getNextAlarm(ELAPSED_REALTIME_WAKEUP), pw);
2830             pw.println();
2831 
2832             pw.print("Last wakeup: ");
2833             TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw);
2834             pw.print(" = ");
2835             pw.println(mLastWakeup);
2836 
2837             pw.print("Last trigger: ");
2838             TimeUtils.formatDuration(mLastTrigger, nowELAPSED, pw);
2839             pw.print(" = ");
2840             pw.println(mLastTrigger);
2841 
2842             pw.print("Num time change events: ");
2843             pw.println(mNumTimeChanged);
2844 
2845             pw.println();
2846             pw.println("App ids requesting SCHEDULE_EXACT_ALARM: " + mExactAlarmCandidates);
2847 
2848             pw.println();
2849             pw.print("Last OP_SCHEDULE_EXACT_ALARM: [");
2850             for (int i = 0; i < mLastOpScheduleExactAlarm.size(); i++) {
2851                 if (i > 0) {
2852                     pw.print(", ");
2853                 }
2854                 UserHandle.formatUid(pw, mLastOpScheduleExactAlarm.keyAt(i));
2855                 pw.print(":" + AppOpsManager.modeToName(mLastOpScheduleExactAlarm.valueAt(i)));
2856             }
2857             pw.println("]");
2858 
2859             pw.println();
2860             pw.println("Next alarm clock information: ");
2861             pw.increaseIndent();
2862             final TreeSet<Integer> users = new TreeSet<>();
2863             for (int i = 0; i < mNextAlarmClockForUser.size(); i++) {
2864                 users.add(mNextAlarmClockForUser.keyAt(i));
2865             }
2866             for (int i = 0; i < mPendingSendNextAlarmClockChangedForUser.size(); i++) {
2867                 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
2868             }
2869             for (int user : users) {
2870                 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
2871                 final long time = next != null ? next.getTriggerTime() : 0;
2872                 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
2873                 pw.print("user:");
2874                 pw.print(user);
2875                 pw.print(" pendingSend:");
2876                 pw.print(pendingSend);
2877                 pw.print(" time:");
2878                 pw.print(time);
2879                 if (time > 0) {
2880                     pw.print(" = ");
2881                     pw.print(sdf.format(new Date(time)));
2882                     pw.print(" = ");
2883                     TimeUtils.formatDuration(time, nowRTC, pw);
2884                 }
2885                 pw.println();
2886             }
2887             pw.decreaseIndent();
2888 
2889             if (mAlarmStore.size() > 0) {
2890                 pw.println();
2891                 mAlarmStore.dump(pw, nowELAPSED, sdf);
2892             }
2893             pw.println();
2894 
2895             pw.println("Pending user blocked background alarms: ");
2896             pw.increaseIndent();
2897             boolean blocked = false;
2898             for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
2899                 final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
2900                 if (blockedAlarms != null && blockedAlarms.size() > 0) {
2901                     blocked = true;
2902                     dumpAlarmList(pw, blockedAlarms, nowELAPSED, sdf);
2903                 }
2904             }
2905             if (!blocked) {
2906                 pw.println("none");
2907             }
2908             pw.decreaseIndent();
2909             pw.println();
2910 
2911             pw.print("Pending alarms per uid: [");
2912             for (int i = 0; i < mAlarmsPerUid.size(); i++) {
2913                 if (i > 0) {
2914                     pw.print(", ");
2915                 }
2916                 UserHandle.formatUid(pw, mAlarmsPerUid.keyAt(i));
2917                 pw.print(":");
2918                 pw.print(mAlarmsPerUid.valueAt(i));
2919             }
2920             pw.println("]");
2921             pw.println();
2922 
2923             pw.println("App Alarm history:");
2924             mAppWakeupHistory.dump(pw, nowELAPSED);
2925 
2926             if (mPendingIdleUntil != null) {
2927                 pw.println();
2928                 pw.println("Idle mode state:");
2929 
2930                 pw.increaseIndent();
2931                 pw.print("Idling until: ");
2932                 if (mPendingIdleUntil != null) {
2933                     pw.println(mPendingIdleUntil);
2934                     mPendingIdleUntil.dump(pw, nowELAPSED, sdf);
2935                 } else {
2936                     pw.println("null");
2937                 }
2938                 pw.decreaseIndent();
2939             }
2940             if (mNextWakeFromIdle != null) {
2941                 pw.println();
2942                 pw.print("Next wake from idle: ");
2943                 pw.println(mNextWakeFromIdle);
2944 
2945                 pw.increaseIndent();
2946                 mNextWakeFromIdle.dump(pw, nowELAPSED, sdf);
2947                 pw.decreaseIndent();
2948             }
2949 
2950             pw.println();
2951             pw.print("Past-due non-wakeup alarms: ");
2952             if (mPendingNonWakeupAlarms.size() > 0) {
2953                 pw.println(mPendingNonWakeupAlarms.size());
2954 
2955                 pw.increaseIndent();
2956                 dumpAlarmList(pw, mPendingNonWakeupAlarms, nowELAPSED, sdf);
2957                 pw.decreaseIndent();
2958             } else {
2959                 pw.println("(none)");
2960             }
2961             pw.increaseIndent();
2962             pw.print("Number of delayed alarms: ");
2963             pw.print(mNumDelayedAlarms);
2964             pw.print(", total delay time: ");
2965             TimeUtils.formatDuration(mTotalDelayTime, pw);
2966             pw.println();
2967 
2968             pw.print("Max delay time: ");
2969             TimeUtils.formatDuration(mMaxDelayTime, pw);
2970             pw.print(", max non-interactive time: ");
2971             TimeUtils.formatDuration(mNonInteractiveTime, pw);
2972             pw.println();
2973             pw.decreaseIndent();
2974 
2975             pw.println();
2976             pw.print("Broadcast ref count: ");
2977             pw.println(mBroadcastRefCount);
2978             pw.print("PendingIntent send count: ");
2979             pw.println(mSendCount);
2980             pw.print("PendingIntent finish count: ");
2981             pw.println(mSendFinishCount);
2982             pw.print("Listener send count: ");
2983             pw.println(mListenerCount);
2984             pw.print("Listener finish count: ");
2985             pw.println(mListenerFinishCount);
2986             pw.println();
2987 
2988             if (mInFlight.size() > 0) {
2989                 pw.println("Outstanding deliveries:");
2990                 pw.increaseIndent();
2991                 for (int i = 0; i < mInFlight.size(); i++) {
2992                     pw.print("#");
2993                     pw.print(i);
2994                     pw.print(": ");
2995                     pw.println(mInFlight.get(i));
2996                 }
2997                 pw.decreaseIndent();
2998                 pw.println();
2999             }
3000 
3001             pw.println("Allow while idle history:");
3002             mAllowWhileIdleHistory.dump(pw, nowELAPSED);
3003             pw.println();
3004 
3005             pw.println("Allow while idle compat history:");
3006             mAllowWhileIdleCompatHistory.dump(pw, nowELAPSED);
3007             pw.println();
3008 
3009             if (mLastPriorityAlarmDispatch.size() > 0) {
3010                 pw.println("Last priority alarm dispatches:");
3011                 pw.increaseIndent();
3012                 for (int i = 0; i < mLastPriorityAlarmDispatch.size(); i++) {
3013                     pw.print("UID: ");
3014                     UserHandle.formatUid(pw, mLastPriorityAlarmDispatch.keyAt(i));
3015                     pw.print(": ");
3016                     TimeUtils.formatDuration(mLastPriorityAlarmDispatch.valueAt(i), nowELAPSED, pw);
3017                     pw.println();
3018                 }
3019                 pw.decreaseIndent();
3020             }
3021 
3022             if (mRemovalHistory.size() > 0) {
3023                 pw.println("Removal history: ");
3024                 pw.increaseIndent();
3025                 for (int i = 0; i < mRemovalHistory.size(); i++) {
3026                     UserHandle.formatUid(pw, mRemovalHistory.keyAt(i));
3027                     pw.println(":");
3028                     pw.increaseIndent();
3029                     final RemovedAlarm[] historyForUid = mRemovalHistory.valueAt(i).toArray();
3030                     for (final RemovedAlarm removedAlarm : historyForUid) {
3031                         removedAlarm.dump(pw, nowELAPSED, sdf);
3032                     }
3033                     pw.decreaseIndent();
3034                 }
3035                 pw.decreaseIndent();
3036                 pw.println();
3037             }
3038 
3039             if (mLog.dump(pw, "Recent problems:")) {
3040                 pw.println();
3041             }
3042 
3043             final FilterStats[] topFilters = new FilterStats[10];
3044             final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
3045                 @Override
3046                 public int compare(FilterStats lhs, FilterStats rhs) {
3047                     if (lhs.aggregateTime < rhs.aggregateTime) {
3048                         return 1;
3049                     } else if (lhs.aggregateTime > rhs.aggregateTime) {
3050                         return -1;
3051                     }
3052                     return 0;
3053                 }
3054             };
3055             int len = 0;
3056             // Get the top 10 FilterStats, ordered by aggregateTime.
3057             for (int iu = 0; iu < mBroadcastStats.size(); iu++) {
3058                 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
3059                 for (int ip = 0; ip < uidStats.size(); ip++) {
3060                     BroadcastStats bs = uidStats.valueAt(ip);
3061                     for (int is = 0; is < bs.filterStats.size(); is++) {
3062                         FilterStats fs = bs.filterStats.valueAt(is);
3063                         int pos = len > 0
3064                                 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
3065                         if (pos < 0) {
3066                             pos = -pos - 1;
3067                         }
3068                         if (pos < topFilters.length) {
3069                             int copylen = topFilters.length - pos - 1;
3070                             if (copylen > 0) {
3071                                 System.arraycopy(topFilters, pos, topFilters, pos + 1, copylen);
3072                             }
3073                             topFilters[pos] = fs;
3074                             if (len < topFilters.length) {
3075                                 len++;
3076                             }
3077                         }
3078                     }
3079                 }
3080             }
3081             if (len > 0) {
3082                 pw.println("Top Alarms:");
3083                 pw.increaseIndent();
3084                 for (int i = 0; i < len; i++) {
3085                     FilterStats fs = topFilters[i];
3086                     if (fs.nesting > 0) pw.print("*ACTIVE* ");
3087                     TimeUtils.formatDuration(fs.aggregateTime, pw);
3088                     pw.print(" running, ");
3089                     pw.print(fs.numWakeup);
3090                     pw.print(" wakeups, ");
3091                     pw.print(fs.count);
3092                     pw.print(" alarms: ");
3093                     UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
3094                     pw.print(":");
3095                     pw.print(fs.mBroadcastStats.mPackageName);
3096                     pw.println();
3097 
3098                     pw.increaseIndent();
3099                     pw.print(fs.mTag);
3100                     pw.println();
3101                     pw.decreaseIndent();
3102                 }
3103                 pw.decreaseIndent();
3104             }
3105 
3106             pw.println();
3107             pw.println("Alarm Stats:");
3108             final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
3109             for (int iu = 0; iu < mBroadcastStats.size(); iu++) {
3110                 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
3111                 for (int ip = 0; ip < uidStats.size(); ip++) {
3112                     BroadcastStats bs = uidStats.valueAt(ip);
3113                     if (bs.nesting > 0) pw.print("*ACTIVE* ");
3114                     UserHandle.formatUid(pw, bs.mUid);
3115                     pw.print(":");
3116                     pw.print(bs.mPackageName);
3117                     pw.print(" ");
3118                     TimeUtils.formatDuration(bs.aggregateTime, pw);
3119                     pw.print(" running, ");
3120                     pw.print(bs.numWakeup);
3121                     pw.println(" wakeups:");
3122 
3123                     tmpFilters.clear();
3124                     for (int is = 0; is < bs.filterStats.size(); is++) {
3125                         tmpFilters.add(bs.filterStats.valueAt(is));
3126                     }
3127                     Collections.sort(tmpFilters, comparator);
3128                     pw.increaseIndent();
3129                     for (int i = 0; i < tmpFilters.size(); i++) {
3130                         FilterStats fs = tmpFilters.get(i);
3131                         if (fs.nesting > 0) pw.print("*ACTIVE* ");
3132                         TimeUtils.formatDuration(fs.aggregateTime, pw);
3133                         pw.print(" ");
3134                         pw.print(fs.numWakeup);
3135                         pw.print(" wakes ");
3136                         pw.print(fs.count);
3137                         pw.print(" alarms, last ");
3138                         TimeUtils.formatDuration(fs.lastTime, nowELAPSED, pw);
3139                         pw.println(":");
3140 
3141                         pw.increaseIndent();
3142                         pw.print(fs.mTag);
3143                         pw.println();
3144                         pw.decreaseIndent();
3145                     }
3146                     pw.decreaseIndent();
3147                 }
3148             }
3149             pw.println();
3150             mStatLogger.dump(pw);
3151 
3152             if (RECORD_DEVICE_IDLE_ALARMS) {
3153                 pw.println();
3154                 pw.println("Allow while idle dispatches:");
3155                 pw.increaseIndent();
3156                 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
3157                     IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
3158                     TimeUtils.formatDuration(ent.elapsedRealtime, nowELAPSED, pw);
3159                     pw.print(": ");
3160                     UserHandle.formatUid(pw, ent.uid);
3161                     pw.print(":");
3162                     pw.println(ent.pkg);
3163 
3164                     pw.increaseIndent();
3165                     if (ent.op != null) {
3166                         pw.print(ent.op);
3167                         pw.print(" / ");
3168                         pw.print(ent.tag);
3169                         if (ent.argRealtime != 0) {
3170                             pw.print(" (");
3171                             TimeUtils.formatDuration(ent.argRealtime, nowELAPSED, pw);
3172                             pw.print(")");
3173                         }
3174                         pw.println();
3175                     }
3176                     pw.decreaseIndent();
3177                 }
3178                 pw.decreaseIndent();
3179             }
3180         }
3181     }
3182 
dumpProto(FileDescriptor fd)3183     void dumpProto(FileDescriptor fd) {
3184         final ProtoOutputStream proto = new ProtoOutputStream(fd);
3185 
3186         synchronized (mLock) {
3187             final long nowRTC = mInjector.getCurrentTimeMillis();
3188             final long nowElapsed = mInjector.getElapsedRealtime();
3189             proto.write(AlarmManagerServiceDumpProto.CURRENT_TIME, nowRTC);
3190             proto.write(AlarmManagerServiceDumpProto.ELAPSED_REALTIME, nowElapsed);
3191             proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_CLOCK_TIME,
3192                     mLastTimeChangeClockTime);
3193             proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_REALTIME,
3194                     mLastTimeChangeRealtime);
3195 
3196             mConstants.dumpProto(proto, AlarmManagerServiceDumpProto.SETTINGS);
3197 
3198             if (mAppStateTracker != null) {
3199                 mAppStateTracker.dumpProto(proto, AlarmManagerServiceDumpProto.APP_STATE_TRACKER);
3200             }
3201 
3202             proto.write(AlarmManagerServiceDumpProto.IS_INTERACTIVE, mInteractive);
3203             if (!mInteractive) {
3204                 // Durations
3205                 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_NON_INTERACTIVE_MS,
3206                         nowElapsed - mNonInteractiveStartTime);
3207                 proto.write(AlarmManagerServiceDumpProto.MAX_WAKEUP_DELAY_MS,
3208                         currentNonWakeupFuzzLocked(nowElapsed));
3209                 proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_DISPATCH_MS,
3210                         nowElapsed - mLastAlarmDeliveryTime);
3211                 proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_NON_WAKEUP_DELIVERY_MS,
3212                         nowElapsed - mNextNonWakeupDeliveryTime);
3213             }
3214 
3215             proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_NON_WAKEUP_ALARM_MS,
3216                     mNextNonWakeup - nowElapsed);
3217             proto.write(AlarmManagerServiceDumpProto.TIME_UNTIL_NEXT_WAKEUP_MS,
3218                     mNextWakeup - nowElapsed);
3219             proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_WAKEUP_MS,
3220                     nowElapsed - mLastWakeup);
3221             proto.write(AlarmManagerServiceDumpProto.TIME_SINCE_LAST_WAKEUP_SET_MS,
3222                     nowElapsed - mNextWakeUpSetAt);
3223             proto.write(AlarmManagerServiceDumpProto.TIME_CHANGE_EVENT_COUNT, mNumTimeChanged);
3224 
3225             final TreeSet<Integer> users = new TreeSet<>();
3226             final int nextAlarmClockForUserSize = mNextAlarmClockForUser.size();
3227             for (int i = 0; i < nextAlarmClockForUserSize; i++) {
3228                 users.add(mNextAlarmClockForUser.keyAt(i));
3229             }
3230             final int pendingSendNextAlarmClockChangedForUserSize =
3231                     mPendingSendNextAlarmClockChangedForUser.size();
3232             for (int i = 0; i < pendingSendNextAlarmClockChangedForUserSize; i++) {
3233                 users.add(mPendingSendNextAlarmClockChangedForUser.keyAt(i));
3234             }
3235             for (int user : users) {
3236                 final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
3237                 final long time = next != null ? next.getTriggerTime() : 0;
3238                 final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
3239                 final long aToken = proto.start(
3240                         AlarmManagerServiceDumpProto.NEXT_ALARM_CLOCK_METADATA);
3241                 proto.write(AlarmClockMetadataProto.USER, user);
3242                 proto.write(AlarmClockMetadataProto.IS_PENDING_SEND, pendingSend);
3243                 proto.write(AlarmClockMetadataProto.TRIGGER_TIME_MS, time);
3244                 proto.end(aToken);
3245             }
3246             mAlarmStore.dumpProto(proto, nowElapsed);
3247 
3248             for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
3249                 final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
3250                 if (blockedAlarms != null) {
3251                     for (Alarm a : blockedAlarms) {
3252                         a.dumpDebug(proto,
3253                                 AlarmManagerServiceDumpProto.PENDING_USER_BLOCKED_BACKGROUND_ALARMS,
3254                                 nowElapsed);
3255                     }
3256                 }
3257             }
3258             if (mPendingIdleUntil != null) {
3259                 mPendingIdleUntil.dumpDebug(
3260                         proto, AlarmManagerServiceDumpProto.PENDING_IDLE_UNTIL, nowElapsed);
3261             }
3262             if (mNextWakeFromIdle != null) {
3263                 mNextWakeFromIdle.dumpDebug(proto, AlarmManagerServiceDumpProto.NEXT_WAKE_FROM_IDLE,
3264                         nowElapsed);
3265             }
3266 
3267             for (Alarm a : mPendingNonWakeupAlarms) {
3268                 a.dumpDebug(proto, AlarmManagerServiceDumpProto.PAST_DUE_NON_WAKEUP_ALARMS,
3269                         nowElapsed);
3270             }
3271 
3272             proto.write(AlarmManagerServiceDumpProto.DELAYED_ALARM_COUNT, mNumDelayedAlarms);
3273             proto.write(AlarmManagerServiceDumpProto.TOTAL_DELAY_TIME_MS, mTotalDelayTime);
3274             proto.write(AlarmManagerServiceDumpProto.MAX_DELAY_DURATION_MS, mMaxDelayTime);
3275             proto.write(AlarmManagerServiceDumpProto.MAX_NON_INTERACTIVE_DURATION_MS,
3276                     mNonInteractiveTime);
3277 
3278             proto.write(AlarmManagerServiceDumpProto.BROADCAST_REF_COUNT, mBroadcastRefCount);
3279             proto.write(AlarmManagerServiceDumpProto.PENDING_INTENT_SEND_COUNT, mSendCount);
3280             proto.write(AlarmManagerServiceDumpProto.PENDING_INTENT_FINISH_COUNT, mSendFinishCount);
3281             proto.write(AlarmManagerServiceDumpProto.LISTENER_SEND_COUNT, mListenerCount);
3282             proto.write(AlarmManagerServiceDumpProto.LISTENER_FINISH_COUNT, mListenerFinishCount);
3283 
3284             for (InFlight f : mInFlight) {
3285                 f.dumpDebug(proto, AlarmManagerServiceDumpProto.OUTSTANDING_DELIVERIES);
3286             }
3287 
3288             mLog.dumpDebug(proto, AlarmManagerServiceDumpProto.RECENT_PROBLEMS);
3289 
3290             final FilterStats[] topFilters = new FilterStats[10];
3291             final Comparator<FilterStats> comparator = new Comparator<FilterStats>() {
3292                 @Override
3293                 public int compare(FilterStats lhs, FilterStats rhs) {
3294                     if (lhs.aggregateTime < rhs.aggregateTime) {
3295                         return 1;
3296                     } else if (lhs.aggregateTime > rhs.aggregateTime) {
3297                         return -1;
3298                     }
3299                     return 0;
3300                 }
3301             };
3302             int len = 0;
3303             // Get the top 10 FilterStats, ordered by aggregateTime.
3304             for (int iu = 0; iu < mBroadcastStats.size(); ++iu) {
3305                 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
3306                 for (int ip = 0; ip < uidStats.size(); ++ip) {
3307                     BroadcastStats bs = uidStats.valueAt(ip);
3308                     for (int is = 0; is < bs.filterStats.size(); ++is) {
3309                         FilterStats fs = bs.filterStats.valueAt(is);
3310                         int pos = len > 0
3311                                 ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0;
3312                         if (pos < 0) {
3313                             pos = -pos - 1;
3314                         }
3315                         if (pos < topFilters.length) {
3316                             int copylen = topFilters.length - pos - 1;
3317                             if (copylen > 0) {
3318                                 System.arraycopy(topFilters, pos, topFilters, pos + 1, copylen);
3319                             }
3320                             topFilters[pos] = fs;
3321                             if (len < topFilters.length) {
3322                                 len++;
3323                             }
3324                         }
3325                     }
3326                 }
3327             }
3328             for (int i = 0; i < len; ++i) {
3329                 final long token = proto.start(AlarmManagerServiceDumpProto.TOP_ALARMS);
3330                 FilterStats fs = topFilters[i];
3331 
3332                 proto.write(AlarmManagerServiceDumpProto.TopAlarm.UID, fs.mBroadcastStats.mUid);
3333                 proto.write(AlarmManagerServiceDumpProto.TopAlarm.PACKAGE_NAME,
3334                         fs.mBroadcastStats.mPackageName);
3335                 fs.dumpDebug(proto, AlarmManagerServiceDumpProto.TopAlarm.FILTER);
3336 
3337                 proto.end(token);
3338             }
3339 
3340             final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
3341             for (int iu = 0; iu < mBroadcastStats.size(); ++iu) {
3342                 ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
3343                 for (int ip = 0; ip < uidStats.size(); ++ip) {
3344                     final long token = proto.start(AlarmManagerServiceDumpProto.ALARM_STATS);
3345 
3346                     BroadcastStats bs = uidStats.valueAt(ip);
3347                     bs.dumpDebug(proto, AlarmManagerServiceDumpProto.AlarmStat.BROADCAST);
3348 
3349                     // uidStats is an ArrayMap, which we can't sort.
3350                     tmpFilters.clear();
3351                     for (int is = 0; is < bs.filterStats.size(); ++is) {
3352                         tmpFilters.add(bs.filterStats.valueAt(is));
3353                     }
3354                     Collections.sort(tmpFilters, comparator);
3355                     for (FilterStats fs : tmpFilters) {
3356                         fs.dumpDebug(proto, AlarmManagerServiceDumpProto.AlarmStat.FILTERS);
3357                     }
3358 
3359                     proto.end(token);
3360                 }
3361             }
3362 
3363             if (RECORD_DEVICE_IDLE_ALARMS) {
3364                 for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
3365                     IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
3366                     final long token = proto.start(
3367                             AlarmManagerServiceDumpProto.ALLOW_WHILE_IDLE_DISPATCHES);
3368 
3369                     proto.write(IdleDispatchEntryProto.UID, ent.uid);
3370                     proto.write(IdleDispatchEntryProto.PKG, ent.pkg);
3371                     proto.write(IdleDispatchEntryProto.TAG, ent.tag);
3372                     proto.write(IdleDispatchEntryProto.OP, ent.op);
3373                     proto.write(IdleDispatchEntryProto.ENTRY_CREATION_REALTIME,
3374                             ent.elapsedRealtime);
3375                     proto.write(IdleDispatchEntryProto.ARG_REALTIME, ent.argRealtime);
3376 
3377                     proto.end(token);
3378                 }
3379             }
3380         }
3381 
3382         proto.flush();
3383     }
3384 
getNextWakeFromIdleTimeImpl()3385     long getNextWakeFromIdleTimeImpl() {
3386         synchronized (mLock) {
3387             return mNextWakeFromIdle != null ? mNextWakeFromIdle.getWhenElapsed() : Long.MAX_VALUE;
3388         }
3389     }
3390 
isIdlingImpl()3391     private boolean isIdlingImpl() {
3392         synchronized (mLock) {
3393             return mPendingIdleUntil != null;
3394         }
3395     }
3396 
getNextAlarmClockImpl(int userId)3397     AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
3398         synchronized (mLock) {
3399             return mNextAlarmClockForUser.get(userId);
3400         }
3401     }
3402 
3403     /**
3404      * Recomputes the next alarm clock for all users.
3405      */
updateNextAlarmClockLocked()3406     private void updateNextAlarmClockLocked() {
3407         if (!mNextAlarmClockMayChange) {
3408             return;
3409         }
3410         mNextAlarmClockMayChange = false;
3411 
3412         final SparseArray<AlarmManager.AlarmClockInfo> nextForUser = mTmpSparseAlarmClockArray;
3413         nextForUser.clear();
3414 
3415         final ArrayList<Alarm> allAlarms = mAlarmStore.asList();
3416         for (final Alarm a : allAlarms) {
3417             if (a.alarmClock != null) {
3418                 final int userId = UserHandle.getUserId(a.uid);
3419                 final AlarmManager.AlarmClockInfo current = mNextAlarmClockForUser.get(userId);
3420 
3421                 if (DEBUG_ALARM_CLOCK) {
3422                     Log.v(TAG, "Found AlarmClockInfo " + a.alarmClock + " at "
3423                             + formatNextAlarm(getContext(), a.alarmClock, userId)
3424                             + " for user " + userId);
3425                 }
3426 
3427                 // AlarmClocks are sorted by time, so no need to compare times here.
3428                 if (nextForUser.get(userId) == null) {
3429                     nextForUser.put(userId, a.alarmClock);
3430                 } else if (a.alarmClock.equals(current)
3431                         && current.getTriggerTime() <= nextForUser.get(userId).getTriggerTime()) {
3432                     // same/earlier time and it's the one we cited before, so stick with it
3433                     nextForUser.put(userId, current);
3434                 }
3435             }
3436         }
3437 
3438         final int newUserCount = nextForUser.size();
3439         for (int i = 0; i < newUserCount; i++) {
3440             AlarmManager.AlarmClockInfo newAlarm = nextForUser.valueAt(i);
3441             int userId = nextForUser.keyAt(i);
3442             AlarmManager.AlarmClockInfo currentAlarm = mNextAlarmClockForUser.get(userId);
3443             if (!newAlarm.equals(currentAlarm)) {
3444                 updateNextAlarmInfoForUserLocked(userId, newAlarm);
3445             }
3446         }
3447 
3448         final int oldUserCount = mNextAlarmClockForUser.size();
3449         for (int i = oldUserCount - 1; i >= 0; i--) {
3450             int userId = mNextAlarmClockForUser.keyAt(i);
3451             if (nextForUser.get(userId) == null) {
3452                 updateNextAlarmInfoForUserLocked(userId, null);
3453             }
3454         }
3455     }
3456 
updateNextAlarmInfoForUserLocked(int userId, AlarmManager.AlarmClockInfo alarmClock)3457     private void updateNextAlarmInfoForUserLocked(int userId,
3458             AlarmManager.AlarmClockInfo alarmClock) {
3459         if (alarmClock != null) {
3460             if (DEBUG_ALARM_CLOCK) {
3461                 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): " +
3462                         formatNextAlarm(getContext(), alarmClock, userId));
3463             }
3464             mNextAlarmClockForUser.put(userId, alarmClock);
3465         } else {
3466             if (DEBUG_ALARM_CLOCK) {
3467                 Log.v(TAG, "Next AlarmClockInfoForUser(" + userId + "): None");
3468             }
3469             mNextAlarmClockForUser.remove(userId);
3470         }
3471 
3472         mPendingSendNextAlarmClockChangedForUser.put(userId, true);
3473         mHandler.removeMessages(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
3474         mHandler.sendEmptyMessage(AlarmHandler.SEND_NEXT_ALARM_CLOCK_CHANGED);
3475     }
3476 
3477     /**
3478      * Updates NEXT_ALARM_FORMATTED and sends NEXT_ALARM_CLOCK_CHANGED_INTENT for all users
3479      * for which alarm clocks have changed since the last call to this.
3480      *
3481      * Do not call with a lock held. Only call from mHandler's thread.
3482      *
3483      * @see AlarmHandler#SEND_NEXT_ALARM_CLOCK_CHANGED
3484      */
sendNextAlarmClockChanged()3485     private void sendNextAlarmClockChanged() {
3486         SparseArray<AlarmManager.AlarmClockInfo> pendingUsers = mHandlerSparseAlarmClockArray;
3487         pendingUsers.clear();
3488 
3489         synchronized (mLock) {
3490             final int n = mPendingSendNextAlarmClockChangedForUser.size();
3491             for (int i = 0; i < n; i++) {
3492                 int userId = mPendingSendNextAlarmClockChangedForUser.keyAt(i);
3493                 pendingUsers.append(userId, mNextAlarmClockForUser.get(userId));
3494             }
3495             mPendingSendNextAlarmClockChangedForUser.clear();
3496         }
3497 
3498         final int n = pendingUsers.size();
3499         for (int i = 0; i < n; i++) {
3500             int userId = pendingUsers.keyAt(i);
3501             AlarmManager.AlarmClockInfo alarmClock = pendingUsers.valueAt(i);
3502             Settings.System.putStringForUser(getContext().getContentResolver(),
3503                     Settings.System.NEXT_ALARM_FORMATTED,
3504                     formatNextAlarm(getContext(), alarmClock, userId),
3505                     userId);
3506 
3507             getContext().sendBroadcastAsUser(NEXT_ALARM_CLOCK_CHANGED_INTENT,
3508                     new UserHandle(userId));
3509         }
3510     }
3511 
3512     /**
3513      * Formats an alarm like platform/packages/apps/DeskClock used to.
3514      */
formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info, int userId)3515     private static String formatNextAlarm(final Context context, AlarmManager.AlarmClockInfo info,
3516             int userId) {
3517         String skeleton = DateFormat.is24HourFormat(context, userId) ? "EHm" : "Ehma";
3518         String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
3519         return (info == null) ? "" :
3520                 DateFormat.format(pattern, info.getTriggerTime()).toString();
3521     }
3522 
rescheduleKernelAlarmsLocked()3523     void rescheduleKernelAlarmsLocked() {
3524         // Schedule the next upcoming wakeup alarm.  If there is a deliverable batch
3525         // prior to that which contains no wakeups, we schedule that as well.
3526         final long nowElapsed = mInjector.getElapsedRealtime();
3527         long nextNonWakeup = 0;
3528         if (mAlarmStore.size() > 0) {
3529             final long firstWakeup = mAlarmStore.getNextWakeupDeliveryTime();
3530             final long first = mAlarmStore.getNextDeliveryTime();
3531             if (firstWakeup != 0) {
3532                 mNextWakeup = firstWakeup;
3533                 mNextWakeUpSetAt = nowElapsed;
3534                 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup);
3535             }
3536             if (first != firstWakeup) {
3537                 nextNonWakeup = first;
3538             }
3539         }
3540         if (mPendingNonWakeupAlarms.size() > 0) {
3541             if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
3542                 nextNonWakeup = mNextNonWakeupDeliveryTime;
3543             }
3544         }
3545         if (nextNonWakeup != 0) {
3546             mNextNonWakeup = nextNonWakeup;
3547             mNextNonWakeUpSetAt = nowElapsed;
3548             setLocked(ELAPSED_REALTIME, nextNonWakeup);
3549         }
3550     }
3551 
3552     /**
3553      * Called when the {@link Constants#EXACT_ALARM_DENY_LIST}, changes with the packages that
3554      * either got added or deleted.
3555      * These packages may lose or gain the SCHEDULE_EXACT_ALARM permission.
3556      *
3557      * Note that these packages don't need to be installed on the device, but if they are and they
3558      * do undergo a permission change, we will handle them appropriately.
3559      *
3560      * This should not be called with the lock held as it calls out to other services.
3561      * This is not expected to get called frequently.
3562      */
handleChangesToExactAlarmDenyList(ArraySet<String> changedPackages, boolean added)3563     void handleChangesToExactAlarmDenyList(ArraySet<String> changedPackages, boolean added) {
3564         Slog.w(TAG, "Packages " + changedPackages + (added ? " added to" : " removed from")
3565                 + " the exact alarm deny list.");
3566 
3567         final int[] startedUserIds = mActivityManagerInternal.getStartedUserIds();
3568 
3569         for (int i = 0; i < changedPackages.size(); i++) {
3570             final String changedPackage = changedPackages.valueAt(i);
3571             for (final int userId : startedUserIds) {
3572                 final int uid = mPackageManagerInternal.getPackageUid(changedPackage, 0, userId);
3573                 if (uid <= 0) {
3574                     continue;
3575                 }
3576                 if (!isExactAlarmChangeEnabled(changedPackage, userId)) {
3577                     continue;
3578                 }
3579                 final int appOpMode;
3580                 synchronized (mLock) {
3581                     appOpMode = mLastOpScheduleExactAlarm.get(uid,
3582                             AppOpsManager.opToDefaultMode(AppOpsManager.OP_SCHEDULE_EXACT_ALARM));
3583                 }
3584                 final boolean requested = mExactAlarmCandidates.contains(UserHandle.getAppId(uid));
3585 
3586                 // added: true => package was added to the deny list
3587                 // added: false => package was removed from the deny list
3588                 final boolean hadPermission = getScheduleExactAlarmState(requested, !added,
3589                         appOpMode);
3590                 final boolean hasPermission = getScheduleExactAlarmState(requested, added,
3591                         appOpMode);
3592 
3593                 if (hadPermission == hasPermission) {
3594                     continue;
3595                 }
3596                 if (added) {
3597                     synchronized (mLock) {
3598                         removeExactAlarmsOnPermissionRevokedLocked(uid, changedPackage);
3599                     }
3600                 } else {
3601                     sendScheduleExactAlarmPermissionStateChangedBroadcast(changedPackage, userId);
3602                 }
3603             }
3604         }
3605     }
3606 
3607     /**
3608      * Called when an app loses {@link Manifest.permission#SCHEDULE_EXACT_ALARM} to remove alarms
3609      * that the app is no longer eligible to use.
3610      *
3611      * This is not expected to get called frequently.
3612      */
removeExactAlarmsOnPermissionRevokedLocked(int uid, String packageName)3613     void removeExactAlarmsOnPermissionRevokedLocked(int uid, String packageName) {
3614         if (isExemptFromExactAlarmPermission(uid)
3615                 || !isExactAlarmChangeEnabled(packageName, UserHandle.getUserId(uid))) {
3616             return;
3617         }
3618         Slog.w(TAG, "Package " + packageName + ", uid " + uid + " lost SCHEDULE_EXACT_ALARM!");
3619 
3620         final Predicate<Alarm> whichAlarms = a -> (a.uid == uid && a.packageName.equals(packageName)
3621                 && a.windowLength == 0);
3622         removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_EXACT_PERMISSION_REVOKED);
3623 
3624         if (mConstants.KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED) {
3625             PermissionManagerService.killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid),
3626                     "schedule_exact_alarm revoked");
3627         }
3628     }
3629 
removeAlarmsInternalLocked(Predicate<Alarm> whichAlarms, int reason)3630     private void removeAlarmsInternalLocked(Predicate<Alarm> whichAlarms, int reason) {
3631         final long nowRtc = mInjector.getCurrentTimeMillis();
3632         final long nowElapsed = mInjector.getElapsedRealtime();
3633 
3634         final ArrayList<Alarm> removedAlarms = mAlarmStore.remove(whichAlarms);
3635         final boolean removedFromStore = !removedAlarms.isEmpty();
3636 
3637         for (int i = mPendingBackgroundAlarms.size() - 1; i >= 0; i--) {
3638             final ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.valueAt(i);
3639             for (int j = alarmsForUid.size() - 1; j >= 0; j--) {
3640                 final Alarm alarm = alarmsForUid.get(j);
3641                 if (whichAlarms.test(alarm)) {
3642                     removedAlarms.add(alarmsForUid.remove(j));
3643                 }
3644             }
3645             if (alarmsForUid.size() == 0) {
3646                 mPendingBackgroundAlarms.removeAt(i);
3647             }
3648         }
3649         for (int i = mPendingNonWakeupAlarms.size() - 1; i >= 0; i--) {
3650             final Alarm a = mPendingNonWakeupAlarms.get(i);
3651             if (whichAlarms.test(a)) {
3652                 removedAlarms.add(mPendingNonWakeupAlarms.remove(i));
3653             }
3654         }
3655 
3656         for (final Alarm removed : removedAlarms) {
3657             decrementAlarmCount(removed.uid, 1);
3658             if (removed.listener != null) {
3659                 removed.listener.asBinder().unlinkToDeath(mListenerDeathRecipient, 0);
3660             }
3661             if (!RemovedAlarm.isLoggable(reason)) {
3662                 continue;
3663             }
3664             RingBuffer<RemovedAlarm> bufferForUid = mRemovalHistory.get(removed.uid);
3665             if (bufferForUid == null) {
3666                 bufferForUid = new RingBuffer<>(RemovedAlarm.class, REMOVAL_HISTORY_SIZE_PER_UID);
3667                 mRemovalHistory.put(removed.uid, bufferForUid);
3668             }
3669             bufferForUid.append(new RemovedAlarm(removed, reason, nowRtc, nowElapsed));
3670         }
3671 
3672         if (removedFromStore) {
3673             boolean idleUntilUpdated = false;
3674             if (mPendingIdleUntil != null && whichAlarms.test(mPendingIdleUntil)) {
3675                 mPendingIdleUntil = null;
3676                 idleUntilUpdated = true;
3677             }
3678             if (mNextWakeFromIdle != null && whichAlarms.test(mNextWakeFromIdle)) {
3679                 mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm();
3680                 if (mPendingIdleUntil != null) {
3681                     idleUntilUpdated |= mAlarmStore.updateAlarmDeliveries(alarm ->
3682                             (alarm == mPendingIdleUntil && adjustIdleUntilTime(alarm)));
3683                 }
3684             }
3685             if (idleUntilUpdated) {
3686                 mAlarmStore.updateAlarmDeliveries(
3687                         alarm -> adjustDeliveryTimeBasedOnDeviceIdle(alarm));
3688             }
3689             rescheduleKernelAlarmsLocked();
3690             updateNextAlarmClockLocked();
3691         }
3692     }
3693 
removeLocked(PendingIntent operation, IAlarmListener directReceiver, int reason)3694     void removeLocked(PendingIntent operation, IAlarmListener directReceiver, int reason) {
3695         if (operation == null && directReceiver == null) {
3696             if (localLOGV) {
3697                 Slog.w(TAG, "requested remove() of null operation",
3698                         new RuntimeException("here"));
3699             }
3700             return;
3701         }
3702         removeAlarmsInternalLocked(a -> a.matches(operation, directReceiver), reason);
3703     }
3704 
removeLocked(final int uid, int reason)3705     void removeLocked(final int uid, int reason) {
3706         if (uid == Process.SYSTEM_UID) {
3707             // If a force-stop occurs for a system-uid package, ignore it.
3708             return;
3709         }
3710         removeAlarmsInternalLocked(a -> a.uid == uid, reason);
3711     }
3712 
removeLocked(final String packageName)3713     void removeLocked(final String packageName) {
3714         if (packageName == null) {
3715             if (localLOGV) {
3716                 Slog.w(TAG, "requested remove() of null packageName",
3717                         new RuntimeException("here"));
3718             }
3719             return;
3720         }
3721         removeAlarmsInternalLocked(a -> a.matches(packageName), REMOVE_REASON_UNDEFINED);
3722     }
3723 
3724     // Only called for ephemeral apps
removeForStoppedLocked(final int uid)3725     void removeForStoppedLocked(final int uid) {
3726         if (uid == Process.SYSTEM_UID) {
3727             // If a force-stop occurs for a system-uid package, ignore it.
3728             return;
3729         }
3730         final Predicate<Alarm> whichAlarms = (a) -> (a.uid == uid
3731                 && mActivityManagerInternal.isAppStartModeDisabled(uid, a.packageName));
3732         removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_UNDEFINED);
3733     }
3734 
removeUserLocked(int userHandle)3735     void removeUserLocked(int userHandle) {
3736         if (userHandle == USER_SYSTEM) {
3737             Slog.w(TAG, "Ignoring attempt to remove system-user state!");
3738             return;
3739         }
3740         final Predicate<Alarm> whichAlarms =
3741                 (Alarm a) -> UserHandle.getUserId(a.uid) == userHandle;
3742         removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_UNDEFINED);
3743 
3744         for (int i = mLastPriorityAlarmDispatch.size() - 1; i >= 0; i--) {
3745             if (UserHandle.getUserId(mLastPriorityAlarmDispatch.keyAt(i)) == userHandle) {
3746                 mLastPriorityAlarmDispatch.removeAt(i);
3747             }
3748         }
3749         for (int i = mRemovalHistory.size() - 1; i >= 0; i--) {
3750             if (UserHandle.getUserId(mRemovalHistory.keyAt(i)) == userHandle) {
3751                 mRemovalHistory.removeAt(i);
3752             }
3753         }
3754         for (int i = mLastOpScheduleExactAlarm.size() - 1; i >= 0; i--) {
3755             if (UserHandle.getUserId(mLastOpScheduleExactAlarm.keyAt(i)) == userHandle) {
3756                 mLastOpScheduleExactAlarm.removeAt(i);
3757             }
3758         }
3759     }
3760 
interactiveStateChangedLocked(boolean interactive)3761     void interactiveStateChangedLocked(boolean interactive) {
3762         if (mInteractive != interactive) {
3763             mInteractive = interactive;
3764             final long nowELAPSED = mInjector.getElapsedRealtime();
3765             if (interactive) {
3766                 if (mPendingNonWakeupAlarms.size() > 0) {
3767                     final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
3768                     mTotalDelayTime += thisDelayTime;
3769                     if (mMaxDelayTime < thisDelayTime) {
3770                         mMaxDelayTime = thisDelayTime;
3771                     }
3772                     final ArrayList<Alarm> triggerList = new ArrayList<>(mPendingNonWakeupAlarms);
3773                     deliverAlarmsLocked(triggerList, nowELAPSED);
3774                     mPendingNonWakeupAlarms.clear();
3775                 }
3776                 if (mNonInteractiveStartTime > 0) {
3777                     long dur = nowELAPSED - mNonInteractiveStartTime;
3778                     if (dur > mNonInteractiveTime) {
3779                         mNonInteractiveTime = dur;
3780                     }
3781                 }
3782                 // And send a TIME_TICK right now, since it is important to get the UI updated.
3783                 mHandler.post(() ->
3784                         getContext().sendBroadcastAsUser(mTimeTickIntent, UserHandle.ALL));
3785             } else {
3786                 mNonInteractiveStartTime = nowELAPSED;
3787             }
3788         }
3789     }
3790 
lookForPackageLocked(String packageName)3791     boolean lookForPackageLocked(String packageName) {
3792         final ArrayList<Alarm> allAlarms = mAlarmStore.asList();
3793         for (final Alarm alarm : allAlarms) {
3794             if (alarm.matches(packageName)) {
3795                 return true;
3796             }
3797         }
3798         return false;
3799     }
3800 
setLocked(int type, long when)3801     private void setLocked(int type, long when) {
3802         if (mInjector.isAlarmDriverPresent()) {
3803             mInjector.setAlarm(type, when);
3804         } else {
3805             Message msg = Message.obtain();
3806             msg.what = AlarmHandler.ALARM_EVENT;
3807 
3808             mHandler.removeMessages(msg.what);
3809             mHandler.sendMessageAtTime(msg, when);
3810         }
3811     }
3812 
dumpAlarmList(IndentingPrintWriter ipw, ArrayList<Alarm> list, long nowELAPSED, SimpleDateFormat sdf)3813     static final void dumpAlarmList(IndentingPrintWriter ipw, ArrayList<Alarm> list,
3814             long nowELAPSED, SimpleDateFormat sdf) {
3815         final int n = list.size();
3816         for (int i = n - 1; i >= 0; i--) {
3817             final Alarm a = list.get(i);
3818             final String label = Alarm.typeToString(a.type);
3819             ipw.print(label);
3820             ipw.print(" #");
3821             ipw.print(n - i);
3822             ipw.print(": ");
3823             ipw.println(a);
3824             ipw.increaseIndent();
3825             a.dump(ipw, nowELAPSED, sdf);
3826             ipw.decreaseIndent();
3827         }
3828     }
3829 
isExemptFromBatterySaver(Alarm alarm)3830     private static boolean isExemptFromBatterySaver(Alarm alarm) {
3831         if (alarm.alarmClock != null) {
3832             return true;
3833         }
3834         if ((alarm.operation != null)
3835                 && (alarm.operation.isActivity() || alarm.operation.isForegroundService())) {
3836             return true;
3837         }
3838         if (UserHandle.isCore(alarm.creatorUid)) {
3839             return true;
3840         }
3841         return false;
3842     }
3843 
isBackgroundRestricted(Alarm alarm)3844     private boolean isBackgroundRestricted(Alarm alarm) {
3845         if (alarm.alarmClock != null) {
3846             // Don't defer alarm clocks
3847             return false;
3848         }
3849         if (alarm.operation != null && alarm.operation.isActivity()) {
3850             // Don't defer starting actual UI
3851             return false;
3852         }
3853         final String sourcePackage = alarm.sourcePackage;
3854         final int sourceUid = alarm.creatorUid;
3855         if (UserHandle.isCore(sourceUid)) {
3856             return false;
3857         }
3858         return (mAppStateTracker != null) && mAppStateTracker.areAlarmsRestricted(sourceUid,
3859                 sourcePackage);
3860     }
3861 
init()3862     private static native long init();
close(long nativeData)3863     private static native void close(long nativeData);
set(long nativeData, int type, long seconds, long nanoseconds)3864     private static native int set(long nativeData, int type, long seconds, long nanoseconds);
waitForAlarm(long nativeData)3865     private static native int waitForAlarm(long nativeData);
setKernelTime(long nativeData, long millis)3866     private static native int setKernelTime(long nativeData, long millis);
setKernelTimezone(long nativeData, int minuteswest)3867     private static native int setKernelTimezone(long nativeData, int minuteswest);
getNextAlarm(long nativeData, int type)3868     private static native long getNextAlarm(long nativeData, int type);
3869 
triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED)3870     int triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED) {
3871         int wakeUps = 0;
3872         final ArrayList<Alarm> pendingAlarms = mAlarmStore.removePendingAlarms(nowELAPSED);
3873         for (final Alarm alarm : pendingAlarms) {
3874             if (isBackgroundRestricted(alarm)) {
3875                 // Alarms with FLAG_WAKE_FROM_IDLE or mPendingIdleUntil alarm are not deferred
3876                 if (DEBUG_BG_LIMIT) {
3877                     Slog.d(TAG, "Deferring alarm " + alarm + " due to user forced app standby");
3878                 }
3879                 ArrayList<Alarm> alarmsForUid = mPendingBackgroundAlarms.get(alarm.creatorUid);
3880                 if (alarmsForUid == null) {
3881                     alarmsForUid = new ArrayList<>();
3882                     mPendingBackgroundAlarms.put(alarm.creatorUid, alarmsForUid);
3883                 }
3884                 alarmsForUid.add(alarm);
3885                 continue;
3886             }
3887 
3888             alarm.count = 1;
3889             triggerList.add(alarm);
3890             if ((alarm.flags & FLAG_WAKE_FROM_IDLE) != 0) {
3891                 EventLogTags.writeDeviceIdleWakeFromIdle(mPendingIdleUntil != null ? 1 : 0,
3892                         alarm.statsTag);
3893             }
3894             if (mPendingIdleUntil == alarm) {
3895                 mPendingIdleUntil = null;
3896                 mAlarmStore.updateAlarmDeliveries(a -> adjustDeliveryTimeBasedOnDeviceIdle(a));
3897                 if (RECORD_DEVICE_IDLE_ALARMS) {
3898                     IdleDispatchEntry ent = new IdleDispatchEntry();
3899                     ent.uid = alarm.uid;
3900                     ent.pkg = alarm.sourcePackage;
3901                     ent.tag = alarm.statsTag;
3902                     ent.op = "END IDLE";
3903                     ent.elapsedRealtime = mInjector.getElapsedRealtime();
3904                     ent.argRealtime = alarm.getWhenElapsed();
3905                     mAllowWhileIdleDispatches.add(ent);
3906                 }
3907             }
3908             if (mNextWakeFromIdle == alarm) {
3909                 mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm();
3910                 // Note that we don't need to update mPendingIdleUntil because it should already
3911                 // be removed from the alarm store.
3912             }
3913 
3914             // Recurring alarms may have passed several alarm intervals while the
3915             // phone was asleep or off, so pass a trigger count when sending them.
3916             if (alarm.repeatInterval > 0) {
3917                 // this adjustment will be zero if we're late by
3918                 // less than one full repeat interval
3919                 alarm.count += (nowELAPSED - alarm.getRequestedElapsed()) / alarm.repeatInterval;
3920                 // Also schedule its next recurrence
3921                 final long delta = alarm.count * alarm.repeatInterval;
3922                 final long nextElapsed = alarm.getRequestedElapsed() + delta;
3923                 final long nextMaxElapsed = maxTriggerTime(nowELAPSED, nextElapsed,
3924                         alarm.repeatInterval);
3925                 setImplLocked(alarm.type, alarm.origWhen + delta, nextElapsed,
3926                         nextMaxElapsed - nextElapsed, alarm.repeatInterval, alarm.operation, null,
3927                         null, alarm.flags, alarm.workSource, alarm.alarmClock, alarm.uid,
3928                         alarm.packageName, null, EXACT_ALLOW_REASON_NOT_APPLICABLE);
3929             }
3930 
3931             if (alarm.wakeup) {
3932                 wakeUps++;
3933             }
3934 
3935             // We removed an alarm clock. Let the caller recompute the next alarm clock.
3936             if (alarm.alarmClock != null) {
3937                 mNextAlarmClockMayChange = true;
3938             }
3939         }
3940 
3941         // This is a new alarm delivery set; bump the sequence number to indicate that
3942         // all apps' alarm delivery classes should be recalculated.
3943         mCurrentSeq++;
3944         calculateDeliveryPriorities(triggerList);
3945         Collections.sort(triggerList, mAlarmDispatchComparator);
3946 
3947         if (localLOGV) {
3948             for (int i = 0; i < triggerList.size(); i++) {
3949                 Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
3950             }
3951         }
3952 
3953         return wakeUps;
3954     }
3955 
currentNonWakeupFuzzLocked(long nowELAPSED)3956     long currentNonWakeupFuzzLocked(long nowELAPSED) {
3957         long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
3958         if (timeSinceOn < 5 * 60 * 1000) {
3959             // If the screen has been off for 5 minutes, only delay by at most two minutes.
3960             return 2 * 60 * 1000;
3961         } else if (timeSinceOn < 30 * 60 * 1000) {
3962             // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
3963             return 15 * 60 * 1000;
3964         } else {
3965             // Otherwise, we will delay by at most an hour.
3966             return 60 * 60 * 1000;
3967         }
3968     }
3969 
checkAllowNonWakeupDelayLocked(long nowELAPSED)3970     boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
3971         if (mInteractive) {
3972             return false;
3973         }
3974         if (mLastAlarmDeliveryTime <= 0) {
3975             return false;
3976         }
3977         if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) {
3978             // This is just a little paranoia, if somehow we have pending non-wakeup alarms
3979             // and the next delivery time is in the past, then just deliver them all.  This
3980             // avoids bugs where we get stuck in a loop trying to poll for alarms.
3981             return false;
3982         }
3983         long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
3984         return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
3985     }
3986 
deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED)3987     void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
3988         mLastAlarmDeliveryTime = nowELAPSED;
3989         for (int i = 0; i < triggerList.size(); i++) {
3990             Alarm alarm = triggerList.get(i);
3991             if (alarm.wakeup) {
3992                 Trace.traceBegin(Trace.TRACE_TAG_POWER,
3993                         "Dispatch wakeup alarm to " + alarm.packageName);
3994             } else {
3995                 Trace.traceBegin(Trace.TRACE_TAG_POWER,
3996                         "Dispatch non-wakeup alarm to " + alarm.packageName);
3997             }
3998             try {
3999                 if (localLOGV) {
4000                     Slog.v(TAG, "sending alarm " + alarm);
4001                 }
4002                 if (RECORD_ALARMS_IN_HISTORY) {
4003                     mActivityManagerInternal.noteAlarmStart(alarm.operation, alarm.workSource,
4004                             alarm.uid, alarm.statsTag);
4005                 }
4006                 mDeliveryTracker.deliverLocked(alarm, nowELAPSED);
4007             } catch (RuntimeException e) {
4008                 Slog.w(TAG, "Failure sending alarm.", e);
4009             }
4010             Trace.traceEnd(Trace.TRACE_TAG_POWER);
4011             decrementAlarmCount(alarm.uid, 1);
4012         }
4013     }
4014 
4015     @VisibleForTesting
isExemptFromAppStandby(Alarm a)4016     static boolean isExemptFromAppStandby(Alarm a) {
4017         return a.alarmClock != null || UserHandle.isCore(a.creatorUid)
4018                 || (a.flags & (FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED | FLAG_ALLOW_WHILE_IDLE)) != 0;
4019     }
4020 
4021     @VisibleForTesting
4022     static class Injector {
4023         private long mNativeData;
4024         private Context mContext;
4025 
Injector(Context context)4026         Injector(Context context) {
4027             mContext = context;
4028         }
4029 
init()4030         void init() {
4031             System.loadLibrary("alarm_jni");
4032             mNativeData = AlarmManagerService.init();
4033         }
4034 
waitForAlarm()4035         int waitForAlarm() {
4036             return AlarmManagerService.waitForAlarm(mNativeData);
4037         }
4038 
isAlarmDriverPresent()4039         boolean isAlarmDriverPresent() {
4040             return mNativeData != 0;
4041         }
4042 
setAlarm(int type, long millis)4043         void setAlarm(int type, long millis) {
4044             // The kernel never triggers alarms with negative wakeup times
4045             // so we ensure they are positive.
4046             final long alarmSeconds, alarmNanoseconds;
4047             if (millis < 0) {
4048                 alarmSeconds = 0;
4049                 alarmNanoseconds = 0;
4050             } else {
4051                 alarmSeconds = millis / 1000;
4052                 alarmNanoseconds = (millis % 1000) * 1000 * 1000;
4053             }
4054 
4055             final int result = AlarmManagerService.set(mNativeData, type, alarmSeconds,
4056                     alarmNanoseconds);
4057             if (result != 0) {
4058                 final long nowElapsed = SystemClock.elapsedRealtime();
4059                 Slog.wtf(TAG, "Unable to set kernel alarm, now=" + nowElapsed
4060                         + " type=" + type + " @ (" + alarmSeconds + "," + alarmNanoseconds
4061                         + "), ret = " + result + " = " + Os.strerror(result));
4062             }
4063         }
4064 
getCallingUid()4065         int getCallingUid() {
4066             return Binder.getCallingUid();
4067         }
4068 
getNextAlarm(int type)4069         long getNextAlarm(int type) {
4070             return AlarmManagerService.getNextAlarm(mNativeData, type);
4071         }
4072 
setKernelTimezone(int minutesWest)4073         void setKernelTimezone(int minutesWest) {
4074             AlarmManagerService.setKernelTimezone(mNativeData, minutesWest);
4075         }
4076 
setKernelTime(long millis)4077         void setKernelTime(long millis) {
4078             if (mNativeData != 0) {
4079                 AlarmManagerService.setKernelTime(mNativeData, millis);
4080             }
4081         }
4082 
close()4083         void close() {
4084             AlarmManagerService.close(mNativeData);
4085         }
4086 
getElapsedRealtime()4087         long getElapsedRealtime() {
4088             return SystemClock.elapsedRealtime();
4089         }
4090 
getCurrentTimeMillis()4091         long getCurrentTimeMillis() {
4092             return System.currentTimeMillis();
4093         }
4094 
getAlarmWakeLock()4095         PowerManager.WakeLock getAlarmWakeLock() {
4096             final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
4097             return pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
4098         }
4099 
getSystemUiUid(PackageManagerInternal pm)4100         int getSystemUiUid(PackageManagerInternal pm) {
4101             return pm.getPackageUid(pm.getSystemUiServiceComponent().getPackageName(),
4102                     MATCH_SYSTEM_ONLY, USER_SYSTEM);
4103         }
4104 
getAppOpsService()4105         IAppOpsService getAppOpsService() {
4106             return IAppOpsService.Stub.asInterface(
4107                     ServiceManager.getService(Context.APP_OPS_SERVICE));
4108         }
4109 
getClockReceiver(AlarmManagerService service)4110         ClockReceiver getClockReceiver(AlarmManagerService service) {
4111             return service.new ClockReceiver();
4112         }
4113 
registerDeviceConfigListener(DeviceConfig.OnPropertiesChangedListener listener)4114         void registerDeviceConfigListener(DeviceConfig.OnPropertiesChangedListener listener) {
4115             DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ALARM_MANAGER,
4116                     JobSchedulerBackgroundThread.getExecutor(), listener);
4117         }
4118     }
4119 
4120     private class AlarmThread extends Thread {
4121         private int mFalseWakeups;
4122         private int mWtfThreshold;
4123 
AlarmThread()4124         AlarmThread() {
4125             super("AlarmManager");
4126             mFalseWakeups = 0;
4127             mWtfThreshold = 100;
4128         }
4129 
run()4130         public void run() {
4131             ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
4132 
4133             while (true) {
4134                 int result = mInjector.waitForAlarm();
4135                 final long nowRTC = mInjector.getCurrentTimeMillis();
4136                 final long nowELAPSED = mInjector.getElapsedRealtime();
4137                 synchronized (mLock) {
4138                     mLastWakeup = nowELAPSED;
4139                 }
4140                 if (result == 0) {
4141                     Slog.wtf(TAG, "waitForAlarm returned 0, nowRTC = " + nowRTC
4142                             + ", nowElapsed = " + nowELAPSED);
4143                 }
4144                 triggerList.clear();
4145 
4146                 if ((result & TIME_CHANGED_MASK) != 0) {
4147                     // The kernel can give us spurious time change notifications due to
4148                     // small adjustments it makes internally; we want to filter those out.
4149                     final long lastTimeChangeClockTime;
4150                     final long expectedClockTime;
4151                     synchronized (mLock) {
4152                         lastTimeChangeClockTime = mLastTimeChangeClockTime;
4153                         expectedClockTime = lastTimeChangeClockTime
4154                                 + (nowELAPSED - mLastTimeChangeRealtime);
4155                     }
4156                     if (lastTimeChangeClockTime == 0 || nowRTC < (expectedClockTime - 1000)
4157                             || nowRTC > (expectedClockTime + 1000)) {
4158                         // The change is by at least +/- 1000 ms (or this is the first change),
4159                         // let's do it!
4160                         if (DEBUG_BATCH) {
4161                             Slog.v(TAG, "Time changed notification from kernel; rebatching");
4162                         }
4163                         // StatsLog requires currentTimeMillis(), which == nowRTC to within usecs.
4164                         FrameworkStatsLog.write(FrameworkStatsLog.WALL_CLOCK_TIME_SHIFTED, nowRTC);
4165                         removeImpl(null, mTimeTickTrigger);
4166                         removeImpl(mDateChangeSender, null);
4167                         reevaluateRtcAlarms();
4168                         mClockReceiver.scheduleTimeTickEvent();
4169                         mClockReceiver.scheduleDateChangedEvent();
4170                         synchronized (mLock) {
4171                             mNumTimeChanged++;
4172                             mLastTimeChangeClockTime = nowRTC;
4173                             mLastTimeChangeRealtime = nowELAPSED;
4174                         }
4175                         Intent intent = new Intent(Intent.ACTION_TIME_CHANGED);
4176                         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
4177                                 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
4178                                 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
4179                                 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
4180                         mOptsTimeBroadcast.setTemporaryAppAllowlist(
4181                                 mActivityManagerInternal.getBootTimeTempAllowListDuration(),
4182                                 TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
4183                                 PowerExemptionManager.REASON_TIME_CHANGED, "");
4184                         getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
4185                                 null /* receiverPermission */, mOptsTimeBroadcast.toBundle());
4186                         // The world has changed on us, so we need to re-evaluate alarms
4187                         // regardless of whether the kernel has told us one went off.
4188                         result |= IS_WAKEUP_MASK;
4189                     }
4190                 }
4191 
4192                 if (result != TIME_CHANGED_MASK) {
4193                     // If this was anything besides just a time change, then figure what if
4194                     // anything to do about alarms.
4195                     synchronized (mLock) {
4196                         if (localLOGV) {
4197                             Slog.v(TAG, "Checking for alarms... rtc=" + nowRTC
4198                                             + ", elapsed=" + nowELAPSED);
4199                         }
4200 
4201                         mLastTrigger = nowELAPSED;
4202                         final int wakeUps = triggerAlarmsLocked(triggerList, nowELAPSED);
4203                         if (wakeUps == 0 && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
4204                             // if there are no wakeup alarms and the screen is off, we can
4205                             // delay what we have so far until the future.
4206                             if (mPendingNonWakeupAlarms.size() == 0) {
4207                                 mStartCurrentDelayTime = nowELAPSED;
4208                                 mNextNonWakeupDeliveryTime = nowELAPSED
4209                                         + ((currentNonWakeupFuzzLocked(nowELAPSED) * 3) / 2);
4210                             }
4211                             mPendingNonWakeupAlarms.addAll(triggerList);
4212                             mNumDelayedAlarms += triggerList.size();
4213                             rescheduleKernelAlarmsLocked();
4214                             updateNextAlarmClockLocked();
4215                         } else {
4216                             // now deliver the alarm intents; if there are pending non-wakeup
4217                             // alarms, we need to merge them in to the list.  note we don't
4218                             // just deliver them first because we generally want non-wakeup
4219                             // alarms delivered after wakeup alarms.
4220                             if (mPendingNonWakeupAlarms.size() > 0) {
4221                                 calculateDeliveryPriorities(mPendingNonWakeupAlarms);
4222                                 triggerList.addAll(mPendingNonWakeupAlarms);
4223                                 Collections.sort(triggerList, mAlarmDispatchComparator);
4224                                 final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
4225                                 mTotalDelayTime += thisDelayTime;
4226                                 if (mMaxDelayTime < thisDelayTime) {
4227                                     mMaxDelayTime = thisDelayTime;
4228                                 }
4229                                 mPendingNonWakeupAlarms.clear();
4230                             }
4231                             if (mLastTimeChangeRealtime != nowELAPSED && triggerList.isEmpty()) {
4232                                 if (++mFalseWakeups >= mWtfThreshold) {
4233                                     Slog.wtf(TAG, "Too many (" + mFalseWakeups
4234                                             + ") false wakeups, nowElapsed=" + nowELAPSED);
4235                                     if (mWtfThreshold < 100_000) {
4236                                         mWtfThreshold *= 10;
4237                                     } else {
4238                                         mFalseWakeups = 0;
4239                                     }
4240                                 }
4241                             }
4242                             final ArraySet<Pair<String, Integer>> triggerPackages =
4243                                     new ArraySet<>();
4244                             for (int i = 0; i < triggerList.size(); i++) {
4245                                 final Alarm a = triggerList.get(i);
4246                                 if (!isExemptFromAppStandby(a)) {
4247                                     triggerPackages.add(Pair.create(
4248                                             a.sourcePackage, UserHandle.getUserId(a.creatorUid)));
4249                                 }
4250                             }
4251                             deliverAlarmsLocked(triggerList, nowELAPSED);
4252                             reorderAlarmsBasedOnStandbyBuckets(triggerPackages);
4253                             rescheduleKernelAlarmsLocked();
4254                             updateNextAlarmClockLocked();
4255                             MetricsHelper.pushAlarmBatchDelivered(triggerList.size(), wakeUps);
4256                         }
4257                     }
4258 
4259                 } else {
4260                     // Just in case -- even though no wakeup flag was set, make sure
4261                     // we have updated the kernel to the next alarm time.
4262                     synchronized (mLock) {
4263                         rescheduleKernelAlarmsLocked();
4264                     }
4265                 }
4266             }
4267         }
4268     }
4269 
4270     /**
4271      * Attribute blame for a WakeLock.
4272      *
4273      * @param ws       WorkSource to attribute blame.
4274      * @param knownUid attribution uid; < 0 values are ignored.
4275      */
setWakelockWorkSource(WorkSource ws, int knownUid, String tag, boolean first)4276     void setWakelockWorkSource(WorkSource ws, int knownUid, String tag, boolean first) {
4277         try {
4278             mWakeLock.setHistoryTag(first ? tag : null);
4279 
4280             if (ws != null) {
4281                 mWakeLock.setWorkSource(ws);
4282                 return;
4283             }
4284 
4285             if (knownUid >= 0) {
4286                 mWakeLock.setWorkSource(new WorkSource(knownUid));
4287                 return;
4288             }
4289         } catch (Exception e) {
4290         }
4291 
4292         // Something went wrong; fall back to attributing the lock to the OS
4293         mWakeLock.setWorkSource(null);
4294     }
4295 
getAlarmAttributionUid(Alarm alarm)4296     private static int getAlarmAttributionUid(Alarm alarm) {
4297         if (alarm.workSource != null && !alarm.workSource.isEmpty()) {
4298             return alarm.workSource.getAttributionUid();
4299         }
4300 
4301         return alarm.creatorUid;
4302     }
4303 
4304 
4305     @VisibleForTesting
4306     class AlarmHandler extends Handler {
4307         public static final int ALARM_EVENT = 1;
4308         public static final int SEND_NEXT_ALARM_CLOCK_CHANGED = 2;
4309         public static final int LISTENER_TIMEOUT = 3;
4310         public static final int REPORT_ALARMS_ACTIVE = 4;
4311         public static final int APP_STANDBY_BUCKET_CHANGED = 5;
4312         public static final int CHARGING_STATUS_CHANGED = 6;
4313         public static final int REMOVE_FOR_CANCELED = 7;
4314         public static final int REMOVE_EXACT_ALARMS = 8;
4315         public static final int EXACT_ALARM_DENY_LIST_PACKAGES_ADDED = 9;
4316         public static final int EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED = 10;
4317         public static final int REFRESH_EXACT_ALARM_CANDIDATES = 11;
4318 
AlarmHandler()4319         AlarmHandler() {
4320             super(Looper.myLooper());
4321         }
4322 
4323         @Override
handleMessage(Message msg)4324         public void handleMessage(Message msg) {
4325             switch (msg.what) {
4326                 case ALARM_EVENT: {
4327                     // This code is used when the kernel timer driver is not available, which
4328                     // shouldn't happen. Here, we try our best to simulate it, which may be useful
4329                     // when porting Android to a new device. Note that we can't wake up a device
4330                     // this way, so WAKE_UP alarms will be delivered only when the device is awake.
4331                     ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
4332                     synchronized (mLock) {
4333                         final long nowELAPSED = mInjector.getElapsedRealtime();
4334                         triggerAlarmsLocked(triggerList, nowELAPSED);
4335                         updateNextAlarmClockLocked();
4336                     }
4337 
4338                     // now trigger the alarms without the lock held
4339                     for (int i = 0; i < triggerList.size(); i++) {
4340                         Alarm alarm = triggerList.get(i);
4341                         try {
4342                             alarm.operation.send();
4343                         } catch (PendingIntent.CanceledException e) {
4344                             if (alarm.repeatInterval > 0) {
4345                                 // This IntentSender is no longer valid, but this
4346                                 // is a repeating alarm, so toss the hoser.
4347                                 removeImpl(alarm.operation, null);
4348                             }
4349                         }
4350                         decrementAlarmCount(alarm.uid, 1);
4351                     }
4352                     break;
4353                 }
4354 
4355                 case SEND_NEXT_ALARM_CLOCK_CHANGED:
4356                     sendNextAlarmClockChanged();
4357                     break;
4358 
4359                 case LISTENER_TIMEOUT:
4360                     mDeliveryTracker.alarmTimedOut((IBinder) msg.obj);
4361                     break;
4362 
4363                 case REPORT_ALARMS_ACTIVE:
4364                     if (mLocalDeviceIdleController != null) {
4365                         mLocalDeviceIdleController.setAlarmsActive(msg.arg1 != 0);
4366                     }
4367                     break;
4368 
4369                 case CHARGING_STATUS_CHANGED:
4370                     synchronized (mLock) {
4371                         mAppStandbyParole = (Boolean) msg.obj;
4372                         if (reorderAlarmsBasedOnStandbyBuckets(null)) {
4373                             rescheduleKernelAlarmsLocked();
4374                             updateNextAlarmClockLocked();
4375                         }
4376                     }
4377                     break;
4378 
4379                 case APP_STANDBY_BUCKET_CHANGED:
4380                     synchronized (mLock) {
4381                         final ArraySet<Pair<String, Integer>> filterPackages = new ArraySet<>();
4382                         filterPackages.add(Pair.create((String) msg.obj, msg.arg1));
4383                         if (reorderAlarmsBasedOnStandbyBuckets(filterPackages)) {
4384                             rescheduleKernelAlarmsLocked();
4385                             updateNextAlarmClockLocked();
4386                         }
4387                     }
4388                     break;
4389 
4390                 case REMOVE_FOR_CANCELED:
4391                     final PendingIntent operation = (PendingIntent) msg.obj;
4392                     synchronized (mLock) {
4393                         removeLocked(operation, null, REMOVE_REASON_PI_CANCELLED);
4394                     }
4395                     break;
4396 
4397                 case REMOVE_EXACT_ALARMS:
4398                     final int uid = msg.arg1;
4399                     final String packageName = (String) msg.obj;
4400                     synchronized (mLock) {
4401                         removeExactAlarmsOnPermissionRevokedLocked(uid, packageName);
4402                     }
4403                     break;
4404                 case EXACT_ALARM_DENY_LIST_PACKAGES_ADDED:
4405                     handleChangesToExactAlarmDenyList((ArraySet<String>) msg.obj, true);
4406                     break;
4407                 case EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED:
4408                     handleChangesToExactAlarmDenyList((ArraySet<String>) msg.obj, false);
4409                     break;
4410                 case REFRESH_EXACT_ALARM_CANDIDATES:
4411                     refreshExactAlarmCandidates();
4412                     break;
4413                 default:
4414                     // nope, just ignore it
4415                     break;
4416             }
4417         }
4418     }
4419 
4420     @VisibleForTesting
4421     class ChargingReceiver extends BroadcastReceiver {
ChargingReceiver()4422         ChargingReceiver() {
4423             IntentFilter filter = new IntentFilter();
4424             filter.addAction(BatteryManager.ACTION_CHARGING);
4425             filter.addAction(BatteryManager.ACTION_DISCHARGING);
4426             getContext().registerReceiver(this, filter);
4427         }
4428 
4429         @Override
onReceive(Context context, Intent intent)4430         public void onReceive(Context context, Intent intent) {
4431             final String action = intent.getAction();
4432             final boolean charging;
4433             if (BatteryManager.ACTION_CHARGING.equals(action)) {
4434                 if (DEBUG_STANDBY) {
4435                     Slog.d(TAG, "Device is charging.");
4436                 }
4437                 charging = true;
4438             } else {
4439                 if (DEBUG_STANDBY) {
4440                     Slog.d(TAG, "Disconnected from power.");
4441                 }
4442                 charging = false;
4443             }
4444             mHandler.removeMessages(AlarmHandler.CHARGING_STATUS_CHANGED);
4445             mHandler.obtainMessage(AlarmHandler.CHARGING_STATUS_CHANGED, charging)
4446                     .sendToTarget();
4447         }
4448     }
4449 
4450     @VisibleForTesting
4451     class ClockReceiver extends BroadcastReceiver {
ClockReceiver()4452         public ClockReceiver() {
4453             IntentFilter filter = new IntentFilter();
4454             filter.addAction(Intent.ACTION_DATE_CHANGED);
4455             getContext().registerReceiver(this, filter);
4456         }
4457 
4458         @Override
onReceive(Context context, Intent intent)4459         public void onReceive(Context context, Intent intent) {
4460             if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED)) {
4461                 // Since the kernel does not keep track of DST, we need to
4462                 // reset the TZ information at the beginning of each day
4463                 // based off of the current Zone gmt offset + userspace tracked
4464                 // daylight savings information.
4465                 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
4466                 int gmtOffset = zone.getOffset(mInjector.getCurrentTimeMillis());
4467                 mInjector.setKernelTimezone(-(gmtOffset / 60000));
4468                 scheduleDateChangedEvent();
4469             }
4470         }
4471 
scheduleTimeTickEvent()4472         public void scheduleTimeTickEvent() {
4473             final long currentTime = mInjector.getCurrentTimeMillis();
4474             final long nextTime = 60000 * ((currentTime / 60000) + 1);
4475 
4476             // Schedule this event for the amount of time that it would take to get to
4477             // the top of the next minute.
4478             final long tickEventDelay = nextTime - currentTime;
4479 
4480             final WorkSource workSource = null; // Let system take blame for time tick events.
4481 
4482             int flags = AlarmManager.FLAG_STANDALONE;
4483             flags |= mConstants.TIME_TICK_ALLOWED_WHILE_IDLE ? FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
4484                     : 0;
4485 
4486             setImpl(ELAPSED_REALTIME, mInjector.getElapsedRealtime() + tickEventDelay, 0,
4487                     0, null, mTimeTickTrigger, TIME_TICK_TAG, flags, workSource, null,
4488                     Process.myUid(), "android", null, EXACT_ALLOW_REASON_ALLOW_LIST);
4489 
4490             // Finally, remember when we set the tick alarm
4491             synchronized (mLock) {
4492                 mLastTickSet = currentTime;
4493             }
4494         }
4495 
scheduleDateChangedEvent()4496         public void scheduleDateChangedEvent() {
4497             Calendar calendar = Calendar.getInstance();
4498             calendar.setTimeInMillis(mInjector.getCurrentTimeMillis());
4499             calendar.set(Calendar.HOUR_OF_DAY, 0);
4500             calendar.set(Calendar.MINUTE, 0);
4501             calendar.set(Calendar.SECOND, 0);
4502             calendar.set(Calendar.MILLISECOND, 0);
4503             calendar.add(Calendar.DAY_OF_MONTH, 1);
4504 
4505             final WorkSource workSource = null; // Let system take blame for date change events.
4506             setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender, null, null,
4507                     AlarmManager.FLAG_STANDALONE, workSource, null,
4508                     Process.myUid(), "android", null, EXACT_ALLOW_REASON_ALLOW_LIST);
4509         }
4510     }
4511 
4512     class InteractiveStateReceiver extends BroadcastReceiver {
InteractiveStateReceiver()4513         public InteractiveStateReceiver() {
4514             IntentFilter filter = new IntentFilter();
4515             filter.addAction(Intent.ACTION_SCREEN_OFF);
4516             filter.addAction(Intent.ACTION_SCREEN_ON);
4517             filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
4518             getContext().registerReceiver(this, filter);
4519         }
4520 
4521         @Override
onReceive(Context context, Intent intent)4522         public void onReceive(Context context, Intent intent) {
4523             synchronized (mLock) {
4524                 interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
4525             }
4526         }
4527     }
4528 
4529     class UninstallReceiver extends BroadcastReceiver {
UninstallReceiver()4530         public UninstallReceiver() {
4531             IntentFilter filter = new IntentFilter();
4532             filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
4533             filter.addAction(Intent.ACTION_PACKAGE_ADDED);
4534             filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
4535             filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
4536             filter.addDataScheme(IntentFilter.SCHEME_PACKAGE);
4537             getContext().registerReceiver(this, filter);
4538             // Register for events related to sdcard installation.
4539             IntentFilter sdFilter = new IntentFilter();
4540             sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
4541             sdFilter.addAction(Intent.ACTION_USER_STOPPED);
4542             sdFilter.addAction(Intent.ACTION_UID_REMOVED);
4543             getContext().registerReceiver(this, sdFilter);
4544         }
4545 
4546         @Override
onReceive(Context context, Intent intent)4547         public void onReceive(Context context, Intent intent) {
4548             final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
4549             synchronized (mLock) {
4550                 String pkgList[] = null;
4551                 switch (intent.getAction()) {
4552                     case Intent.ACTION_QUERY_PACKAGE_RESTART:
4553                         pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
4554                         for (String packageName : pkgList) {
4555                             if (lookForPackageLocked(packageName)) {
4556                                 setResultCode(Activity.RESULT_OK);
4557                                 return;
4558                             }
4559                         }
4560                         return;
4561                     case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
4562                         pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
4563                         break;
4564                     case Intent.ACTION_USER_STOPPED:
4565                         final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
4566                         if (userHandle >= 0) {
4567                             removeUserLocked(userHandle);
4568                             mAppWakeupHistory.removeForUser(userHandle);
4569                             mAllowWhileIdleHistory.removeForUser(userHandle);
4570                             mAllowWhileIdleCompatHistory.removeForUser(userHandle);
4571                         }
4572                         return;
4573                     case Intent.ACTION_UID_REMOVED:
4574                         mLastPriorityAlarmDispatch.delete(uid);
4575                         mRemovalHistory.delete(uid);
4576                         mLastOpScheduleExactAlarm.delete(uid);
4577                         return;
4578                     case Intent.ACTION_PACKAGE_REMOVED:
4579                         if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
4580                             // This package is being updated; don't kill its alarms.
4581                             // We will refresh the exact alarm candidates on subsequent receipt of
4582                             // PACKAGE_ADDED.
4583                             return;
4584                         }
4585                         mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES);
4586                         // Intentional fall-through.
4587                     case Intent.ACTION_PACKAGE_RESTARTED:
4588                         final Uri data = intent.getData();
4589                         if (data != null) {
4590                             final String pkg = data.getSchemeSpecificPart();
4591                             if (pkg != null) {
4592                                 pkgList = new String[]{pkg};
4593                             }
4594                         }
4595                         break;
4596                     case Intent.ACTION_PACKAGE_ADDED:
4597                         mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES);
4598                         return;
4599                 }
4600                 if (pkgList != null && (pkgList.length > 0)) {
4601                     for (String pkg : pkgList) {
4602                         if (uid >= 0) {
4603                             // package-removed and package-restarted case
4604                             mAppWakeupHistory.removeForPackage(pkg, UserHandle.getUserId(uid));
4605                             mAllowWhileIdleHistory.removeForPackage(pkg, UserHandle.getUserId(uid));
4606                             mAllowWhileIdleCompatHistory.removeForPackage(pkg,
4607                                     UserHandle.getUserId(uid));
4608                             removeLocked(uid, REMOVE_REASON_UNDEFINED);
4609                         } else {
4610                             // external-applications-unavailable case
4611                             removeLocked(pkg);
4612                         }
4613                         mPriorities.remove(pkg);
4614                         for (int i = mBroadcastStats.size() - 1; i >= 0; i--) {
4615                             ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
4616                             if (uidStats.remove(pkg) != null) {
4617                                 if (uidStats.size() <= 0) {
4618                                     mBroadcastStats.removeAt(i);
4619                                 }
4620                             }
4621                         }
4622                     }
4623                 }
4624             }
4625         }
4626     }
4627 
4628     /**
4629      * Tracking of app assignments to standby buckets
4630      */
4631     private final class AppStandbyTracker extends AppIdleStateChangeListener {
4632         @Override
onAppIdleStateChanged(final String packageName, final @UserIdInt int userId, boolean idle, int bucket, int reason)4633         public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
4634                 boolean idle, int bucket, int reason) {
4635             if (DEBUG_STANDBY) {
4636                 Slog.d(TAG, "Package " + packageName + " for user " + userId + " now in bucket " +
4637                         bucket);
4638             }
4639             mHandler.obtainMessage(AlarmHandler.APP_STANDBY_BUCKET_CHANGED, userId, -1, packageName)
4640                     .sendToTarget();
4641         }
4642     }
4643 
4644     private final Listener mForceAppStandbyListener = new Listener() {
4645 
4646         @Override
4647         public void updateAllAlarms() {
4648             // Called when:
4649             // 1. Power exemption list changes,
4650             // 2. Battery saver state is toggled,
4651             // 3. Any package is moved into or out of the EXEMPTED bucket.
4652             synchronized (mLock) {
4653                 if (mAlarmStore.updateAlarmDeliveries(
4654                         a -> adjustDeliveryTimeBasedOnBatterySaver(a))) {
4655                     rescheduleKernelAlarmsLocked();
4656                 }
4657             }
4658         }
4659 
4660         @Override
4661         public void updateAlarmsForUid(int uid) {
4662             // Called when the given uid's state switches b/w active and idle.
4663             synchronized (mLock) {
4664                 if (mAlarmStore.updateAlarmDeliveries(a -> {
4665                     if (a.creatorUid != uid) {
4666                         return false;
4667                     }
4668                     return adjustDeliveryTimeBasedOnBatterySaver(a);
4669                 })) {
4670                     rescheduleKernelAlarmsLocked();
4671                 }
4672             }
4673         }
4674 
4675         @Override
4676         public void unblockAllUnrestrictedAlarms() {
4677             // Called when:
4678             // 1. Power exemption list changes,
4679             // 2. User FAS feature is disabled.
4680             synchronized (mLock) {
4681                 sendAllUnrestrictedPendingBackgroundAlarmsLocked();
4682             }
4683         }
4684 
4685         @Override
4686         public void unblockAlarmsForUid(int uid) {
4687             synchronized (mLock) {
4688                 // Called when the given uid becomes active.
4689                 sendPendingBackgroundAlarmsLocked(uid, null);
4690             }
4691         }
4692 
4693         @Override
4694         public void unblockAlarmsForUidPackage(int uid, String packageName) {
4695             // Called when user turns off FAS for this (uid, package).
4696             synchronized (mLock) {
4697                 sendPendingBackgroundAlarmsLocked(uid, packageName);
4698             }
4699         }
4700 
4701         @Override
4702         public void removeAlarmsForUid(int uid) {
4703             synchronized (mLock) {
4704                 removeForStoppedLocked(uid);
4705             }
4706         }
4707     };
4708 
getStatsLocked(PendingIntent pi)4709     private final BroadcastStats getStatsLocked(PendingIntent pi) {
4710         String pkg = pi.getCreatorPackage();
4711         int uid = pi.getCreatorUid();
4712         return getStatsLocked(uid, pkg);
4713     }
4714 
getStatsLocked(int uid, String pkgName)4715     private final BroadcastStats getStatsLocked(int uid, String pkgName) {
4716         ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.get(uid);
4717         if (uidStats == null) {
4718             uidStats = new ArrayMap<String, BroadcastStats>();
4719             mBroadcastStats.put(uid, uidStats);
4720         }
4721         BroadcastStats bs = uidStats.get(pkgName);
4722         if (bs == null) {
4723             bs = new BroadcastStats(uid, pkgName);
4724             uidStats.put(pkgName, bs);
4725         }
4726         return bs;
4727     }
4728 
4729     /**
4730      * Canonical count of (operation.send() - onSendFinished()) and
4731      * listener send/complete/timeout invocations.
4732      * Guarded by the usual lock.
4733      */
4734     @GuardedBy("mLock")
4735     private int mSendCount = 0;
4736     @GuardedBy("mLock")
4737     private int mSendFinishCount = 0;
4738     @GuardedBy("mLock")
4739     private int mListenerCount = 0;
4740     @GuardedBy("mLock")
4741     private int mListenerFinishCount = 0;
4742 
4743     class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished {
4744 
removeLocked(PendingIntent pi, Intent intent)4745         private InFlight removeLocked(PendingIntent pi, Intent intent) {
4746             for (int i = 0; i < mInFlight.size(); i++) {
4747                 final InFlight inflight = mInFlight.get(i);
4748                 if (inflight.mPendingIntent == pi) {
4749                     if (pi.isBroadcast()) {
4750                         notifyBroadcastAlarmCompleteLocked(inflight.mUid);
4751                     }
4752                     return mInFlight.remove(i);
4753                 }
4754             }
4755             mLog.w("No in-flight alarm for " + pi + " " + intent);
4756             return null;
4757         }
4758 
removeLocked(IBinder listener)4759         private InFlight removeLocked(IBinder listener) {
4760             for (int i = 0; i < mInFlight.size(); i++) {
4761                 if (mInFlight.get(i).mListener == listener) {
4762                     return mInFlight.remove(i);
4763                 }
4764             }
4765             mLog.w("No in-flight alarm for listener " + listener);
4766             return null;
4767         }
4768 
updateStatsLocked(InFlight inflight)4769         private void updateStatsLocked(InFlight inflight) {
4770             final long nowELAPSED = mInjector.getElapsedRealtime();
4771             BroadcastStats bs = inflight.mBroadcastStats;
4772             bs.nesting--;
4773             if (bs.nesting <= 0) {
4774                 bs.nesting = 0;
4775                 bs.aggregateTime += nowELAPSED - bs.startTime;
4776             }
4777             FilterStats fs = inflight.mFilterStats;
4778             fs.nesting--;
4779             if (fs.nesting <= 0) {
4780                 fs.nesting = 0;
4781                 fs.aggregateTime += nowELAPSED - fs.startTime;
4782             }
4783             if (RECORD_ALARMS_IN_HISTORY) {
4784                 mActivityManagerInternal.noteAlarmFinish(inflight.mPendingIntent,
4785                         inflight.mWorkSource, inflight.mUid, inflight.mTag);
4786             }
4787         }
4788 
updateTrackingLocked(InFlight inflight)4789         private void updateTrackingLocked(InFlight inflight) {
4790             if (inflight != null) {
4791                 updateStatsLocked(inflight);
4792             }
4793             mBroadcastRefCount--;
4794             if (DEBUG_WAKELOCK) {
4795                 Slog.d(TAG, "mBroadcastRefCount -> " + mBroadcastRefCount);
4796             }
4797             if (mBroadcastRefCount == 0) {
4798                 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
4799                 mWakeLock.release();
4800                 if (mInFlight.size() > 0) {
4801                     mLog.w("Finished all dispatches with " + mInFlight.size()
4802                             + " remaining inflights");
4803                     for (int i = 0; i < mInFlight.size(); i++) {
4804                         mLog.w("  Remaining #" + i + ": " + mInFlight.get(i));
4805                     }
4806                     mInFlight.clear();
4807                 }
4808             } else {
4809                 // the next of our alarms is now in flight.  reattribute the wakelock.
4810                 if (mInFlight.size() > 0) {
4811                     InFlight inFlight = mInFlight.get(0);
4812                     setWakelockWorkSource(inFlight.mWorkSource, inFlight.mCreatorUid, inFlight.mTag,
4813                             false);
4814                 } else {
4815                     // should never happen
4816                     mLog.w("Alarm wakelock still held but sent queue empty");
4817                     mWakeLock.setWorkSource(null);
4818                 }
4819             }
4820         }
4821 
4822         /**
4823          * Callback that arrives when a direct-call alarm reports that delivery has finished
4824          */
4825         @Override
alarmComplete(IBinder who)4826         public void alarmComplete(IBinder who) {
4827             if (who == null) {
4828                 mLog.w("Invalid alarmComplete: uid=" + Binder.getCallingUid()
4829                         + " pid=" + Binder.getCallingPid());
4830                 return;
4831             }
4832 
4833             final long ident = Binder.clearCallingIdentity();
4834             try {
4835                 synchronized (mLock) {
4836                     mHandler.removeMessages(AlarmHandler.LISTENER_TIMEOUT, who);
4837                     InFlight inflight = removeLocked(who);
4838                     if (inflight != null) {
4839                         if (DEBUG_LISTENER_CALLBACK) {
4840                             Slog.i(TAG, "alarmComplete() from " + who);
4841                         }
4842                         updateTrackingLocked(inflight);
4843                         mListenerFinishCount++;
4844                     } else {
4845                         // Delivery timed out, and the timeout handling already took care of
4846                         // updating our tracking here, so we needn't do anything further.
4847                         if (DEBUG_LISTENER_CALLBACK) {
4848                             Slog.i(TAG, "Late alarmComplete() from " + who);
4849                         }
4850                     }
4851                 }
4852             } finally {
4853                 Binder.restoreCallingIdentity(ident);
4854             }
4855         }
4856 
4857         /**
4858          * Callback that arrives when a PendingIntent alarm has finished delivery
4859          */
4860         @Override
onSendFinished(PendingIntent pi, Intent intent, int resultCode, String resultData, Bundle resultExtras)4861         public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
4862                 String resultData, Bundle resultExtras) {
4863             synchronized (mLock) {
4864                 mSendFinishCount++;
4865                 updateTrackingLocked(removeLocked(pi, intent));
4866             }
4867         }
4868 
4869         /**
4870          * Timeout of a direct-call alarm delivery
4871          */
alarmTimedOut(IBinder who)4872         public void alarmTimedOut(IBinder who) {
4873             synchronized (mLock) {
4874                 InFlight inflight = removeLocked(who);
4875                 if (inflight != null) {
4876                     // TODO: implement ANR policy for the target
4877                     if (DEBUG_LISTENER_CALLBACK) {
4878                         Slog.i(TAG, "Alarm listener " + who + " timed out in delivery");
4879                     }
4880                     updateTrackingLocked(inflight);
4881                     mListenerFinishCount++;
4882                 } else {
4883                     if (DEBUG_LISTENER_CALLBACK) {
4884                         Slog.i(TAG, "Spurious timeout of listener " + who);
4885                     }
4886                     mLog.w("Spurious timeout of listener " + who);
4887                 }
4888             }
4889         }
4890 
4891         /**
4892          * Deliver an alarm and set up the post-delivery handling appropriately
4893          */
4894         @GuardedBy("mLock")
deliverLocked(Alarm alarm, long nowELAPSED)4895         public void deliverLocked(Alarm alarm, long nowELAPSED) {
4896             final long workSourceToken = ThreadLocalWorkSource.setUid(
4897                     getAlarmAttributionUid(alarm));
4898             try {
4899                 if (alarm.operation != null) {
4900                     // PendingIntent alarm
4901                     mSendCount++;
4902 
4903                     try {
4904                         alarm.operation.send(getContext(), 0,
4905                                 mBackgroundIntent.putExtra(Intent.EXTRA_ALARM_COUNT, alarm.count),
4906                                 mDeliveryTracker, mHandler, null, alarm.mIdleOptions);
4907                     } catch (PendingIntent.CanceledException e) {
4908                         if (alarm.repeatInterval > 0) {
4909                             // This IntentSender is no longer valid, but this
4910                             // is a repeating alarm, so toss it
4911                             removeImpl(alarm.operation, null);
4912                         }
4913                         // No actual delivery was possible, so the delivery tracker's
4914                         // 'finished' callback won't be invoked.  We also don't need
4915                         // to do any wakelock or stats tracking, so we have nothing
4916                         // left to do here but go on to the next thing.
4917                         mSendFinishCount++;
4918                         return;
4919                     }
4920                 } else {
4921                     // Direct listener callback alarm
4922                     mListenerCount++;
4923 
4924                     alarm.listener.asBinder().unlinkToDeath(mListenerDeathRecipient, 0);
4925 
4926                     if (RECORD_ALARMS_IN_HISTORY) {
4927                         if (alarm.listener == mTimeTickTrigger) {
4928                             mTickHistory[mNextTickHistory++] = nowELAPSED;
4929                             if (mNextTickHistory >= TICK_HISTORY_DEPTH) {
4930                                 mNextTickHistory = 0;
4931                             }
4932                         }
4933                     }
4934 
4935                     try {
4936                         if (DEBUG_LISTENER_CALLBACK) {
4937                             Slog.v(TAG, "Alarm to uid=" + alarm.uid
4938                                     + " listener=" + alarm.listener.asBinder());
4939                         }
4940                         alarm.listener.doAlarm(this);
4941                         mHandler.sendMessageDelayed(
4942                                 mHandler.obtainMessage(AlarmHandler.LISTENER_TIMEOUT,
4943                                         alarm.listener.asBinder()),
4944                                 mConstants.LISTENER_TIMEOUT);
4945                     } catch (Exception e) {
4946                         if (DEBUG_LISTENER_CALLBACK) {
4947                             Slog.i(TAG, "Alarm undeliverable to listener "
4948                                     + alarm.listener.asBinder(), e);
4949                         }
4950                         // As in the PendingIntent.CanceledException case, delivery of the
4951                         // alarm was not possible, so we have no wakelock or timeout or
4952                         // stats management to do.  It threw before we posted the delayed
4953                         // timeout message, so we're done here.
4954                         mListenerFinishCount++;
4955                         return;
4956                     }
4957                 }
4958             } finally {
4959                 ThreadLocalWorkSource.restore(workSourceToken);
4960             }
4961 
4962             // The alarm is now in flight; now arrange wakelock and stats tracking
4963             if (DEBUG_WAKELOCK) {
4964                 Slog.d(TAG, "mBroadcastRefCount -> " + (mBroadcastRefCount + 1));
4965             }
4966             if (mBroadcastRefCount == 0) {
4967                 setWakelockWorkSource(alarm.workSource, alarm.creatorUid, alarm.statsTag, true);
4968                 mWakeLock.acquire();
4969                 mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget();
4970             }
4971             final InFlight inflight = new InFlight(AlarmManagerService.this, alarm, nowELAPSED);
4972             mInFlight.add(inflight);
4973             mBroadcastRefCount++;
4974             if (inflight.isBroadcast()) {
4975                 notifyBroadcastAlarmPendingLocked(alarm.uid);
4976             }
4977             final boolean doze = (mPendingIdleUntil != null);
4978             final boolean batterySaver = (mAppStateTracker != null
4979                     && mAppStateTracker.isForceAllAppsStandbyEnabled());
4980             if (doze || batterySaver) {
4981                 if (isAllowedWhileIdleRestricted(alarm)) {
4982                     // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm while the
4983                     // device was in doze or battery saver.
4984                     final AppWakeupHistory history = ((alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0)
4985                             ? mAllowWhileIdleHistory
4986                             : mAllowWhileIdleCompatHistory;
4987                     history.recordAlarmForPackage(alarm.sourcePackage,
4988                             UserHandle.getUserId(alarm.creatorUid), nowELAPSED);
4989                     mAlarmStore.updateAlarmDeliveries(a -> {
4990                         if (a.creatorUid != alarm.creatorUid || !isAllowedWhileIdleRestricted(a)) {
4991                             return false;
4992                         }
4993                         final boolean dozeAdjusted = doze && adjustDeliveryTimeBasedOnDeviceIdle(a);
4994                         final boolean batterySaverAdjusted =
4995                                 batterySaver && adjustDeliveryTimeBasedOnBatterySaver(a);
4996                         return dozeAdjusted || batterySaverAdjusted;
4997                     });
4998                 } else if ((alarm.flags & FLAG_PRIORITIZE) != 0) {
4999                     mLastPriorityAlarmDispatch.put(alarm.creatorUid, nowELAPSED);
5000                     mAlarmStore.updateAlarmDeliveries(a -> {
5001                         if (a.creatorUid != alarm.creatorUid
5002                                 || (alarm.flags & FLAG_PRIORITIZE) == 0) {
5003                             return false;
5004                         }
5005                         final boolean dozeAdjusted = doze && adjustDeliveryTimeBasedOnDeviceIdle(a);
5006                         final boolean batterySaverAdjusted =
5007                                 batterySaver && adjustDeliveryTimeBasedOnBatterySaver(a);
5008                         return dozeAdjusted || batterySaverAdjusted;
5009                     });
5010                 }
5011                 if (RECORD_DEVICE_IDLE_ALARMS) {
5012                     IdleDispatchEntry ent = new IdleDispatchEntry();
5013                     ent.uid = alarm.uid;
5014                     ent.pkg = alarm.packageName;
5015                     ent.tag = alarm.statsTag;
5016                     ent.op = "DELIVER";
5017                     ent.elapsedRealtime = nowELAPSED;
5018                     mAllowWhileIdleDispatches.add(ent);
5019                 }
5020             }
5021             if (!isExemptFromAppStandby(alarm)) {
5022                 mAppWakeupHistory.recordAlarmForPackage(alarm.sourcePackage,
5023                         UserHandle.getUserId(alarm.creatorUid), nowELAPSED);
5024             }
5025             final BroadcastStats bs = inflight.mBroadcastStats;
5026             bs.count++;
5027             if (bs.nesting == 0) {
5028                 bs.nesting = 1;
5029                 bs.startTime = nowELAPSED;
5030             } else {
5031                 bs.nesting++;
5032             }
5033             final FilterStats fs = inflight.mFilterStats;
5034             fs.count++;
5035             if (fs.nesting == 0) {
5036                 fs.nesting = 1;
5037                 fs.startTime = nowELAPSED;
5038             } else {
5039                 fs.nesting++;
5040             }
5041             if (alarm.type == ELAPSED_REALTIME_WAKEUP
5042                     || alarm.type == RTC_WAKEUP) {
5043                 bs.numWakeup++;
5044                 fs.numWakeup++;
5045                 mActivityManagerInternal.noteWakeupAlarm(
5046                         alarm.operation, alarm.workSource, alarm.uid, alarm.packageName,
5047                         alarm.statsTag);
5048             }
5049         }
5050     }
5051 
incrementAlarmCount(int uid)5052     private void incrementAlarmCount(int uid) {
5053         final int uidIndex = mAlarmsPerUid.indexOfKey(uid);
5054         if (uidIndex >= 0) {
5055             mAlarmsPerUid.setValueAt(uidIndex, mAlarmsPerUid.valueAt(uidIndex) + 1);
5056         } else {
5057             mAlarmsPerUid.put(uid, 1);
5058         }
5059     }
5060 
5061     /**
5062      * Send {@link AlarmManager#ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED} to
5063      * the app that is just granted the permission.
5064      */
sendScheduleExactAlarmPermissionStateChangedBroadcast( String packageName, int userId)5065     private void sendScheduleExactAlarmPermissionStateChangedBroadcast(
5066             String packageName, int userId) {
5067         final Intent i = new Intent(
5068                 AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED);
5069         i.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
5070                 | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
5071                 | Intent.FLAG_RECEIVER_FOREGROUND);
5072         i.setPackage(packageName);
5073 
5074         // We need to allow the app to start a foreground service.
5075         // This broadcast is very rare, so we do not cache the BroadcastOptions.
5076         final BroadcastOptions opts = BroadcastOptions.makeBasic();
5077         opts.setTemporaryAppAllowlist(
5078                 mActivityManagerInternal.getBootTimeTempAllowListDuration(),
5079                 TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
5080                 REASON_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED, "");
5081         getContext().sendBroadcastAsUser(i, UserHandle.of(userId), /*permission*/ null,
5082                 opts.toBundle());
5083     }
5084 
decrementAlarmCount(int uid, int decrement)5085     private void decrementAlarmCount(int uid, int decrement) {
5086         int oldCount = 0;
5087         final int uidIndex = mAlarmsPerUid.indexOfKey(uid);
5088         if (uidIndex >= 0) {
5089             oldCount = mAlarmsPerUid.valueAt(uidIndex);
5090             if (oldCount > decrement) {
5091                 mAlarmsPerUid.setValueAt(uidIndex, oldCount - decrement);
5092             } else {
5093                 mAlarmsPerUid.removeAt(uidIndex);
5094             }
5095         }
5096         if (oldCount < decrement) {
5097             Slog.wtf(TAG, "Attempt to decrement existing alarm count " + oldCount + " by "
5098                     + decrement + " for uid " + uid);
5099         }
5100     }
5101 
5102     private class ShellCmd extends ShellCommand {
5103 
getBinderService()5104         IAlarmManager getBinderService() {
5105             return IAlarmManager.Stub.asInterface(mService);
5106         }
5107 
5108         @Override
onCommand(String cmd)5109         public int onCommand(String cmd) {
5110             if (cmd == null) {
5111                 return handleDefaultCommands(cmd);
5112             }
5113 
5114             final PrintWriter pw = getOutPrintWriter();
5115             try {
5116                 switch (cmd) {
5117                     case "set-time":
5118                         final long millis = Long.parseLong(getNextArgRequired());
5119                         return (getBinderService().setTime(millis)) ? 0 : -1;
5120                     case "set-timezone":
5121                         final String tz = getNextArgRequired();
5122                         getBinderService().setTimeZone(tz);
5123                         return 0;
5124                     case "get-config-version":
5125                         final int version = getBinderService().getConfigVersion();
5126                         pw.println(version);
5127                         return 0;
5128                     default:
5129                         return handleDefaultCommands(cmd);
5130                 }
5131             } catch (Exception e) {
5132                 pw.println(e);
5133             }
5134             return -1;
5135         }
5136 
5137         @Override
onHelp()5138         public void onHelp() {
5139             PrintWriter pw = getOutPrintWriter();
5140             pw.println("Alarm manager service (alarm) commands:");
5141             pw.println("  help");
5142             pw.println("    Print this help text.");
5143             pw.println("  set-time TIME");
5144             pw.println("    Set the system clock time to TIME where TIME is milliseconds");
5145             pw.println("    since the Epoch.");
5146             pw.println("  set-timezone TZ");
5147             pw.println("    Set the system timezone to TZ where TZ is an Olson id.");
5148             pw.println("  get-config-version");
5149             pw.println("    Returns an integer denoting the version of device_config keys the"
5150                     + " service is sync'ed to. As long as this returns the same version, the values"
5151                     + " of the config are guaranteed to remain the same.");
5152         }
5153     }
5154 }
5155