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