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