1 /** 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations 14 * under the License. 15 */ 16 17 package com.android.server.usage; 18 19 import static android.app.usage.UsageEvents.Event.CHOOSER_ACTION; 20 import static android.app.usage.UsageEvents.Event.CONFIGURATION_CHANGE; 21 import static android.app.usage.UsageEvents.Event.DEVICE_EVENT_PACKAGE_NAME; 22 import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN; 23 import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK; 24 import static android.app.usage.UsageEvents.Event.LOCUS_ID_SET; 25 import static android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION; 26 import static android.app.usage.UsageEvents.Event.SHORTCUT_INVOCATION; 27 import static android.app.usage.UsageEvents.Event.USER_INTERACTION; 28 import static android.app.usage.UsageEvents.Event.USER_STOPPED; 29 import static android.app.usage.UsageEvents.Event.USER_UNLOCKED; 30 import static android.app.usage.UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY; 31 import static android.app.usage.UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY; 32 import static android.content.Intent.ACTION_UID_REMOVED; 33 import static android.content.Intent.EXTRA_UID; 34 import static android.text.format.DateUtils.HOUR_IN_MILLIS; 35 36 import android.Manifest; 37 import android.annotation.CurrentTimeMillisLong; 38 import android.annotation.ElapsedRealtimeLong; 39 import android.annotation.IntRange; 40 import android.annotation.NonNull; 41 import android.annotation.Nullable; 42 import android.annotation.SuppressLint; 43 import android.annotation.UserIdInt; 44 import android.app.ActivityManager; 45 import android.app.ActivityManager.ProcessState; 46 import android.app.AppOpsManager; 47 import android.app.IUidObserver; 48 import android.app.PendingIntent; 49 import android.app.UidObserver; 50 import android.app.admin.DevicePolicyManagerInternal; 51 import android.app.usage.AppLaunchEstimateInfo; 52 import android.app.usage.AppStandbyInfo; 53 import android.app.usage.BroadcastResponseStatsList; 54 import android.app.usage.ConfigurationStats; 55 import android.app.usage.EventStats; 56 import android.app.usage.Flags; 57 import android.app.usage.IUsageStatsManager; 58 import android.app.usage.UsageEvents; 59 import android.app.usage.UsageEvents.Event; 60 import android.app.usage.UsageEventsQuery; 61 import android.app.usage.UsageStats; 62 import android.app.usage.UsageStatsManager; 63 import android.app.usage.UsageStatsManager.StandbyBuckets; 64 import android.app.usage.UsageStatsManager.UsageSource; 65 import android.app.usage.UsageStatsManagerInternal; 66 import android.content.BroadcastReceiver; 67 import android.content.ComponentName; 68 import android.content.Context; 69 import android.content.Intent; 70 import android.content.IntentFilter; 71 import android.content.LocusId; 72 import android.content.pm.PackageInfo; 73 import android.content.pm.PackageManager; 74 import android.content.pm.PackageManagerInternal; 75 import android.content.pm.ParceledListSlice; 76 import android.content.pm.ShortcutServiceInternal; 77 import android.content.res.Configuration; 78 import android.os.Binder; 79 import android.os.Environment; 80 import android.os.FileUtils; 81 import android.os.Handler; 82 import android.os.IBinder; 83 import android.os.Looper; 84 import android.os.Message; 85 import android.os.ParcelFileDescriptor; 86 import android.os.PersistableBundle; 87 import android.os.Process; 88 import android.os.RemoteException; 89 import android.os.SystemClock; 90 import android.os.SystemProperties; 91 import android.os.Trace; 92 import android.os.UserHandle; 93 import android.os.UserManager; 94 import android.provider.Settings; 95 import android.text.TextUtils; 96 import android.util.ArrayMap; 97 import android.util.ArraySet; 98 import android.util.AtomicFile; 99 import android.util.Log; 100 import android.util.Slog; 101 import android.util.SparseArray; 102 import android.util.SparseIntArray; 103 import android.util.SparseSetArray; 104 105 import com.android.internal.annotations.GuardedBy; 106 import com.android.internal.annotations.VisibleForTesting; 107 import com.android.internal.content.PackageMonitor; 108 import com.android.internal.os.BackgroundThread; 109 import com.android.internal.util.CollectionUtils; 110 import com.android.internal.util.DumpUtils; 111 import com.android.internal.util.FrameworkStatsLog; 112 import com.android.internal.util.IndentingPrintWriter; 113 import com.android.server.IoThread; 114 import com.android.server.LocalServices; 115 import com.android.server.SystemService; 116 import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener; 117 import com.android.server.utils.AlarmQueue; 118 119 import libcore.util.EmptyArray; 120 121 import java.io.BufferedReader; 122 import java.io.BufferedWriter; 123 import java.io.File; 124 import java.io.FileDescriptor; 125 import java.io.FileInputStream; 126 import java.io.FileOutputStream; 127 import java.io.FileReader; 128 import java.io.FileWriter; 129 import java.io.IOException; 130 import java.io.PrintWriter; 131 import java.nio.file.Files; 132 import java.nio.file.StandardCopyOption; 133 import java.util.ArrayList; 134 import java.util.Arrays; 135 import java.util.HashMap; 136 import java.util.LinkedList; 137 import java.util.List; 138 import java.util.Map; 139 import java.util.Objects; 140 import java.util.Set; 141 import java.util.concurrent.CopyOnWriteArraySet; 142 import java.util.concurrent.TimeUnit; 143 144 /** 145 * A service that collects, aggregates, and persists application usage data. 146 * This data can be queried by apps that have been granted permission by AppOps. 147 */ 148 public class UsageStatsService extends SystemService implements 149 UserUsageStatsService.StatsUpdatedListener { 150 151 static final String TAG = "UsageStatsService"; 152 public static final boolean ENABLE_TIME_CHANGE_CORRECTION 153 = SystemProperties.getBoolean("persist.debug.time_correction", true); 154 155 private static final boolean USE_DEDICATED_HANDLER_THREAD = 156 SystemProperties.getBoolean("persist.debug.use_dedicated_handler_thread", 157 Flags.useDedicatedHandlerThread()); 158 159 static final boolean DEBUG = false; // Never submit with true 160 static final boolean DEBUG_RESPONSE_STATS = DEBUG || Log.isLoggable(TAG, Log.DEBUG); 161 static final boolean COMPRESS_TIME = false; 162 163 private static final long TEN_SECONDS = 10 * 1000; 164 private static final long TWENTY_MINUTES = 20 * 60 * 1000; 165 private static final long ONE_DAY = 24 * HOUR_IN_MILLIS; 166 private static final long ONE_WEEK = 7 * ONE_DAY; 167 private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES; 168 static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. 169 /** 170 * Used when we can't determine the next app launch time. Assume the app will get launched 171 * this amount of time in the future. 172 */ 173 private static final long UNKNOWN_LAUNCH_TIME_DELAY_MS = 365 * ONE_DAY; 174 175 private static final boolean ENABLE_KERNEL_UPDATES = true; 176 private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set"); 177 178 // /data/system/usagestats. Now only used for globalcomponentusage. Previously per-user stats 179 // were stored here too, but they've been moved to /data/system_ce/$userId/usagestats. 180 private static final File COMMON_USAGE_STATS_DIR = 181 new File(Environment.getDataSystemDirectory(), "usagestats"); 182 private static final File LEGACY_USER_USAGE_STATS_DIR = COMMON_USAGE_STATS_DIR; 183 184 // /data/system_de/usagestats. When the globalcomponentusage file was added, it was incorrectly 185 // added here instead of in /data/system/usagestats where it should be. We lazily migrate this 186 // file by reading it from here if needed, and always writing it to the new path. We don't 187 // delete the old directory, as system_server no longer has permission to do so. 188 // 189 // Note, this migration is *not* related to the migration of the per-user stats from 190 // /data/system/usagestats/$userId to /data/system_ce/$userId/usagestats mentioned above. Both 191 // of these just happen to involve /data/system/usagestats. /data/system is the right place for 192 // system data not tied to a user, but the wrong place for per-user data. So due to two 193 // separate mistakes, we've unfortunately ended up with one case where we need to move files out 194 // of /data/system, and one case where we need to move a different file *into* /data/system. 195 private static final File LEGACY_COMMON_USAGE_STATS_DIR = 196 new File(Environment.getDataSystemDeDirectory(), "usagestats"); 197 198 private static final String GLOBAL_COMPONENT_USAGE_FILE_NAME = "globalcomponentusage"; 199 200 private static final char TOKEN_DELIMITER = '/'; 201 202 // The maximum length for extras {@link UsageStatsManager#EXTRA_EVENT_CATEGORY}, 203 // {@link UsageStatsManager#EXTRA_EVENT_ACTION} in a {@link UsageEvents.Event#mExtras}. 204 // The value will be truncated at this limit. 205 private static final int MAX_TEXT_LENGTH = 127; 206 207 // Handler message types. 208 static final int MSG_REPORT_EVENT = 0; 209 static final int MSG_FLUSH_TO_DISK = 1; 210 static final int MSG_REMOVE_USER = 2; 211 static final int MSG_UID_STATE_CHANGED = 3; 212 static final int MSG_REPORT_EVENT_TO_ALL_USERID = 4; 213 static final int MSG_UNLOCKED_USER = 5; 214 static final int MSG_PACKAGE_REMOVED = 6; 215 static final int MSG_ON_START = 7; 216 static final int MSG_HANDLE_LAUNCH_TIME_ON_USER_UNLOCK = 8; 217 static final int MSG_NOTIFY_ESTIMATED_LAUNCH_TIMES_CHANGED = 9; 218 static final int MSG_UID_REMOVED = 10; 219 static final int MSG_USER_STARTED = 11; 220 static final int MSG_NOTIFY_USAGE_EVENT_LISTENER = 12; 221 222 private final Object mLock = new Object(); 223 private Handler mHandler; 224 private Handler mIoHandler; 225 AppOpsManager mAppOps; 226 UserManager mUserManager; 227 PackageManager mPackageManager; 228 PackageManagerInternal mPackageManagerInternal; 229 // Do not use directly. Call getDpmInternal() instead 230 DevicePolicyManagerInternal mDpmInternal; 231 // Do not use directly. Call getShortcutServiceInternal() instead 232 ShortcutServiceInternal mShortcutServiceInternal; 233 234 private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); 235 private final CopyOnWriteArraySet<Integer> mUserUnlockedStates = new CopyOnWriteArraySet<>(); 236 private final SparseIntArray mUidToKernelCounter = new SparseIntArray(); 237 int mUsageSource; 238 239 private long mRealTimeSnapshot; 240 private long mSystemTimeSnapshot; 241 // A map storing last time global usage of packages, measured in milliseconds since the epoch. 242 private final Map<String, Long> mLastTimeComponentUsedGlobal = new ArrayMap<>(); 243 244 /** Manages the standby state of apps. */ 245 AppStandbyInternal mAppStandby; 246 247 /** Manages app time limit observers */ 248 AppTimeLimitController mAppTimeLimit; 249 250 private final PackageMonitor mPackageMonitor = new MyPackageMonitor(); 251 252 // A map maintaining a queue of events to be reported per user. 253 private final SparseArray<LinkedList<Event>> mReportedEvents = new SparseArray<>(); 254 final SparseArray<ArraySet<String>> mUsageReporters = new SparseArray(); 255 final SparseArray<ActivityData> mVisibleActivities = new SparseArray(); 256 @GuardedBy("mLaunchTimeAlarmQueues") // Don't hold the main lock 257 private final SparseArray<LaunchTimeAlarmQueue> mLaunchTimeAlarmQueues = new SparseArray<>(); 258 @GuardedBy("mUsageEventListeners") // Don't hold the main lock when calling out 259 private final ArraySet<UsageStatsManagerInternal.UsageEventListener> mUsageEventListeners = 260 new ArraySet<>(); 261 private final CopyOnWriteArraySet<UsageStatsManagerInternal.EstimatedLaunchTimeChangedListener> 262 mEstimatedLaunchTimeChangedListeners = new CopyOnWriteArraySet<>(); 263 @GuardedBy("mPendingLaunchTimeChangePackages") 264 private final SparseSetArray<String> mPendingLaunchTimeChangePackages = new SparseSetArray<>(); 265 266 private BroadcastResponseStatsTracker mResponseStatsTracker; 267 268 private static class ActivityData { 269 private final String mTaskRootPackage; 270 private final String mTaskRootClass; 271 private final String mUsageSourcePackage; 272 public int lastEvent = Event.NONE; 273 ActivityData(String taskRootPackage, String taskRootClass, String sourcePackage)274 private ActivityData(String taskRootPackage, String taskRootClass, String sourcePackage) { 275 mTaskRootPackage = taskRootPackage; 276 mTaskRootClass = taskRootClass; 277 mUsageSourcePackage = sourcePackage; 278 } 279 } 280 281 private AppIdleStateChangeListener mStandbyChangeListener = 282 new AppIdleStateChangeListener() { 283 @Override 284 public void onAppIdleStateChanged(String packageName, int userId, boolean idle, 285 int bucket, int reason) { 286 Event event = new Event(Event.STANDBY_BUCKET_CHANGED, 287 SystemClock.elapsedRealtime()); 288 event.mBucketAndReason = (bucket << 16) | (reason & 0xFFFF); 289 event.mPackage = packageName; 290 reportEventOrAddToQueue(userId, event); 291 } 292 }; 293 294 @VisibleForTesting 295 static class Injector { getAppStandbyController(Context context)296 AppStandbyInternal getAppStandbyController(Context context) { 297 return AppStandbyInternal.newAppStandbyController( 298 UsageStatsService.class.getClassLoader(), context); 299 } 300 } 301 302 private final Handler.Callback mIoHandlerCallback = (msg) -> { 303 switch (msg.what) { 304 case MSG_UID_STATE_CHANGED: { 305 final int uid = msg.arg1; 306 final int procState = msg.arg2; 307 308 final int newCounter = (procState <= ActivityManager.PROCESS_STATE_TOP) ? 0 : 1; 309 synchronized (mUidToKernelCounter) { 310 final int oldCounter = mUidToKernelCounter.get(uid, 0); 311 if (newCounter != oldCounter) { 312 mUidToKernelCounter.put(uid, newCounter); 313 try { 314 FileUtils.stringToFile(KERNEL_COUNTER_FILE, uid + " " + newCounter); 315 } catch (IOException e) { 316 Slog.w(TAG, "Failed to update counter set: " + e); 317 } 318 } 319 } 320 return true; 321 } 322 case MSG_HANDLE_LAUNCH_TIME_ON_USER_UNLOCK: { 323 final int userId = msg.arg1; 324 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, 325 "usageStatsHandleEstimatedLaunchTimesOnUser(" + userId + ")"); 326 handleEstimatedLaunchTimesOnUserUnlock(userId); 327 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); 328 return true; 329 } 330 case MSG_NOTIFY_USAGE_EVENT_LISTENER: { 331 final int userId = msg.arg1; 332 final Event event = (Event) msg.obj; 333 synchronized (mUsageEventListeners) { 334 final int size = mUsageEventListeners.size(); 335 for (int i = 0; i < size; ++i) { 336 mUsageEventListeners.valueAt(i).onUsageEvent(userId, event); 337 } 338 } 339 return true; 340 } 341 } 342 return false; 343 }; 344 345 private final Injector mInjector; 346 UsageStatsService(Context context)347 public UsageStatsService(Context context) { 348 this(context, new Injector()); 349 } 350 351 @VisibleForTesting UsageStatsService(Context context, Injector injector)352 UsageStatsService(Context context, Injector injector) { 353 super(context); 354 mInjector = injector; 355 } 356 357 @Override 358 @SuppressLint("AndroidFrameworkRequiresPermission") onStart()359 public void onStart() { 360 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); 361 mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); 362 mPackageManager = getContext().getPackageManager(); 363 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); 364 mHandler = getUsageEventProcessingHandler(); 365 mIoHandler = new Handler(IoThread.get().getLooper(), mIoHandlerCallback); 366 367 mAppStandby = mInjector.getAppStandbyController(getContext()); 368 mResponseStatsTracker = new BroadcastResponseStatsTracker(mAppStandby, getContext()); 369 370 mAppTimeLimit = new AppTimeLimitController(getContext(), 371 new AppTimeLimitController.TimeLimitCallbackListener() { 372 @Override 373 public void onLimitReached(int observerId, int userId, long timeLimit, 374 long timeElapsed, PendingIntent callbackIntent) { 375 if (callbackIntent == null) return; 376 Intent intent = new Intent(); 377 intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId); 378 intent.putExtra(UsageStatsManager.EXTRA_TIME_LIMIT, timeLimit); 379 intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed); 380 try { 381 callbackIntent.send(getContext(), 0, intent); 382 } catch (PendingIntent.CanceledException e) { 383 Slog.w(TAG, "Couldn't deliver callback: " 384 + callbackIntent); 385 } 386 } 387 388 @Override 389 public void onSessionEnd(int observerId, int userId, long timeElapsed, 390 PendingIntent callbackIntent) { 391 if (callbackIntent == null) return; 392 Intent intent = new Intent(); 393 intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId); 394 intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed); 395 try { 396 callbackIntent.send(getContext(), 0, intent); 397 } catch (PendingIntent.CanceledException e) { 398 Slog.w(TAG, "Couldn't deliver callback: " 399 + callbackIntent); 400 } 401 } 402 }, mHandler.getLooper()); 403 404 mAppStandby.addListener(mStandbyChangeListener); 405 406 mPackageMonitor.register(getContext(), 407 /* thread= */ USE_DEDICATED_HANDLER_THREAD ? mHandler.getLooper() : null, 408 UserHandle.ALL, true); 409 410 IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED); 411 filter.addAction(Intent.ACTION_USER_STARTED); 412 getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter, 413 null, /* scheduler= */ USE_DEDICATED_HANDLER_THREAD ? mHandler : null); 414 415 getContext().registerReceiverAsUser(new UidRemovedReceiver(), UserHandle.ALL, 416 new IntentFilter(ACTION_UID_REMOVED), null, 417 /* scheduler= */ USE_DEDICATED_HANDLER_THREAD ? mHandler : null); 418 419 mRealTimeSnapshot = SystemClock.elapsedRealtime(); 420 mSystemTimeSnapshot = System.currentTimeMillis(); 421 422 publishLocalService(UsageStatsManagerInternal.class, new LocalService()); 423 publishLocalService(AppStandbyInternal.class, mAppStandby); 424 publishBinderServices(); 425 426 mHandler.obtainMessage(MSG_ON_START).sendToTarget(); 427 } 428 429 @VisibleForTesting publishBinderServices()430 void publishBinderServices() { 431 publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService()); 432 } 433 434 @Override onBootPhase(int phase)435 public void onBootPhase(int phase) { 436 mAppStandby.onBootPhase(phase); 437 if (phase == PHASE_SYSTEM_SERVICES_READY) { 438 // initialize mDpmInternal 439 getDpmInternal(); 440 // initialize mShortcutServiceInternal 441 getShortcutServiceInternal(); 442 mResponseStatsTracker.onSystemServicesReady(getContext()); 443 444 if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) { 445 try { 446 ActivityManager.getService().registerUidObserver(mUidObserver, 447 ActivityManager.UID_OBSERVER_PROCSTATE 448 | ActivityManager.UID_OBSERVER_GONE, 449 ActivityManager.PROCESS_STATE_UNKNOWN, null); 450 } catch (RemoteException e) { 451 throw new RuntimeException(e); 452 } 453 } else { 454 Slog.w(TAG, "Missing procfs interface: " + KERNEL_COUNTER_FILE); 455 } 456 readUsageSourceSetting(); 457 } 458 } 459 460 @Override onUserStarting(@onNull TargetUser user)461 public void onUserStarting(@NonNull TargetUser user) { 462 // Create an entry in the user state map to indicate that the user has been started but 463 // not necessarily unlocked. This will ensure that reported events are flushed to disk 464 // event if the user is never unlocked (following the logic in #flushToDiskLocked) 465 mUserState.put(user.getUserIdentifier(), null); 466 } 467 468 @Override onUserUnlocking(@onNull TargetUser user)469 public void onUserUnlocking(@NonNull TargetUser user) { 470 mHandler.obtainMessage(MSG_UNLOCKED_USER, user.getUserIdentifier(), 0).sendToTarget(); 471 } 472 473 @Override onUserStopping(@onNull TargetUser user)474 public void onUserStopping(@NonNull TargetUser user) { 475 final int userId = user.getUserIdentifier(); 476 477 synchronized (mLock) { 478 // User was started but never unlocked so no need to report a user stopped event 479 if (!mUserUnlockedStates.contains(userId)) { 480 persistPendingEventsLocked(userId); 481 return; 482 } 483 484 // Report a user stopped event before persisting all stats to disk via the user service 485 final Event event = new Event(USER_STOPPED, SystemClock.elapsedRealtime()); 486 event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; 487 reportEvent(event, userId); 488 final UserUsageStatsService userService = mUserState.get(userId); 489 if (userService != null) { 490 userService.userStopped(); 491 } 492 mUserUnlockedStates.remove(userId); 493 mUserState.put(userId, null); // release the service (mainly for GC) 494 } 495 496 synchronized (mLaunchTimeAlarmQueues) { 497 LaunchTimeAlarmQueue alarmQueue = mLaunchTimeAlarmQueues.get(userId); 498 if (alarmQueue != null) { 499 alarmQueue.removeAllAlarms(); 500 mLaunchTimeAlarmQueues.remove(userId); 501 } 502 } 503 } 504 getUsageEventProcessingHandler()505 private Handler getUsageEventProcessingHandler() { 506 if (USE_DEDICATED_HANDLER_THREAD) { 507 return new H(UsageStatsHandlerThread.get().getLooper()); 508 } else { 509 return new H(BackgroundThread.get().getLooper()); 510 } 511 } 512 onUserUnlocked(int userId)513 private void onUserUnlocked(int userId) { 514 // fetch the installed packages outside the lock so it doesn't block package manager. 515 final HashMap<String, Long> installedPackages = getInstalledPackages(userId); 516 517 UsageStatsIdleService.scheduleUpdateMappingsJob(getContext(), userId); 518 519 final boolean deleteObsoleteData = shouldDeleteObsoleteData(UserHandle.of(userId)); 520 synchronized (mLock) { 521 // This should be safe to add this early. Other than reportEventOrAddToQueue and 522 // getBackupPayload, every other user grabs the lock before accessing 523 // mUserUnlockedStates. reportEventOrAddToQueue does not depend on anything other than 524 // mUserUnlockedStates, and the lock will protect the handler. 525 mUserUnlockedStates.add(userId); 526 // Create a user unlocked event to report 527 final Event unlockEvent = new Event(USER_UNLOCKED, SystemClock.elapsedRealtime()); 528 unlockEvent.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; 529 530 migrateStatsToSystemCeIfNeededLocked(userId); 531 532 // Read pending reported events from disk and merge them with those stored in memory 533 final LinkedList<Event> pendingEvents = new LinkedList<>(); 534 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "loadPendingEvents"); 535 loadPendingEventsLocked(userId, pendingEvents); 536 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); 537 synchronized (mReportedEvents) { 538 final LinkedList<Event> eventsInMem = mReportedEvents.get(userId); 539 if (eventsInMem != null) { 540 pendingEvents.addAll(eventsInMem); 541 mReportedEvents.remove(userId); 542 } 543 } 544 boolean needToFlush = !pendingEvents.isEmpty(); 545 546 initializeUserUsageStatsServiceLocked(userId, System.currentTimeMillis(), 547 installedPackages, deleteObsoleteData); 548 final UserUsageStatsService userService = getUserUsageStatsServiceLocked(userId); 549 if (userService == null) { 550 Slog.i(TAG, "Attempted to unlock stopped or removed user " + userId); 551 return; 552 } 553 554 // Process all the pending reported events 555 while (pendingEvents.peek() != null) { 556 reportEvent(pendingEvents.poll(), userId); 557 } 558 reportEvent(unlockEvent, userId); 559 560 // Remove all the stats stored in system DE. 561 deleteRecursively(new File(Environment.getDataSystemDeDirectory(userId), "usagestats")); 562 563 // Force a flush to disk for the current user to ensure important events are persisted. 564 // Note: there is a very very small chance that the system crashes between deleting 565 // the stats above from DE and persisting them to CE here in which case we will lose 566 // those events that were in memory and deleted from DE. (b/139836090) 567 if (needToFlush) { 568 userService.persistActiveStats(); 569 } 570 } 571 572 mIoHandler.obtainMessage(MSG_HANDLE_LAUNCH_TIME_ON_USER_UNLOCK, userId, 0).sendToTarget(); 573 } 574 575 /** 576 * Fetches a map (package_name:install_time) of installed packages for the given user. This 577 * map contains all installed packages, including those packages which have been uninstalled 578 * with the DELETE_KEEP_DATA flag. 579 * This is a helper method which should only be called when the given user's usage stats service 580 * is initialized; it performs a heavy query to package manager so do not call it otherwise. 581 * <br/> 582 * Note: DO NOT call this while holding the usage stats lock ({@code mLock}). 583 */ 584 @Nullable getInstalledPackages(int userId)585 private HashMap<String, Long> getInstalledPackages(int userId) { 586 if (mPackageManager == null) { 587 return null; 588 } 589 final List<PackageInfo> installedPackages = mPackageManager.getInstalledPackagesAsUser( 590 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); 591 final HashMap<String, Long> packagesMap = new HashMap<>(); 592 for (int i = installedPackages.size() - 1; i >= 0; i--) { 593 final PackageInfo packageInfo = installedPackages.get(i); 594 packagesMap.put(packageInfo.packageName, packageInfo.firstInstallTime); 595 } 596 return packagesMap; 597 } 598 getDpmInternal()599 private DevicePolicyManagerInternal getDpmInternal() { 600 if (mDpmInternal == null) { 601 mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class); 602 } 603 return mDpmInternal; 604 } 605 getShortcutServiceInternal()606 private ShortcutServiceInternal getShortcutServiceInternal() { 607 if (mShortcutServiceInternal == null) { 608 mShortcutServiceInternal = LocalServices.getService(ShortcutServiceInternal.class); 609 } 610 return mShortcutServiceInternal; 611 } 612 readUsageSourceSetting()613 private void readUsageSourceSetting() { 614 synchronized (mLock) { 615 mUsageSource = Settings.Global.getInt(getContext().getContentResolver(), 616 Settings.Global.APP_TIME_LIMIT_USAGE_SOURCE, USAGE_SOURCE_TASK_ROOT_ACTIVITY); 617 } 618 } 619 620 private class LaunchTimeAlarmQueue extends AlarmQueue<String> { 621 private final int mUserId; 622 LaunchTimeAlarmQueue(int userId, @NonNull Context context, @NonNull Looper looper)623 LaunchTimeAlarmQueue(int userId, @NonNull Context context, @NonNull Looper looper) { 624 super(context, looper, "*usage.launchTime*", "Estimated launch times", true, 30_000L); 625 mUserId = userId; 626 } 627 628 @Override isForUser(@onNull String key, int userId)629 protected boolean isForUser(@NonNull String key, int userId) { 630 return mUserId == userId; 631 } 632 633 @Override processExpiredAlarms(@onNull ArraySet<String> expired)634 protected void processExpiredAlarms(@NonNull ArraySet<String> expired) { 635 if (DEBUG) { 636 Slog.d(TAG, "Processing " + expired.size() + " expired alarms: " 637 + expired.toString()); 638 } 639 if (expired.size() > 0) { 640 synchronized (mPendingLaunchTimeChangePackages) { 641 mPendingLaunchTimeChangePackages.addAll(mUserId, expired); 642 } 643 mHandler.sendEmptyMessage(MSG_NOTIFY_ESTIMATED_LAUNCH_TIMES_CHANGED); 644 } 645 } 646 } 647 648 private class UserActionsReceiver extends BroadcastReceiver { 649 @Override onReceive(Context context, Intent intent)650 public void onReceive(Context context, Intent intent) { 651 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 652 final String action = intent.getAction(); 653 if (Intent.ACTION_USER_REMOVED.equals(action)) { 654 if (userId >= 0) { 655 mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget(); 656 } 657 } else if (Intent.ACTION_USER_STARTED.equals(action)) { 658 if (userId >= 0) { 659 if (!Flags.disableIdleCheck() || userId > 0) { 660 // Don't check idle state for USER_SYSTEM during the boot up. 661 mHandler.obtainMessage(MSG_USER_STARTED, userId, 0).sendToTarget(); 662 } 663 } 664 } 665 } 666 } 667 668 private class UidRemovedReceiver extends BroadcastReceiver { 669 @Override onReceive(Context context, Intent intent)670 public void onReceive(Context context, Intent intent) { 671 final int uid = intent.getIntExtra(EXTRA_UID, -1); 672 if (uid == -1) { 673 return; 674 } 675 676 mHandler.obtainMessage(MSG_UID_REMOVED, uid, 0).sendToTarget(); 677 } 678 } 679 680 private final IUidObserver mUidObserver = new UidObserver() { 681 @Override 682 public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { 683 mIoHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget(); 684 } 685 686 @Override 687 public void onUidGone(int uid, boolean disabled) { 688 onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0, 689 ActivityManager.PROCESS_CAPABILITY_NONE); 690 } 691 }; 692 693 @Override onStatsUpdated()694 public void onStatsUpdated() { 695 mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL); 696 } 697 698 @Override onStatsReloaded()699 public void onStatsReloaded() { 700 // This method ends up being called with the lock held, so we need to be careful how we 701 // call into other things. 702 mAppStandby.postOneTimeCheckIdleStates(); 703 } 704 705 @Override onNewUpdate(int userId)706 public void onNewUpdate(int userId) { 707 mAppStandby.initializeDefaultsForSystemApps(userId); 708 } 709 sameApp(int callingUid, @UserIdInt int userId, String packageName)710 private boolean sameApp(int callingUid, @UserIdInt int userId, String packageName) { 711 return mPackageManagerInternal.getPackageUid(packageName, 0 /* flags */, userId) 712 == callingUid; 713 } 714 isInstantApp(String packageName, int userId)715 private boolean isInstantApp(String packageName, int userId) { 716 return mPackageManagerInternal.isPackageEphemeral(userId, packageName); 717 } 718 shouldObfuscateInstantAppsForCaller(int callingUid, int userId)719 private boolean shouldObfuscateInstantAppsForCaller(int callingUid, int userId) { 720 return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId); 721 } 722 shouldHideShortcutInvocationEvents(int userId, String callingPackage, int callingPid, int callingUid)723 private boolean shouldHideShortcutInvocationEvents(int userId, String callingPackage, 724 int callingPid, int callingUid) { 725 final ShortcutServiceInternal shortcutServiceInternal = getShortcutServiceInternal(); 726 if (shortcutServiceInternal != null) { 727 return !shortcutServiceInternal.hasShortcutHostPermission(userId, callingPackage, 728 callingPid, callingUid); 729 } 730 return true; // hide by default if we can't verify visibility 731 } 732 shouldHideLocusIdEvents(int callingPid, int callingUid)733 private boolean shouldHideLocusIdEvents(int callingPid, int callingUid) { 734 if (callingUid == Process.SYSTEM_UID) { 735 return false; 736 } 737 return !(getContext().checkPermission( 738 android.Manifest.permission.ACCESS_LOCUS_ID_USAGE_STATS, callingPid, callingUid) 739 == PackageManager.PERMISSION_GRANTED); 740 } 741 742 /** 743 * Obfuscate both {@link UsageEvents.Event#NOTIFICATION_SEEN} and 744 * {@link UsageEvents.Event#NOTIFICATION_INTERRUPTION} events if the provided calling uid does 745 * not hold the {@link android.Manifest.permission#MANAGE_NOTIFICATIONS} permission. 746 */ shouldObfuscateNotificationEvents(int callingPid, int callingUid)747 private boolean shouldObfuscateNotificationEvents(int callingPid, int callingUid) { 748 if (callingUid == Process.SYSTEM_UID) { 749 return false; 750 } 751 return !(getContext().checkPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS, 752 callingPid, callingUid) == PackageManager.PERMISSION_GRANTED); 753 } 754 deleteRecursively(final File path)755 private static void deleteRecursively(final File path) { 756 if (path.isDirectory()) { 757 final File[] files = path.listFiles(); 758 if (files != null) { 759 for (File subFile : files) { 760 deleteRecursively(subFile); 761 } 762 } 763 } 764 765 if (path.exists() && !path.delete()) { 766 Slog.e(TAG, "Failed to delete " + path); 767 } 768 } 769 770 /** 771 * This should the be only way to fetch the usage stats service for a specific user. 772 */ getUserUsageStatsServiceLocked(int userId)773 private UserUsageStatsService getUserUsageStatsServiceLocked(int userId) { 774 final UserUsageStatsService service = mUserState.get(userId); 775 if (service == null) { 776 Slog.wtf(TAG, "Failed to fetch usage stats service for user " + userId + ". " 777 + "The user might not have been initialized yet."); 778 } 779 return service; 780 } 781 782 /** 783 * Initializes the given user's usage stats service - this should ideally only be called once, 784 * when the user is initially unlocked. 785 */ initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis, HashMap<String, Long> installedPackages, boolean deleteObsoleteData)786 private void initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis, 787 HashMap<String, Long> installedPackages, boolean deleteObsoleteData) { 788 final File usageStatsDir = new File(Environment.getDataSystemCeDirectory(userId), 789 "usagestats"); 790 final UserUsageStatsService service = new UserUsageStatsService(getContext(), userId, 791 usageStatsDir, this); 792 try { 793 service.init(currentTimeMillis, installedPackages, deleteObsoleteData); 794 mUserState.put(userId, service); 795 } catch (Exception e) { 796 if (mUserManager.isUserUnlocked(userId)) { 797 Slog.w(TAG, "Failed to initialized unlocked user " + userId); 798 throw e; // rethrow the exception - user is unlocked 799 } else { 800 Slog.w(TAG, "Attempted to initialize service for stopped or removed user " 801 + userId); 802 } 803 } 804 } 805 migrateStatsToSystemCeIfNeededLocked(int userId)806 private void migrateStatsToSystemCeIfNeededLocked(int userId) { 807 final File usageStatsDir = new File(Environment.getDataSystemCeDirectory(userId), 808 "usagestats"); 809 if (!usageStatsDir.mkdirs() && !usageStatsDir.exists()) { 810 throw new IllegalStateException("Usage stats directory does not exist: " 811 + usageStatsDir.getAbsolutePath()); 812 } 813 // Check if the migrated status file exists - if not, migrate usage stats. 814 final File migrated = new File(usageStatsDir, "migrated"); 815 if (migrated.exists()) { 816 try (BufferedReader reader = new BufferedReader(new FileReader(migrated))) { 817 final int previousVersion = Integer.parseInt(reader.readLine()); 818 // UsageStatsDatabase.BACKUP_VERSION was 4 when usage stats were migrated to CE. 819 if (previousVersion >= 4) { 820 deleteLegacyUserDir(userId); 821 return; 822 } 823 // If migration logic needs to be changed in a future version, do it here. 824 } catch (NumberFormatException | IOException e) { 825 Slog.e(TAG, "Failed to read migration status file, possibly corrupted."); 826 deleteRecursively(usageStatsDir); 827 if (usageStatsDir.exists()) { 828 Slog.e(TAG, "Unable to delete usage stats CE directory."); 829 throw new RuntimeException(e); 830 } else { 831 // Make the directory again since previous migration was not complete 832 if (!usageStatsDir.mkdirs() && !usageStatsDir.exists()) { 833 throw new IllegalStateException("Usage stats directory does not exist: " 834 + usageStatsDir.getAbsolutePath()); 835 } 836 } 837 } 838 } 839 840 Slog.i(TAG, "Starting migration to system CE for user " + userId); 841 final File legacyUserDir = new File(LEGACY_USER_USAGE_STATS_DIR, Integer.toString(userId)); 842 if (legacyUserDir.exists()) { 843 copyRecursively(usageStatsDir, legacyUserDir); 844 } 845 // Create a status file to indicate that the migration to CE has been completed. 846 try (BufferedWriter writer = new BufferedWriter(new FileWriter(migrated))) { 847 writer.write(Integer.toString(UsageStatsDatabase.BACKUP_VERSION)); 848 writer.write("\n"); 849 writer.flush(); 850 } catch (IOException e) { 851 Slog.e(TAG, "Failed to write migrated status file"); 852 throw new RuntimeException(e); 853 } 854 Slog.i(TAG, "Finished migration to system CE for user " + userId); 855 856 // Migration was successful - delete the legacy user directory 857 deleteLegacyUserDir(userId); 858 } 859 copyRecursively(final File parent, File f)860 private static void copyRecursively(final File parent, File f) { 861 final File[] files = f.listFiles(); 862 if (files == null) { 863 try { 864 Files.copy(f.toPath(), new File(parent, f.getName()).toPath(), 865 StandardCopyOption.REPLACE_EXISTING); 866 } catch (IOException e) { 867 Slog.e(TAG, "Failed to move usage stats file : " + f.toString()); 868 throw new RuntimeException(e); 869 } 870 return; 871 } 872 873 for (int i = files.length - 1; i >= 0; i--) { 874 File newParent = parent; 875 if (files[i].isDirectory()) { 876 newParent = new File(parent, files[i].getName()); 877 final boolean mkdirSuccess = newParent.mkdirs(); 878 if (!mkdirSuccess && !newParent.exists()) { 879 throw new IllegalStateException( 880 "Failed to create usage stats directory during migration: " 881 + newParent.getAbsolutePath()); 882 } 883 } 884 copyRecursively(newParent, files[i]); 885 } 886 } 887 deleteLegacyUserDir(int userId)888 private void deleteLegacyUserDir(int userId) { 889 final File legacyUserDir = new File(LEGACY_USER_USAGE_STATS_DIR, Integer.toString(userId)); 890 if (legacyUserDir.exists()) { 891 deleteRecursively(legacyUserDir); 892 if (legacyUserDir.exists()) { 893 Slog.w(TAG, "Error occurred while attempting to delete legacy usage stats " 894 + "dir for user " + userId); 895 } 896 } 897 } 898 899 /** 900 * Called by the Binder stub 901 */ shutdown()902 void shutdown() { 903 synchronized (mLock) { 904 mHandler.removeMessages(MSG_REPORT_EVENT); 905 Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime()); 906 event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; 907 // orderly shutdown, the last event is DEVICE_SHUTDOWN. 908 reportEventToAllUserId(event); 909 flushToDiskLocked(); 910 persistGlobalComponentUsageLocked(); 911 } 912 913 mAppStandby.flushToDisk(); 914 } 915 916 /** 917 * After power button is pressed for 3.5 seconds 918 * (as defined in {@link com.android.internal.R.integer#config_veryLongPressTimeout}), 919 * report DEVICE_SHUTDOWN event and persist the database. If the power button is pressed for 10 920 * seconds and the device is shutdown, the database is already persisted and we are not losing 921 * data. 922 * This method is called from PhoneWindowManager, do not synchronize on mLock otherwise 923 * PhoneWindowManager may be blocked. 924 */ prepareForPossibleShutdown()925 void prepareForPossibleShutdown() { 926 Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime()); 927 event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; 928 mHandler.obtainMessage(MSG_REPORT_EVENT_TO_ALL_USERID, event).sendToTarget(); 929 mHandler.sendEmptyMessage(MSG_FLUSH_TO_DISK); 930 } 931 loadPendingEventsLocked(int userId, LinkedList<Event> pendingEvents)932 private void loadPendingEventsLocked(int userId, LinkedList<Event> pendingEvents) { 933 final File usageStatsDeDir = new File(Environment.getDataSystemDeDirectory(userId), 934 "usagestats"); 935 final File[] pendingEventsFiles = usageStatsDeDir.listFiles(); 936 if (pendingEventsFiles == null || pendingEventsFiles.length == 0) { 937 return; 938 } 939 Arrays.sort(pendingEventsFiles); 940 941 final int numFiles = pendingEventsFiles.length; 942 for (int i = 0; i < numFiles; i++) { 943 final AtomicFile af = new AtomicFile(pendingEventsFiles[i]); 944 final LinkedList<Event> tmpEvents = new LinkedList<>(); 945 try { 946 try (FileInputStream in = af.openRead()) { 947 UsageStatsProtoV2.readPendingEvents(in, tmpEvents); 948 } 949 // only add to the pending events if the read was successful 950 pendingEvents.addAll(tmpEvents); 951 } catch (Exception e) { 952 // Most likely trying to read a corrupted file - log the failure and continue 953 // reading the other pending event files. 954 Slog.e(TAG, "Could not read " + pendingEventsFiles[i] + " for user " + userId); 955 } 956 } 957 } 958 959 @GuardedBy({"mLock", "mReportedEvents"}) persistPendingEventsLocked(int userId)960 private void persistPendingEventsLocked(int userId) { 961 final LinkedList<Event> pendingEvents = mReportedEvents.get(userId); 962 if (pendingEvents == null || pendingEvents.isEmpty()) { 963 return; 964 } 965 966 final File deDir = Environment.getDataSystemDeDirectory(userId); 967 final File usageStatsDeDir = new File(deDir, "usagestats"); 968 if (!usageStatsDeDir.mkdir() && !usageStatsDeDir.exists()) { 969 if (deDir.exists()) { 970 Slog.e(TAG, "Failed to create " + usageStatsDeDir); 971 } else { 972 Slog.w(TAG, "User " + userId + " was already removed! Discarding pending events"); 973 pendingEvents.clear(); 974 } 975 return; 976 } 977 final File pendingEventsFile = new File(usageStatsDeDir, 978 "pendingevents_" + System.currentTimeMillis()); 979 final AtomicFile af = new AtomicFile(pendingEventsFile); 980 FileOutputStream fos = null; 981 try { 982 fos = af.startWrite(); 983 UsageStatsProtoV2.writePendingEvents(fos, pendingEvents); 984 af.finishWrite(fos); 985 fos = null; 986 pendingEvents.clear(); 987 } catch (Exception e) { 988 Slog.e(TAG, "Failed to write " + pendingEventsFile.getAbsolutePath() 989 + " for user " + userId); 990 } finally { 991 af.failWrite(fos); // when fos is null (successful write), this will no-op 992 } 993 } 994 loadGlobalComponentUsageLocked()995 private void loadGlobalComponentUsageLocked() { 996 AtomicFile af = new AtomicFile(new File(COMMON_USAGE_STATS_DIR, 997 GLOBAL_COMPONENT_USAGE_FILE_NAME)); 998 if (!af.exists()) { 999 af = new AtomicFile(new File(LEGACY_COMMON_USAGE_STATS_DIR, 1000 GLOBAL_COMPONENT_USAGE_FILE_NAME)); 1001 if (!af.exists()) { 1002 return; 1003 } 1004 Slog.i(TAG, "Reading " + GLOBAL_COMPONENT_USAGE_FILE_NAME + " file from old location"); 1005 } 1006 final Map<String, Long> tmpUsage = new ArrayMap<>(); 1007 try { 1008 try (FileInputStream in = af.openRead()) { 1009 UsageStatsProtoV2.readGlobalComponentUsage(in, tmpUsage); 1010 } 1011 // only add to in memory map if the read was successful 1012 final Map.Entry<String, Long>[] entries = 1013 (Map.Entry<String, Long>[]) tmpUsage.entrySet().toArray(); 1014 final int size = entries.length; 1015 for (int i = 0; i < size; ++i) { 1016 // In memory data is usually the most up-to-date, so skip the packages which already 1017 // have usage data. 1018 mLastTimeComponentUsedGlobal.putIfAbsent( 1019 entries[i].getKey(), entries[i].getValue()); 1020 } 1021 } catch (Exception e) { 1022 // Most likely trying to read a corrupted file - log the failure 1023 Slog.e(TAG, "Could not read " + af.getBaseFile()); 1024 } 1025 } 1026 persistGlobalComponentUsageLocked()1027 private void persistGlobalComponentUsageLocked() { 1028 if (mLastTimeComponentUsedGlobal.isEmpty()) { 1029 return; 1030 } 1031 1032 if (!COMMON_USAGE_STATS_DIR.mkdirs() && !COMMON_USAGE_STATS_DIR.exists()) { 1033 throw new IllegalStateException("Common usage stats directory does not exist: " 1034 + COMMON_USAGE_STATS_DIR.getAbsolutePath()); 1035 } 1036 final File lastTimePackageFile = new File(COMMON_USAGE_STATS_DIR, 1037 GLOBAL_COMPONENT_USAGE_FILE_NAME); 1038 final AtomicFile af = new AtomicFile(lastTimePackageFile); 1039 FileOutputStream fos = null; 1040 try { 1041 fos = af.startWrite(); 1042 UsageStatsProtoV2.writeGlobalComponentUsage(fos, mLastTimeComponentUsedGlobal); 1043 af.finishWrite(fos); 1044 fos = null; 1045 } catch (Exception e) { 1046 Slog.e(TAG, "Failed to write " + lastTimePackageFile.getAbsolutePath()); 1047 } finally { 1048 af.failWrite(fos); // when fos is null (successful write), this will no-op 1049 } 1050 } 1051 reportEventOrAddToQueue(int userId, Event event)1052 private void reportEventOrAddToQueue(int userId, Event event) { 1053 if (mUserUnlockedStates.contains(userId)) { 1054 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1055 return; 1056 } 1057 1058 if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) { 1059 final String traceTag = "usageStatsQueueEvent(" + userId + ") #" 1060 + UserUsageStatsService.eventToString(event.mEventType); 1061 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, traceTag); 1062 } 1063 synchronized (mReportedEvents) { 1064 LinkedList<Event> events = mReportedEvents.get(userId); 1065 if (events == null) { 1066 events = new LinkedList<>(); 1067 mReportedEvents.put(userId, events); 1068 } 1069 events.add(event); 1070 if (events.size() == 1) { 1071 // Every time a file is persisted to disk, mReportedEvents is cleared for this user 1072 // so trigger a flush to disk every time the first event has been added. 1073 mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL); 1074 } 1075 } 1076 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); 1077 } 1078 1079 /** 1080 * Assuming the event's timestamp is measured in milliseconds since boot, 1081 * convert it to a system wall time. System and real time snapshots are updated before 1082 * conversion. 1083 */ convertToSystemTimeLocked(Event event)1084 private void convertToSystemTimeLocked(Event event) { 1085 final long actualSystemTime = System.currentTimeMillis(); 1086 if (ENABLE_TIME_CHANGE_CORRECTION) { 1087 final long actualRealtime = SystemClock.elapsedRealtime(); 1088 final long expectedSystemTime = 1089 (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; 1090 final long diffSystemTime = actualSystemTime - expectedSystemTime; 1091 if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) { 1092 // The time has changed. 1093 Slog.i(TAG, "Time changed in by " + (diffSystemTime / 1000) + " seconds"); 1094 mRealTimeSnapshot = actualRealtime; 1095 mSystemTimeSnapshot = actualSystemTime; 1096 } 1097 } 1098 event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot; 1099 } 1100 1101 /** 1102 * Called by the Binder stub. 1103 */ reportEvent(Event event, int userId)1104 void reportEvent(Event event, int userId) { 1105 final int uid; 1106 // Acquire uid outside of mLock for events that need it 1107 switch (event.mEventType) { 1108 case Event.ACTIVITY_RESUMED: 1109 case Event.ACTIVITY_PAUSED: 1110 case Event.ACTIVITY_STOPPED: 1111 uid = mPackageManagerInternal.getPackageUid(event.mPackage, 0, userId); 1112 break; 1113 default: 1114 uid = 0; 1115 } 1116 1117 if (event.mPackage != null && isInstantApp(event.mPackage, userId)) { 1118 event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP; 1119 } 1120 1121 synchronized (mLock) { 1122 // This should never be called directly when the user is locked 1123 if (!mUserUnlockedStates.contains(userId)) { 1124 Slog.wtf(TAG, "Failed to report event for locked user " + userId 1125 + " (" + event.mPackage + "/" + event.mClass 1126 + " eventType:" + event.mEventType 1127 + " instanceId:" + event.mInstanceId + ")"); 1128 return; 1129 } 1130 1131 switch (event.mEventType) { 1132 case Event.ACTIVITY_RESUMED: 1133 logAppUsageEventReportedAtomLocked(Event.ACTIVITY_RESUMED, uid, event.mPackage); 1134 1135 // check if this activity has already been resumed 1136 if (mVisibleActivities.get(event.mInstanceId) != null) break; 1137 final String usageSourcePackage = getUsageSourcePackage(event); 1138 try { 1139 mAppTimeLimit.noteUsageStart(usageSourcePackage, userId); 1140 } catch (IllegalArgumentException iae) { 1141 Slog.e(TAG, "Failed to note usage start", iae); 1142 } 1143 final ActivityData resumedData = new ActivityData(event.mTaskRootPackage, 1144 event.mTaskRootClass, usageSourcePackage); 1145 resumedData.lastEvent = Event.ACTIVITY_RESUMED; 1146 mVisibleActivities.put(event.mInstanceId, resumedData); 1147 final long estimatedLaunchTime = 1148 mAppStandby.getEstimatedLaunchTime(event.mPackage, userId); 1149 final long now = System.currentTimeMillis(); 1150 if (estimatedLaunchTime < now || estimatedLaunchTime > now + ONE_WEEK) { 1151 // If the estimated launch time is in the past or more than a week into 1152 // the future, then we re-estimate a future launch time of less than a week 1153 // from now, so notify listeners of an estimated launch time change. 1154 // Clear the cached value. 1155 if (DEBUG) { 1156 Slog.d(TAG, event.getPackageName() 1157 + " app launch resetting future launch estimate"); 1158 } 1159 mAppStandby.setEstimatedLaunchTime(event.mPackage, userId, 0); 1160 if (stageChangedEstimatedLaunchTime(userId, event.mPackage)) { 1161 mHandler.sendEmptyMessage(MSG_NOTIFY_ESTIMATED_LAUNCH_TIMES_CHANGED); 1162 } 1163 } 1164 break; 1165 case Event.ACTIVITY_PAUSED: 1166 ActivityData pausedData = mVisibleActivities.get(event.mInstanceId); 1167 if (pausedData == null) { 1168 // Must have transitioned from Stopped/Destroyed to Paused state. 1169 final String usageSourcePackage2 = getUsageSourcePackage(event); 1170 try { 1171 mAppTimeLimit.noteUsageStart(usageSourcePackage2, userId); 1172 } catch (IllegalArgumentException iae) { 1173 Slog.e(TAG, "Failed to note usage start", iae); 1174 } 1175 pausedData = new ActivityData(event.mTaskRootPackage, event.mTaskRootClass, 1176 usageSourcePackage2); 1177 mVisibleActivities.put(event.mInstanceId, pausedData); 1178 } else { 1179 logAppUsageEventReportedAtomLocked(Event.ACTIVITY_PAUSED, uid, 1180 event.mPackage); 1181 } 1182 1183 pausedData.lastEvent = Event.ACTIVITY_PAUSED; 1184 if (event.mTaskRootPackage == null) { 1185 // Task Root info is missing. Repair the event based on previous data 1186 event.mTaskRootPackage = pausedData.mTaskRootPackage; 1187 event.mTaskRootClass = pausedData.mTaskRootClass; 1188 } 1189 break; 1190 case Event.ACTIVITY_DESTROYED: 1191 // Treat activity destroys like activity stops. 1192 event.mEventType = Event.ACTIVITY_STOPPED; 1193 // Fallthrough 1194 case Event.ACTIVITY_STOPPED: 1195 final ActivityData prevData = 1196 mVisibleActivities.removeReturnOld(event.mInstanceId); 1197 if (prevData == null) { 1198 Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage 1199 + "/" + event.mClass + " event : " + event.mEventType 1200 + " instanceId : " + event.mInstanceId + ")"); 1201 return; 1202 } 1203 1204 if (prevData.lastEvent != Event.ACTIVITY_PAUSED) { 1205 logAppUsageEventReportedAtomLocked(Event.ACTIVITY_PAUSED, uid, 1206 event.mPackage); 1207 } 1208 1209 ArraySet<String> tokens; 1210 synchronized (mUsageReporters) { 1211 tokens = mUsageReporters.removeReturnOld(event.mInstanceId); 1212 } 1213 if (tokens != null) { 1214 synchronized (tokens) { 1215 final int size = tokens.size(); 1216 // Stop usage on behalf of a UsageReporter that stopped 1217 for (int i = 0; i < size; i++) { 1218 final String token = tokens.valueAt(i); 1219 try { 1220 mAppTimeLimit.noteUsageStop( 1221 buildFullToken(event.mPackage, token), userId); 1222 } catch (IllegalArgumentException iae) { 1223 Slog.w(TAG, "Failed to stop usage for during reporter death: " 1224 + iae); 1225 } 1226 } 1227 } 1228 } 1229 if (event.mTaskRootPackage == null) { 1230 // Task Root info is missing. Repair the event based on previous data 1231 event.mTaskRootPackage = prevData.mTaskRootPackage; 1232 event.mTaskRootClass = prevData.mTaskRootClass; 1233 } 1234 try { 1235 mAppTimeLimit.noteUsageStop(prevData.mUsageSourcePackage, userId); 1236 } catch (IllegalArgumentException iae) { 1237 Slog.w(TAG, "Failed to note usage stop", iae); 1238 } 1239 break; 1240 case Event.USER_INTERACTION: 1241 logAppUsageEventReportedAtomLocked(Event.USER_INTERACTION, uid, event.mPackage); 1242 // Fall through. 1243 case Event.APP_COMPONENT_USED: 1244 convertToSystemTimeLocked(event); 1245 mLastTimeComponentUsedGlobal.put(event.mPackage, event.mTimeStamp); 1246 break; 1247 case Event.SHORTCUT_INVOCATION: 1248 case Event.CHOOSER_ACTION: 1249 // case Event.STANDBY_BUCKET_CHANGED: 1250 case Event.FOREGROUND_SERVICE_START: 1251 case Event.FOREGROUND_SERVICE_STOP: 1252 logAppUsageEventReportedAtomLocked(event.mEventType, uid, event.mPackage); 1253 break; 1254 } 1255 1256 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1257 if (service == null) { 1258 return; // user was stopped or removed 1259 } 1260 service.reportEvent(event); 1261 } 1262 1263 mIoHandler.obtainMessage(MSG_NOTIFY_USAGE_EVENT_LISTENER, userId, 0, event).sendToTarget(); 1264 } 1265 1266 @GuardedBy("mLock") logAppUsageEventReportedAtomLocked(int eventType, int uid, String packageName)1267 private void logAppUsageEventReportedAtomLocked(int eventType, int uid, String packageName) { 1268 FrameworkStatsLog.write(FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED, uid, packageName, 1269 "", getAppUsageEventOccurredAtomEventType(eventType)); 1270 } 1271 1272 /** Make sure align with the EventType defined in the AppUsageEventOccurred atom. */ getAppUsageEventOccurredAtomEventType(int eventType)1273 private int getAppUsageEventOccurredAtomEventType(int eventType) { 1274 switch (eventType) { 1275 case Event.ACTIVITY_RESUMED: 1276 return FrameworkStatsLog 1277 .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND; 1278 case Event.ACTIVITY_PAUSED: 1279 return FrameworkStatsLog 1280 .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_BACKGROUND; 1281 case Event.USER_INTERACTION: 1282 return FrameworkStatsLog 1283 .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__USER_INTERACTION; 1284 case Event.SHORTCUT_INVOCATION: 1285 return FrameworkStatsLog 1286 .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__SHORTCUT_INVOCATION; 1287 case Event.CHOOSER_ACTION: 1288 return FrameworkStatsLog 1289 .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__CHOOSER_ACTION; 1290 case Event.STANDBY_BUCKET_CHANGED: 1291 return FrameworkStatsLog 1292 .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__STANDBY_BUCKET_CHANGED; 1293 case Event.FOREGROUND_SERVICE_START: 1294 return FrameworkStatsLog 1295 .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__FOREGROUND_SERVICE_START; 1296 case Event.FOREGROUND_SERVICE_STOP: 1297 return FrameworkStatsLog 1298 .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__FOREGROUND_SERVICE_STOP; 1299 default: 1300 Slog.w(TAG, "Unsupported usage event logging: " + eventType); 1301 return -1; 1302 } 1303 } 1304 getUsageSourcePackage(Event event)1305 private String getUsageSourcePackage(Event event) { 1306 switch(mUsageSource) { 1307 case USAGE_SOURCE_CURRENT_ACTIVITY: 1308 return event.mPackage; 1309 case USAGE_SOURCE_TASK_ROOT_ACTIVITY: 1310 default: 1311 return event.mTaskRootPackage; 1312 } 1313 } 1314 1315 /** 1316 * Some events like FLUSH_TO_DISK need to be sent to all userId. 1317 * @param event 1318 */ reportEventToAllUserId(Event event)1319 void reportEventToAllUserId(Event event) { 1320 synchronized (mLock) { 1321 final int userCount = mUserState.size(); 1322 for (int i = 0; i < userCount; i++) { 1323 Event copy = new Event(event); 1324 reportEventOrAddToQueue(mUserState.keyAt(i), copy); 1325 } 1326 } 1327 } 1328 1329 /** 1330 * Called by the Handler for message MSG_FLUSH_TO_DISK. 1331 */ flushToDisk()1332 void flushToDisk() { 1333 synchronized (mLock) { 1334 // Before flush to disk, report FLUSH_TO_DISK event to signal UsageStats to update app 1335 // usage. In case of abrupt power shutdown like battery drain or cold temperature, 1336 // all UsageStats has correct data up to last flush to disk. 1337 // The FLUSH_TO_DISK event is an internal event, it will not show up in IntervalStats' 1338 // EventList. 1339 Event event = new Event(FLUSH_TO_DISK, SystemClock.elapsedRealtime()); 1340 event.mPackage = DEVICE_EVENT_PACKAGE_NAME; 1341 reportEventToAllUserId(event); 1342 flushToDiskLocked(); 1343 } 1344 mAppStandby.flushToDisk(); 1345 } 1346 1347 /** 1348 * Called by the Handler for message MSG_USER_REMOVED. 1349 */ onUserRemoved(int userId)1350 void onUserRemoved(int userId) { 1351 synchronized (mLock) { 1352 Slog.i(TAG, "Removing user " + userId + " and all data."); 1353 mUserState.remove(userId); 1354 mAppTimeLimit.onUserRemoved(userId); 1355 } 1356 1357 synchronized (mLaunchTimeAlarmQueues) { 1358 final LaunchTimeAlarmQueue alarmQueue = mLaunchTimeAlarmQueues.get(userId); 1359 if (alarmQueue != null) { 1360 alarmQueue.removeAllAlarms(); 1361 mLaunchTimeAlarmQueues.remove(userId); 1362 } 1363 } 1364 // Since this is only called from the Handler, we don't have to worry about modifying the 1365 // pending change list while the handler is iterating to notify listeners. 1366 synchronized (mPendingLaunchTimeChangePackages) { 1367 mPendingLaunchTimeChangePackages.remove(userId); 1368 } 1369 mAppStandby.onUserRemoved(userId); 1370 mResponseStatsTracker.onUserRemoved(userId); 1371 1372 // Cancel any scheduled jobs for this user since the user is being removed. 1373 UsageStatsIdleService.cancelPruneJob(getContext(), userId); 1374 UsageStatsIdleService.cancelUpdateMappingsJob(getContext(), userId); 1375 } 1376 1377 /** 1378 * Called by the Handler for message MSG_PACKAGE_REMOVED. 1379 */ onPackageRemoved(int userId, String packageName)1380 private void onPackageRemoved(int userId, String packageName) { 1381 // Since this is only called from the Handler, we don't have to worry about modifying the 1382 // pending change list while the handler is iterating to notify listeners. 1383 synchronized (mPendingLaunchTimeChangePackages) { 1384 final ArraySet<String> pkgNames = mPendingLaunchTimeChangePackages.get(userId); 1385 if (pkgNames != null) { 1386 pkgNames.remove(packageName); 1387 } 1388 } 1389 1390 synchronized (mLaunchTimeAlarmQueues) { 1391 final LaunchTimeAlarmQueue alarmQueue = mLaunchTimeAlarmQueues.get(userId); 1392 if (alarmQueue != null) { 1393 alarmQueue.removeAlarmForKey(packageName); 1394 } 1395 } 1396 1397 final int tokenRemoved; 1398 synchronized (mLock) { 1399 final long timeRemoved = System.currentTimeMillis(); 1400 if (!mUserUnlockedStates.contains(userId)) { 1401 // If user is not unlocked and a package is removed for them, we will handle it 1402 // when the user service is initialized and package manager is queried. 1403 return; 1404 } 1405 1406 final UserUsageStatsService userService = mUserState.get(userId); 1407 if (userService == null) { 1408 return; 1409 } 1410 1411 tokenRemoved = userService.onPackageRemoved(packageName, timeRemoved); 1412 } 1413 1414 // Schedule a job to prune any data related to this package. 1415 if (tokenRemoved != PackagesTokenData.UNASSIGNED_TOKEN) { 1416 UsageStatsIdleService.schedulePruneJob(getContext(), userId); 1417 } 1418 } 1419 1420 /** 1421 * Called by the Binder stub. 1422 */ pruneUninstalledPackagesData(int userId)1423 private boolean pruneUninstalledPackagesData(int userId) { 1424 synchronized (mLock) { 1425 if (!mUserUnlockedStates.contains(userId)) { 1426 return false; // user is no longer unlocked 1427 } 1428 1429 final UserUsageStatsService userService = mUserState.get(userId); 1430 if (userService == null) { 1431 return false; // user was stopped or removed 1432 } 1433 1434 return userService.pruneUninstalledPackagesData(); 1435 } 1436 } 1437 1438 /** 1439 * Called by the Binder stub. 1440 */ updatePackageMappingsData(@serIdInt int userId)1441 private boolean updatePackageMappingsData(@UserIdInt int userId) { 1442 // don't update the mappings if a profile user is defined 1443 if (!shouldDeleteObsoleteData(UserHandle.of(userId))) { 1444 return true; // return true so job scheduler doesn't reschedule the job 1445 } 1446 // fetch the installed packages outside the lock so it doesn't block package manager. 1447 final HashMap<String, Long> installedPkgs = getInstalledPackages(userId); 1448 synchronized (mLock) { 1449 if (!mUserUnlockedStates.contains(userId)) { 1450 return false; // user is no longer unlocked 1451 } 1452 1453 final UserUsageStatsService userService = mUserState.get(userId); 1454 if (userService == null) { 1455 return false; // user was stopped or removed 1456 } 1457 1458 return userService.updatePackageMappingsLocked(installedPkgs); 1459 } 1460 } 1461 1462 /** 1463 * Called by the Binder stub. 1464 */ queryUsageStats(int userId, int bucketType, long beginTime, long endTime, boolean obfuscateInstantApps)1465 List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime, 1466 boolean obfuscateInstantApps) { 1467 synchronized (mLock) { 1468 if (!mUserUnlockedStates.contains(userId)) { 1469 Slog.w(TAG, "Failed to query usage stats for locked user " + userId); 1470 return null; 1471 } 1472 1473 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1474 if (service == null) { 1475 return null; // user was stopped or removed 1476 } 1477 List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime); 1478 if (list == null) { 1479 return null; 1480 } 1481 1482 // Mangle instant app names *using their current state (not whether they were ephemeral 1483 // when the data was recorded)*. 1484 if (obfuscateInstantApps) { 1485 for (int i = list.size() - 1; i >= 0; i--) { 1486 final UsageStats stats = list.get(i); 1487 if (isInstantApp(stats.mPackageName, userId)) { 1488 list.set(i, stats.getObfuscatedForInstantApp()); 1489 } 1490 } 1491 } 1492 return list; 1493 } 1494 } 1495 1496 /** 1497 * Called by the Binder stub. 1498 */ queryConfigurationStats(int userId, int bucketType, long beginTime, long endTime)1499 List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime, 1500 long endTime) { 1501 synchronized (mLock) { 1502 if (!mUserUnlockedStates.contains(userId)) { 1503 Slog.w(TAG, "Failed to query configuration stats for locked user " + userId); 1504 return null; 1505 } 1506 1507 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1508 if (service == null) { 1509 return null; // user was stopped or removed 1510 } 1511 return service.queryConfigurationStats(bucketType, beginTime, endTime); 1512 } 1513 } 1514 1515 /** 1516 * Called by the Binder stub. 1517 */ queryEventStats(int userId, int bucketType, long beginTime, long endTime)1518 List<EventStats> queryEventStats(int userId, int bucketType, long beginTime, 1519 long endTime) { 1520 synchronized (mLock) { 1521 if (!mUserUnlockedStates.contains(userId)) { 1522 Slog.w(TAG, "Failed to query event stats for locked user " + userId); 1523 return null; 1524 } 1525 1526 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1527 if (service == null) { 1528 return null; // user was stopped or removed 1529 } 1530 return service.queryEventStats(bucketType, beginTime, endTime); 1531 } 1532 } 1533 1534 /** 1535 * Called by the Binder stub. 1536 */ queryEvents(int userId, long beginTime, long endTime, int flags)1537 UsageEvents queryEvents(int userId, long beginTime, long endTime, int flags) { 1538 return queryEventsWithQueryFilters(userId, beginTime, endTime, flags, 1539 /* eventTypeFilter= */ EmptyArray.INT, /* pkgNameFilter= */ null); 1540 } 1541 1542 /** 1543 * Called by the Binder stub. 1544 */ queryEventsWithQueryFilters(int userId, long beginTime, long endTime, int flags, int[] eventTypeFilter, ArraySet<String> pkgNameFilter)1545 UsageEvents queryEventsWithQueryFilters(int userId, long beginTime, long endTime, int flags, 1546 int[] eventTypeFilter, ArraySet<String> pkgNameFilter) { 1547 synchronized (mLock) { 1548 if (!mUserUnlockedStates.contains(userId)) { 1549 Slog.w(TAG, "Failed to query events for locked user " + userId); 1550 return null; 1551 } 1552 1553 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1554 if (service == null) { 1555 return null; // user was stopped or removed 1556 } 1557 return service.queryEvents(beginTime, endTime, flags, eventTypeFilter, pkgNameFilter); 1558 } 1559 } 1560 1561 /** 1562 * Called by the Binder stub. 1563 */ 1564 @Nullable queryEventsForPackage(int userId, long beginTime, long endTime, String packageName, boolean includeTaskRoot)1565 UsageEvents queryEventsForPackage(int userId, long beginTime, long endTime, 1566 String packageName, boolean includeTaskRoot) { 1567 synchronized (mLock) { 1568 if (!mUserUnlockedStates.contains(userId)) { 1569 Slog.w(TAG, "Failed to query package events for locked user " + userId); 1570 return null; 1571 } 1572 1573 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1574 if (service == null) { 1575 return null; // user was stopped or removed 1576 } 1577 return service.queryEventsForPackage(beginTime, endTime, packageName, includeTaskRoot); 1578 } 1579 } 1580 1581 @Nullable queryEarliestAppEvents(int userId, long beginTime, long endTime, int eventType)1582 private UsageEvents queryEarliestAppEvents(int userId, long beginTime, long endTime, 1583 int eventType) { 1584 synchronized (mLock) { 1585 if (!mUserUnlockedStates.contains(userId)) { 1586 Slog.w(TAG, "Failed to query earliest events for locked user " + userId); 1587 return null; 1588 } 1589 1590 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1591 if (service == null) { 1592 return null; // user was stopped or removed 1593 } 1594 return service.queryEarliestAppEvents(beginTime, endTime, eventType); 1595 } 1596 } 1597 1598 @Nullable queryEarliestEventsForPackage(int userId, long beginTime, long endTime, @NonNull String packageName, int eventType)1599 private UsageEvents queryEarliestEventsForPackage(int userId, long beginTime, long endTime, 1600 @NonNull String packageName, int eventType) { 1601 synchronized (mLock) { 1602 if (!mUserUnlockedStates.contains(userId)) { 1603 Slog.w(TAG, "Failed to query earliest package events for locked user " + userId); 1604 return null; 1605 } 1606 1607 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1608 if (service == null) { 1609 return null; // user was stopped or removed 1610 } 1611 return service.queryEarliestEventsForPackage( 1612 beginTime, endTime, packageName, eventType); 1613 } 1614 } 1615 1616 @CurrentTimeMillisLong getEstimatedPackageLaunchTime(int userId, String packageName)1617 long getEstimatedPackageLaunchTime(int userId, String packageName) { 1618 long estimatedLaunchTime = mAppStandby.getEstimatedLaunchTime(packageName, userId); 1619 final long now = System.currentTimeMillis(); 1620 if (estimatedLaunchTime < now || estimatedLaunchTime == Long.MAX_VALUE) { 1621 estimatedLaunchTime = calculateEstimatedPackageLaunchTime(userId, packageName); 1622 mAppStandby.setEstimatedLaunchTime(packageName, userId, estimatedLaunchTime); 1623 1624 getOrCreateLaunchTimeAlarmQueue(userId).addAlarm(packageName, 1625 SystemClock.elapsedRealtime() + (estimatedLaunchTime - now)); 1626 } 1627 return estimatedLaunchTime; 1628 } 1629 getOrCreateLaunchTimeAlarmQueue(int userId)1630 private LaunchTimeAlarmQueue getOrCreateLaunchTimeAlarmQueue(int userId) { 1631 synchronized (mLaunchTimeAlarmQueues) { 1632 LaunchTimeAlarmQueue alarmQueue = mLaunchTimeAlarmQueues.get(userId); 1633 if (alarmQueue == null) { 1634 alarmQueue = new LaunchTimeAlarmQueue(userId, getContext(), mHandler.getLooper()); 1635 mLaunchTimeAlarmQueues.put(userId, alarmQueue); 1636 } 1637 1638 return alarmQueue; 1639 } 1640 } 1641 1642 @CurrentTimeMillisLong calculateEstimatedPackageLaunchTime(int userId, String packageName)1643 private long calculateEstimatedPackageLaunchTime(int userId, String packageName) { 1644 final long endTime = System.currentTimeMillis(); 1645 final long beginTime = endTime - ONE_WEEK; 1646 final long unknownTime = endTime + UNKNOWN_LAUNCH_TIME_DELAY_MS; 1647 final UsageEvents events = queryEarliestEventsForPackage( 1648 userId, beginTime, endTime, packageName, Event.ACTIVITY_RESUMED); 1649 if (events == null) { 1650 if (DEBUG) { 1651 Slog.d(TAG, "No events for " + userId + ":" + packageName); 1652 } 1653 return unknownTime; 1654 } 1655 final UsageEvents.Event event = new UsageEvents.Event(); 1656 final boolean hasMoreThan24HoursOfHistory; 1657 if (events.getNextEvent(event)) { 1658 hasMoreThan24HoursOfHistory = endTime - event.getTimeStamp() > ONE_DAY; 1659 if (DEBUG) { 1660 Slog.d(TAG, userId + ":" + packageName + " history > 24 hours=" 1661 + hasMoreThan24HoursOfHistory); 1662 } 1663 } else { 1664 if (DEBUG) { 1665 Slog.d(TAG, userId + ":" + packageName + " has no events"); 1666 } 1667 return unknownTime; 1668 } 1669 do { 1670 if (event.getEventType() == Event.ACTIVITY_RESUMED) { 1671 final long timestamp = event.getTimeStamp(); 1672 final long nextLaunch = 1673 calculateNextLaunchTime(hasMoreThan24HoursOfHistory, timestamp); 1674 if (nextLaunch > endTime) { 1675 return nextLaunch; 1676 } 1677 } 1678 } while (events.getNextEvent(event)); 1679 return unknownTime; 1680 } 1681 1682 @CurrentTimeMillisLong calculateNextLaunchTime( boolean hasMoreThan24HoursOfHistory, long eventTimestamp)1683 private static long calculateNextLaunchTime( 1684 boolean hasMoreThan24HoursOfHistory, long eventTimestamp) { 1685 // For our estimates, we assume the user opens an app at consistent times 1686 // (ie. like clockwork). 1687 // If the app has more than 24 hours of history, then we assume the user will 1688 // reopen the app at the same time on a specific day. 1689 // If the app has less than 24 hours of history (meaning it was likely just 1690 // installed), then we assume the user will open it at exactly the same time 1691 // on the following day. 1692 if (hasMoreThan24HoursOfHistory) { 1693 return eventTimestamp + ONE_WEEK; 1694 } else { 1695 return eventTimestamp + ONE_DAY; 1696 } 1697 } 1698 handleEstimatedLaunchTimesOnUserUnlock(int userId)1699 private void handleEstimatedLaunchTimesOnUserUnlock(int userId) { 1700 final long nowElapsed = SystemClock.elapsedRealtime(); 1701 final long now = System.currentTimeMillis(); 1702 final long beginTime = now - ONE_WEEK; 1703 final UsageEvents events = queryEarliestAppEvents( 1704 userId, beginTime, now, Event.ACTIVITY_RESUMED); 1705 if (events == null) { 1706 return; 1707 } 1708 final ArrayMap<String, Boolean> hasMoreThan24HoursOfHistory = new ArrayMap<>(); 1709 final UsageEvents.Event event = new UsageEvents.Event(); 1710 boolean changedTimes = false; 1711 final LaunchTimeAlarmQueue alarmQueue = getOrCreateLaunchTimeAlarmQueue(userId); 1712 for (boolean unprocessedEvent = events.getNextEvent(event); unprocessedEvent; 1713 unprocessedEvent = events.getNextEvent(event)) { 1714 final String packageName = event.getPackageName(); 1715 if (!hasMoreThan24HoursOfHistory.containsKey(packageName)) { 1716 boolean hasHistory = now - event.getTimeStamp() > ONE_DAY; 1717 if (DEBUG) { 1718 Slog.d(TAG, 1719 userId + ":" + packageName + " history > 24 hours=" + hasHistory); 1720 } 1721 hasMoreThan24HoursOfHistory.put(packageName, hasHistory); 1722 } 1723 if (event.getEventType() == Event.ACTIVITY_RESUMED) { 1724 long estimatedLaunchTime = 1725 mAppStandby.getEstimatedLaunchTime(packageName, userId); 1726 if (estimatedLaunchTime < now || estimatedLaunchTime == Long.MAX_VALUE) { 1727 //noinspection ConstantConditions 1728 estimatedLaunchTime = calculateNextLaunchTime( 1729 hasMoreThan24HoursOfHistory.get(packageName), event.getTimeStamp()); 1730 mAppStandby.setEstimatedLaunchTime( 1731 packageName, userId, estimatedLaunchTime); 1732 } 1733 if (estimatedLaunchTime < now + ONE_WEEK) { 1734 // Before a user is unlocked, we don't know when the app will be launched, 1735 // so we give callers the UNKNOWN time. Now that we have a better estimate, 1736 // we should notify them of the change. 1737 if (DEBUG) { 1738 Slog.d(TAG, "User " + userId + " unlock resulting in" 1739 + " estimated launch time change for " + packageName); 1740 } 1741 changedTimes |= stageChangedEstimatedLaunchTime(userId, packageName); 1742 } 1743 alarmQueue.addAlarm(packageName, nowElapsed + (estimatedLaunchTime - now)); 1744 } 1745 } 1746 if (changedTimes) { 1747 mHandler.sendEmptyMessage(MSG_NOTIFY_ESTIMATED_LAUNCH_TIMES_CHANGED); 1748 } 1749 } 1750 setEstimatedLaunchTime(int userId, String packageName, @CurrentTimeMillisLong long estimatedLaunchTime)1751 private void setEstimatedLaunchTime(int userId, String packageName, 1752 @CurrentTimeMillisLong long estimatedLaunchTime) { 1753 final long now = System.currentTimeMillis(); 1754 if (estimatedLaunchTime <= now) { 1755 if (DEBUG) { 1756 Slog.w(TAG, "Ignoring new estimate for " 1757 + userId + ":" + packageName + " because it's old"); 1758 } 1759 return; 1760 } 1761 final long oldEstimatedLaunchTime = mAppStandby.getEstimatedLaunchTime(packageName, userId); 1762 if (estimatedLaunchTime != oldEstimatedLaunchTime) { 1763 mAppStandby.setEstimatedLaunchTime(packageName, userId, estimatedLaunchTime); 1764 if (stageChangedEstimatedLaunchTime(userId, packageName)) { 1765 mHandler.sendEmptyMessage(MSG_NOTIFY_ESTIMATED_LAUNCH_TIMES_CHANGED); 1766 } 1767 } 1768 } 1769 setEstimatedLaunchTimes(int userId, List<AppLaunchEstimateInfo> launchEstimates)1770 private void setEstimatedLaunchTimes(int userId, List<AppLaunchEstimateInfo> launchEstimates) { 1771 boolean changedTimes = false; 1772 final long now = System.currentTimeMillis(); 1773 for (int i = launchEstimates.size() - 1; i >= 0; --i) { 1774 AppLaunchEstimateInfo estimate = launchEstimates.get(i); 1775 if (estimate.estimatedLaunchTime <= now) { 1776 if (DEBUG) { 1777 Slog.w(TAG, "Ignoring new estimate for " 1778 + userId + ":" + estimate.packageName + " because it's old"); 1779 } 1780 continue; 1781 } 1782 final long oldEstimatedLaunchTime = 1783 mAppStandby.getEstimatedLaunchTime(estimate.packageName, userId); 1784 if (estimate.estimatedLaunchTime != oldEstimatedLaunchTime) { 1785 mAppStandby.setEstimatedLaunchTime( 1786 estimate.packageName, userId, estimate.estimatedLaunchTime); 1787 changedTimes |= stageChangedEstimatedLaunchTime(userId, estimate.packageName); 1788 } 1789 } 1790 if (changedTimes) { 1791 mHandler.sendEmptyMessage(MSG_NOTIFY_ESTIMATED_LAUNCH_TIMES_CHANGED); 1792 } 1793 } 1794 stageChangedEstimatedLaunchTime(int userId, String packageName)1795 private boolean stageChangedEstimatedLaunchTime(int userId, String packageName) { 1796 synchronized (mPendingLaunchTimeChangePackages) { 1797 return mPendingLaunchTimeChangePackages.add(userId, packageName); 1798 } 1799 } 1800 1801 /** 1802 * Called via the local interface. 1803 */ registerListener(@onNull UsageStatsManagerInternal.UsageEventListener listener)1804 private void registerListener(@NonNull UsageStatsManagerInternal.UsageEventListener listener) { 1805 synchronized (mUsageEventListeners) { 1806 mUsageEventListeners.add(listener); 1807 } 1808 } 1809 1810 /** 1811 * Called via the local interface. 1812 */ unregisterListener( @onNull UsageStatsManagerInternal.UsageEventListener listener)1813 private void unregisterListener( 1814 @NonNull UsageStatsManagerInternal.UsageEventListener listener) { 1815 synchronized (mUsageEventListeners) { 1816 mUsageEventListeners.remove(listener); 1817 } 1818 } 1819 1820 /** 1821 * Called via the local interface. 1822 */ registerLaunchTimeChangedListener( @onNull UsageStatsManagerInternal.EstimatedLaunchTimeChangedListener listener)1823 private void registerLaunchTimeChangedListener( 1824 @NonNull UsageStatsManagerInternal.EstimatedLaunchTimeChangedListener listener) { 1825 mEstimatedLaunchTimeChangedListeners.add(listener); 1826 } 1827 1828 /** 1829 * Called via the local interface. 1830 */ unregisterLaunchTimeChangedListener( @onNull UsageStatsManagerInternal.EstimatedLaunchTimeChangedListener listener)1831 private void unregisterLaunchTimeChangedListener( 1832 @NonNull UsageStatsManagerInternal.EstimatedLaunchTimeChangedListener listener) { 1833 mEstimatedLaunchTimeChangedListeners.remove(listener); 1834 } 1835 shouldDeleteObsoleteData(UserHandle userHandle)1836 private boolean shouldDeleteObsoleteData(UserHandle userHandle) { 1837 final DevicePolicyManagerInternal dpmInternal = getDpmInternal(); 1838 // If a profile owner is not defined for the given user, obsolete data should be deleted 1839 return dpmInternal == null 1840 || dpmInternal.getProfileOwnerOrDeviceOwnerSupervisionComponent(userHandle) == null; 1841 } 1842 buildFullToken(String packageName, String token)1843 private String buildFullToken(String packageName, String token) { 1844 final StringBuilder sb = new StringBuilder(packageName.length() + token.length() + 1); 1845 sb.append(packageName); 1846 sb.append(TOKEN_DELIMITER); 1847 sb.append(token); 1848 return sb.toString(); 1849 } 1850 flushToDiskLocked()1851 private void flushToDiskLocked() { 1852 final int userCount = mUserState.size(); 1853 for (int i = 0; i < userCount; i++) { 1854 final int userId = mUserState.keyAt(i); 1855 if (!mUserUnlockedStates.contains(userId)) { 1856 persistPendingEventsLocked(userId); 1857 continue; 1858 } 1859 UserUsageStatsService service = mUserState.get(userId); 1860 if (service != null) { 1861 service.persistActiveStats(); 1862 } 1863 } 1864 mHandler.removeMessages(MSG_FLUSH_TO_DISK); 1865 } 1866 getTrimmedString(String input)1867 private String getTrimmedString(String input) { 1868 if (input != null && input.length() > MAX_TEXT_LENGTH) { 1869 return input.substring(0, MAX_TEXT_LENGTH); 1870 } 1871 return input; 1872 } 1873 1874 /** 1875 * Called by the Binder stub. 1876 */ dump(String[] args, PrintWriter pw)1877 void dump(String[] args, PrintWriter pw) { 1878 IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " "); 1879 1880 boolean checkin = false; 1881 boolean compact = false; 1882 final ArrayList<String> pkgs = new ArrayList<>(); 1883 1884 if (args != null) { 1885 for (int i = 0; i < args.length; i++) { 1886 String arg = args[i]; 1887 if ("--checkin".equals(arg)) { 1888 checkin = true; 1889 } else if ("-c".equals(arg)) { 1890 compact = true; 1891 } else if ("flush".equals(arg)) { 1892 synchronized (mLock) { 1893 flushToDiskLocked(); 1894 } 1895 mAppStandby.flushToDisk(); 1896 pw.println("Flushed stats to disk"); 1897 return; 1898 } else if ("is-app-standby-enabled".equals(arg)) { 1899 pw.println(mAppStandby.isAppIdleEnabled()); 1900 return; 1901 } else if ("apptimelimit".equals(arg)) { 1902 synchronized (mLock) { 1903 if (i + 1 >= args.length) { 1904 mAppTimeLimit.dump(null, pw); 1905 } else { 1906 final String[] remainingArgs = 1907 Arrays.copyOfRange(args, i + 1, args.length); 1908 mAppTimeLimit.dump(remainingArgs, pw); 1909 } 1910 return; 1911 } 1912 } else if ("file".equals(arg)) { 1913 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1914 synchronized (mLock) { 1915 if (i + 1 >= args.length) { 1916 // dump everything for all users 1917 final int numUsers = mUserState.size(); 1918 for (int user = 0; user < numUsers; user++) { 1919 final int userId = mUserState.keyAt(user); 1920 if (!mUserUnlockedStates.contains(userId)) { 1921 continue; 1922 } 1923 ipw.println("user=" + userId); 1924 ipw.increaseIndent(); 1925 mUserState.valueAt(user).dumpFile(ipw, null); 1926 ipw.decreaseIndent(); 1927 } 1928 } else { 1929 final int user = parseUserIdFromArgs(args, i, ipw); 1930 if (user != UserHandle.USER_NULL) { 1931 final String[] remainingArgs = Arrays.copyOfRange( 1932 args, i + 2, args.length); 1933 // dump everything for the specified user 1934 mUserState.get(user).dumpFile(ipw, remainingArgs); 1935 } 1936 } 1937 return; 1938 } 1939 } else if ("database-info".equals(arg)) { 1940 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1941 synchronized (mLock) { 1942 if (i + 1 >= args.length) { 1943 // dump info for all users 1944 final int numUsers = mUserState.size(); 1945 for (int user = 0; user < numUsers; user++) { 1946 final int userId = mUserState.keyAt(user); 1947 if (!mUserUnlockedStates.contains(userId)) { 1948 continue; 1949 } 1950 ipw.println("user=" + userId); 1951 ipw.increaseIndent(); 1952 mUserState.valueAt(user).dumpDatabaseInfo(ipw); 1953 ipw.decreaseIndent(); 1954 } 1955 } else { 1956 final int user = parseUserIdFromArgs(args, i, ipw); 1957 if (user != UserHandle.USER_NULL) { 1958 // dump info only for the specified user 1959 mUserState.get(user).dumpDatabaseInfo(ipw); 1960 } 1961 } 1962 return; 1963 } 1964 } else if ("appstandby".equals(arg)) { 1965 mAppStandby.dumpState(args, pw); 1966 return; 1967 } else if ("stats-directory".equals(arg)) { 1968 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1969 synchronized (mLock) { 1970 final int userId = parseUserIdFromArgs(args, i, ipw); 1971 if (userId != UserHandle.USER_NULL) { 1972 ipw.println(new File(Environment.getDataSystemCeDirectory(userId), 1973 "usagestats").getAbsolutePath()); 1974 } 1975 return; 1976 } 1977 } else if ("mappings".equals(arg)) { 1978 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1979 synchronized (mLock) { 1980 final int userId = parseUserIdFromArgs(args, i, ipw); 1981 if (userId != UserHandle.USER_NULL) { 1982 mUserState.get(userId).dumpMappings(ipw); 1983 } 1984 return; 1985 } 1986 } else if ("broadcast-response-stats".equals(arg)) { 1987 synchronized (mLock) { 1988 mResponseStatsTracker.dump(idpw); 1989 } 1990 return; 1991 } else if ("app-component-usage".equals(arg)) { 1992 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1993 synchronized (mLock) { 1994 if (!mLastTimeComponentUsedGlobal.isEmpty()) { 1995 ipw.println("App Component Usages:"); 1996 ipw.increaseIndent(); 1997 for (String pkg : mLastTimeComponentUsedGlobal.keySet()) { 1998 ipw.println("package=" + pkg 1999 + " lastUsed=" + UserUsageStatsService.formatDateTime( 2000 mLastTimeComponentUsedGlobal.get(pkg), true)); 2001 } 2002 ipw.decreaseIndent(); 2003 } 2004 } 2005 return; 2006 } else if (arg != null && !arg.startsWith("-")) { 2007 // Anything else that doesn't start with '-' is a pkg to filter 2008 pkgs.add(arg); 2009 } 2010 } 2011 } 2012 2013 // Flags status. 2014 pw.println("Flags:"); 2015 pw.println(" " + Flags.FLAG_USER_INTERACTION_TYPE_API 2016 + ": " + Flags.userInteractionTypeApi()); 2017 pw.println(" " + Flags.FLAG_USE_PARCELED_LIST 2018 + ": " + Flags.useParceledList()); 2019 pw.println(" " + Flags.FLAG_FILTER_BASED_EVENT_QUERY_API 2020 + ": " + Flags.filterBasedEventQueryApi()); 2021 pw.println(" " + Flags.FLAG_DISABLE_IDLE_CHECK 2022 + ": " + Flags.disableIdleCheck()); 2023 2024 final int[] userIds; 2025 synchronized (mLock) { 2026 final int userCount = mUserState.size(); 2027 userIds = new int[userCount]; 2028 for (int i = 0; i < userCount; i++) { 2029 final int userId = mUserState.keyAt(i); 2030 userIds[i] = userId; 2031 idpw.printPair("user", userId); 2032 idpw.println(); 2033 idpw.increaseIndent(); 2034 if (mUserUnlockedStates.contains(userId)) { 2035 if (checkin) { 2036 mUserState.valueAt(i).checkin(idpw); 2037 } else { 2038 mUserState.valueAt(i).dump(idpw, pkgs, compact); 2039 idpw.println(); 2040 } 2041 } else { 2042 synchronized (mReportedEvents) { 2043 final LinkedList<Event> pendingEvents = mReportedEvents.get(userId); 2044 if (pendingEvents != null && !pendingEvents.isEmpty()) { 2045 final int eventCount = pendingEvents.size(); 2046 idpw.println("Pending events: count=" + eventCount); 2047 idpw.increaseIndent(); 2048 for (int idx = 0; idx < eventCount; idx++) { 2049 UserUsageStatsService.printEvent(idpw, pendingEvents.get(idx), 2050 true); 2051 } 2052 idpw.decreaseIndent(); 2053 idpw.println(); 2054 } 2055 } 2056 } 2057 idpw.decreaseIndent(); 2058 } 2059 2060 idpw.println(); 2061 idpw.printPair("Usage Source", UsageStatsManager.usageSourceToString(mUsageSource)); 2062 idpw.println(); 2063 2064 mAppTimeLimit.dump(null, pw); 2065 2066 idpw.println(); 2067 mResponseStatsTracker.dump(idpw); 2068 } 2069 2070 mAppStandby.dumpUsers(idpw, userIds, pkgs); 2071 2072 if (CollectionUtils.isEmpty(pkgs)) { 2073 pw.println(); 2074 mAppStandby.dumpState(args, pw); 2075 } 2076 } 2077 parseUserIdFromArgs(String[] args, int index, IndentingPrintWriter ipw)2078 private int parseUserIdFromArgs(String[] args, int index, IndentingPrintWriter ipw) { 2079 final int userId; 2080 try { 2081 userId = Integer.parseInt(args[index + 1]); 2082 } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { 2083 ipw.println("invalid user specified."); 2084 return UserHandle.USER_NULL; 2085 } 2086 if (mUserState.indexOfKey(userId) < 0) { 2087 ipw.println("the specified user does not exist."); 2088 return UserHandle.USER_NULL; 2089 } 2090 if (!mUserUnlockedStates.contains(userId)) { 2091 ipw.println("the specified user is currently in a locked state."); 2092 return UserHandle.USER_NULL; 2093 } 2094 return userId; 2095 } 2096 2097 class H extends Handler { H(Looper looper)2098 public H(Looper looper) { 2099 super(looper); 2100 } 2101 2102 @Override handleMessage(Message msg)2103 public void handleMessage(Message msg) { 2104 switch (msg.what) { 2105 case MSG_REPORT_EVENT: 2106 reportEvent((Event) msg.obj, msg.arg1); 2107 break; 2108 case MSG_REPORT_EVENT_TO_ALL_USERID: 2109 reportEventToAllUserId((Event) msg.obj); 2110 break; 2111 case MSG_FLUSH_TO_DISK: 2112 flushToDisk(); 2113 break; 2114 case MSG_UNLOCKED_USER: { 2115 final int userId = msg.arg1; 2116 try { 2117 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, 2118 "usageStatsHandleUserUnlocked(" + userId + ")"); 2119 onUserUnlocked(userId); 2120 } catch (Exception e) { 2121 if (mUserManager.isUserUnlocked(userId)) { 2122 throw e; // rethrow exception - user is unlocked 2123 } else { 2124 Slog.w(TAG, "Attempted to unlock stopped or removed user " + msg.arg1); 2125 } 2126 } finally { 2127 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); 2128 } 2129 break; 2130 } 2131 case MSG_REMOVE_USER: 2132 onUserRemoved(msg.arg1); 2133 break; 2134 case MSG_UID_REMOVED: 2135 mResponseStatsTracker.onUidRemoved(msg.arg1); 2136 break; 2137 case MSG_USER_STARTED: 2138 mAppStandby.postCheckIdleStates(msg.arg1); 2139 break; 2140 case MSG_PACKAGE_REMOVED: 2141 onPackageRemoved(msg.arg1, (String) msg.obj); 2142 break; 2143 case MSG_ON_START: 2144 synchronized (mLock) { 2145 loadGlobalComponentUsageLocked(); 2146 } 2147 break; 2148 case MSG_NOTIFY_ESTIMATED_LAUNCH_TIMES_CHANGED: { 2149 removeMessages(MSG_NOTIFY_ESTIMATED_LAUNCH_TIMES_CHANGED); 2150 2151 // Note that this method of getting the list's size outside and then using it 2152 // for iteration outside of the lock implies possible issue if the set is 2153 // modified during iteration. However, at the time of implementation, this is 2154 // not an issue. 2155 // For addition (increasing the size): if something is added after we get the 2156 // size, then there will be a new MSG_NOTIFY_ESTIMATED_LAUNCH_TIMES_CHANGED 2157 // message in the handler's queue, which means we will iterate over the list 2158 // once again and process the addition 2159 // For removal (decreasing the size): removals only ever happen via the handler, 2160 // which means this iteration code cannot happen at the same time as a removal. 2161 // We go through hoops to avoid holding locks when calling out to listeners. 2162 final int numUsers; 2163 final ArraySet<String> pkgNames = new ArraySet(); 2164 synchronized (mPendingLaunchTimeChangePackages) { 2165 numUsers = mPendingLaunchTimeChangePackages.size(); 2166 } 2167 for (int u = numUsers - 1; u >= 0; --u) { 2168 pkgNames.clear(); 2169 final int userId; 2170 synchronized (mPendingLaunchTimeChangePackages) { 2171 userId = mPendingLaunchTimeChangePackages.keyAt(u); 2172 pkgNames.addAll(mPendingLaunchTimeChangePackages.get(userId)); 2173 mPendingLaunchTimeChangePackages.remove(userId); 2174 } 2175 if (DEBUG) { 2176 Slog.d(TAG, "Notifying listeners for " + userId + "-->" + pkgNames); 2177 } 2178 for (int p = pkgNames.size() - 1; p >= 0; --p) { 2179 final String pkgName = pkgNames.valueAt(p); 2180 final long nextEstimatedLaunchTime = 2181 getEstimatedPackageLaunchTime(userId, pkgName); 2182 for (UsageStatsManagerInternal.EstimatedLaunchTimeChangedListener 2183 listener : mEstimatedLaunchTimeChangedListeners) { 2184 listener.onEstimatedLaunchTimeChanged( 2185 userId, pkgName, nextEstimatedLaunchTime); 2186 } 2187 } 2188 } 2189 } 2190 break; 2191 default: 2192 super.handleMessage(msg); 2193 break; 2194 } 2195 } 2196 } 2197 clearLastUsedTimestamps(@onNull String packageName, @UserIdInt int userId)2198 void clearLastUsedTimestamps(@NonNull String packageName, @UserIdInt int userId) { 2199 mAppStandby.clearLastUsedTimestampsForTest(packageName, userId); 2200 } 2201 deletePackageData(@onNull String packageName, @UserIdInt int userId)2202 void deletePackageData(@NonNull String packageName, @UserIdInt int userId) { 2203 synchronized (mLock) { 2204 mUserState.get(userId).deleteDataFor(packageName); 2205 } 2206 } 2207 2208 private final class BinderService extends IUsageStatsManager.Stub { 2209 hasQueryPermission(String callingPackage)2210 private boolean hasQueryPermission(String callingPackage) { 2211 final int callingUid = Binder.getCallingUid(); 2212 if (callingUid == Process.SYSTEM_UID) { 2213 return true; 2214 } 2215 final int mode = mAppOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, 2216 callingUid, callingPackage); 2217 if (mode == AppOpsManager.MODE_DEFAULT) { 2218 // The default behavior here is to check if PackageManager has given the app 2219 // permission. 2220 return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS) 2221 == PackageManager.PERMISSION_GRANTED; 2222 } 2223 return mode == AppOpsManager.MODE_ALLOWED; 2224 } 2225 canReportUsageStats()2226 private boolean canReportUsageStats() { 2227 if (isCallingUidSystem()) { 2228 // System UID can always report UsageStats 2229 return true; 2230 } 2231 2232 return getContext().checkCallingPermission(Manifest.permission.REPORT_USAGE_STATS) 2233 == PackageManager.PERMISSION_GRANTED; 2234 } 2235 hasObserverPermission()2236 private boolean hasObserverPermission() { 2237 final int callingUid = Binder.getCallingUid(); 2238 DevicePolicyManagerInternal dpmInternal = getDpmInternal(); 2239 //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode. 2240 if (callingUid == Process.SYSTEM_UID 2241 || (dpmInternal != null 2242 && (dpmInternal.isActiveProfileOwner(callingUid) 2243 || dpmInternal.isActiveDeviceOwner(callingUid)))) { 2244 // Caller is the system or the profile owner, so proceed. 2245 return true; 2246 } 2247 return getContext().checkCallingPermission(Manifest.permission.OBSERVE_APP_USAGE) 2248 == PackageManager.PERMISSION_GRANTED; 2249 } 2250 hasPermissions(String... permissions)2251 private boolean hasPermissions(String... permissions) { 2252 final int callingUid = Binder.getCallingUid(); 2253 if (callingUid == Process.SYSTEM_UID) { 2254 // Caller is the system, so proceed. 2255 return true; 2256 } 2257 2258 boolean hasPermissions = true; 2259 final Context context = getContext(); 2260 for (int i = 0; i < permissions.length; i++) { 2261 hasPermissions = hasPermissions && (context.checkCallingPermission(permissions[i]) 2262 == PackageManager.PERMISSION_GRANTED); 2263 } 2264 return hasPermissions; 2265 } 2266 checkCallerIsSystemOrSameApp(String pkg)2267 private void checkCallerIsSystemOrSameApp(String pkg) { 2268 if (isCallingUidSystem()) { 2269 return; 2270 } 2271 checkCallerIsSameApp(pkg); 2272 } 2273 checkCallerIsSameApp(String pkg)2274 private void checkCallerIsSameApp(String pkg) { 2275 final int callingUid = Binder.getCallingUid(); 2276 final int callingUserId = UserHandle.getUserId(callingUid); 2277 2278 if (mPackageManagerInternal.getPackageUid(pkg, /*flags=*/ 0, 2279 callingUserId) != callingUid) { 2280 throw new SecurityException("Calling uid " + callingUid + " cannot query events" 2281 + "for package " + pkg); 2282 } 2283 } 2284 isCallingUidSystem()2285 private boolean isCallingUidSystem() { 2286 final int uid = UserHandle.getAppId(Binder.getCallingUid()); // ignores user 2287 return uid == Process.SYSTEM_UID; 2288 } 2289 queryEventsHelper(int userId, long beginTime, long endTime, String callingPackage, int[] eventTypeFilter, ArraySet<String> pkgNameFilter)2290 private UsageEvents queryEventsHelper(int userId, long beginTime, long endTime, 2291 String callingPackage, int[] eventTypeFilter, ArraySet<String> pkgNameFilter) { 2292 final int callingUid = Binder.getCallingUid(); 2293 final int callingPid = Binder.getCallingPid(); 2294 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( 2295 callingUid, UserHandle.getCallingUserId()); 2296 2297 final long token = Binder.clearCallingIdentity(); 2298 try { 2299 final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents( 2300 userId, callingPackage, callingPid, callingUid); 2301 final boolean hideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid); 2302 final boolean obfuscateNotificationEvents = shouldObfuscateNotificationEvents( 2303 callingPid, callingUid); 2304 int flags = UsageEvents.SHOW_ALL_EVENT_DATA; 2305 if (obfuscateInstantApps) flags |= UsageEvents.OBFUSCATE_INSTANT_APPS; 2306 if (hideShortcutInvocationEvents) flags |= UsageEvents.HIDE_SHORTCUT_EVENTS; 2307 if (hideLocusIdEvents) flags |= UsageEvents.HIDE_LOCUS_EVENTS; 2308 if (obfuscateNotificationEvents) flags |= UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS; 2309 2310 return UsageStatsService.this.queryEventsWithQueryFilters(userId, 2311 beginTime, endTime, flags, eventTypeFilter, pkgNameFilter); 2312 } finally { 2313 Binder.restoreCallingIdentity(token); 2314 } 2315 } 2316 reportUserInteractionInnerHelper(String packageName, @UserIdInt int userId, PersistableBundle extras)2317 private void reportUserInteractionInnerHelper(String packageName, @UserIdInt int userId, 2318 PersistableBundle extras) { 2319 if (Flags.reportUsageStatsPermission()) { 2320 if (!canReportUsageStats()) { 2321 throw new SecurityException( 2322 "Only the system or holders of the REPORT_USAGE_STATS" 2323 + " permission are allowed to call reportUserInteraction"); 2324 } 2325 if (userId != UserHandle.getCallingUserId()) { 2326 // Cross-user event reporting. 2327 getContext().enforceCallingPermission( 2328 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 2329 "Caller doesn't have INTERACT_ACROSS_USERS_FULL permission"); 2330 } 2331 } else { 2332 if (!isCallingUidSystem()) { 2333 throw new SecurityException("Only system is allowed to call" 2334 + " reportUserInteraction"); 2335 } 2336 } 2337 2338 // Verify if this package exists before reporting an event for it. 2339 if (mPackageManagerInternal.getPackageUid(packageName, 0, userId) < 0) { 2340 throw new IllegalArgumentException("Package " + packageName 2341 + " does not exist!"); 2342 } 2343 2344 final Event event = new Event(USER_INTERACTION, SystemClock.elapsedRealtime()); 2345 event.mPackage = packageName; 2346 event.mExtras = extras; 2347 reportEventOrAddToQueue(userId, event); 2348 } 2349 2350 @Override queryUsageStats(int bucketType, long beginTime, long endTime, String callingPackage, int userId)2351 public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime, 2352 long endTime, String callingPackage, int userId) { 2353 if (!hasQueryPermission(callingPackage)) { 2354 return null; 2355 } 2356 2357 final int callingUid = Binder.getCallingUid(); 2358 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), callingUid, 2359 userId, false, true, "queryUsageStats", callingPackage); 2360 2361 // Check the caller's userId for obfuscation decision, not the user being queried 2362 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( 2363 callingUid, UserHandle.getCallingUserId()); 2364 2365 final long token = Binder.clearCallingIdentity(); 2366 try { 2367 final List<UsageStats> results = UsageStatsService.this.queryUsageStats( 2368 userId, bucketType, beginTime, endTime, obfuscateInstantApps); 2369 if (results != null) { 2370 return new ParceledListSlice<>(results); 2371 } 2372 } finally { 2373 Binder.restoreCallingIdentity(token); 2374 } 2375 return null; 2376 } 2377 2378 @Override queryConfigurationStats(int bucketType, long beginTime, long endTime, String callingPackage)2379 public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType, 2380 long beginTime, long endTime, String callingPackage) throws RemoteException { 2381 if (!hasQueryPermission(callingPackage)) { 2382 return null; 2383 } 2384 2385 final int userId = UserHandle.getCallingUserId(); 2386 final long token = Binder.clearCallingIdentity(); 2387 try { 2388 final List<ConfigurationStats> results = 2389 UsageStatsService.this.queryConfigurationStats(userId, bucketType, 2390 beginTime, endTime); 2391 if (results != null) { 2392 return new ParceledListSlice<>(results); 2393 } 2394 } finally { 2395 Binder.restoreCallingIdentity(token); 2396 } 2397 return null; 2398 } 2399 2400 @Override queryEventStats(int bucketType, long beginTime, long endTime, String callingPackage)2401 public ParceledListSlice<EventStats> queryEventStats(int bucketType, 2402 long beginTime, long endTime, String callingPackage) throws RemoteException { 2403 if (!hasQueryPermission(callingPackage)) { 2404 return null; 2405 } 2406 2407 final int userId = UserHandle.getCallingUserId(); 2408 final long token = Binder.clearCallingIdentity(); 2409 try { 2410 final List<EventStats> results = 2411 UsageStatsService.this.queryEventStats(userId, bucketType, 2412 beginTime, endTime); 2413 if (results != null) { 2414 return new ParceledListSlice<>(results); 2415 } 2416 } finally { 2417 Binder.restoreCallingIdentity(token); 2418 } 2419 return null; 2420 } 2421 2422 @Override queryEvents(long beginTime, long endTime, String callingPackage)2423 public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) { 2424 if (!hasQueryPermission(callingPackage)) { 2425 return null; 2426 } 2427 2428 return queryEventsHelper(UserHandle.getCallingUserId(), beginTime, endTime, 2429 callingPackage, /* eventTypeFilter= */ EmptyArray.INT, 2430 /* pkgNameFilter= */ null); 2431 } 2432 2433 @Override queryEventsWithFilter(@onNull UsageEventsQuery query, @NonNull String callingPackage)2434 public UsageEvents queryEventsWithFilter(@NonNull UsageEventsQuery query, 2435 @NonNull String callingPackage) { 2436 Objects.requireNonNull(query); 2437 Objects.requireNonNull(callingPackage); 2438 2439 if (!hasQueryPermission(callingPackage)) { 2440 return null; 2441 } 2442 2443 final int callingUserId = UserHandle.getCallingUserId(); 2444 int userId = query.getUserId(); 2445 if (userId == UserHandle.USER_NULL) { 2446 // Convert userId to actual user Id if not specified in the query object. 2447 userId = callingUserId; 2448 } 2449 if (userId != callingUserId) { 2450 getContext().enforceCallingPermission( 2451 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 2452 "No permission to query usage stats for user " + userId); 2453 } 2454 2455 return queryEventsHelper(userId, query.getBeginTimeMillis(), 2456 query.getEndTimeMillis(), callingPackage, query.getEventTypes(), 2457 /* pkgNameFilter= */ new ArraySet<>(query.getPackageNames())); 2458 } 2459 2460 @Override queryEventsForPackage(long beginTime, long endTime, String callingPackage)2461 public UsageEvents queryEventsForPackage(long beginTime, long endTime, 2462 String callingPackage) { 2463 final int callingUid = Binder.getCallingUid(); 2464 final int callingUserId = UserHandle.getUserId(callingUid); 2465 2466 checkCallerIsSameApp(callingPackage); 2467 final boolean includeTaskRoot = hasQueryPermission(callingPackage); 2468 2469 final long token = Binder.clearCallingIdentity(); 2470 try { 2471 return UsageStatsService.this.queryEventsForPackage(callingUserId, beginTime, 2472 endTime, callingPackage, includeTaskRoot); 2473 } finally { 2474 Binder.restoreCallingIdentity(token); 2475 } 2476 } 2477 2478 @Override queryEventsForUser(long beginTime, long endTime, int userId, String callingPackage)2479 public UsageEvents queryEventsForUser(long beginTime, long endTime, int userId, 2480 String callingPackage) { 2481 if (!hasQueryPermission(callingPackage)) { 2482 return null; 2483 } 2484 2485 final int callingUserId = UserHandle.getCallingUserId(); 2486 if (userId != callingUserId) { 2487 getContext().enforceCallingPermission( 2488 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 2489 "No permission to query usage stats for this user"); 2490 } 2491 2492 return queryEventsHelper(userId, beginTime, endTime, callingPackage, 2493 /* eventTypeFilter= */ EmptyArray.INT, 2494 /* pkgNameFilter= */ null); 2495 } 2496 2497 @Override queryEventsForPackageForUser(long beginTime, long endTime, int userId, String pkg, String callingPackage)2498 public UsageEvents queryEventsForPackageForUser(long beginTime, long endTime, 2499 int userId, String pkg, String callingPackage) { 2500 if (!hasQueryPermission(callingPackage)) { 2501 return null; 2502 } 2503 if (userId != UserHandle.getCallingUserId()) { 2504 getContext().enforceCallingPermission( 2505 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 2506 "No permission to query usage stats for this user"); 2507 } 2508 checkCallerIsSystemOrSameApp(pkg); 2509 2510 final long token = Binder.clearCallingIdentity(); 2511 try { 2512 return UsageStatsService.this.queryEventsForPackage(userId, beginTime, 2513 endTime, pkg, true); 2514 } finally { 2515 Binder.restoreCallingIdentity(token); 2516 } 2517 } 2518 2519 @Override isAppStandbyEnabled()2520 public boolean isAppStandbyEnabled() { 2521 return mAppStandby.isAppIdleEnabled(); 2522 } 2523 2524 @Override isAppInactive(String packageName, int userId, String callingPackage)2525 public boolean isAppInactive(String packageName, int userId, String callingPackage) { 2526 final int callingUid = Binder.getCallingUid(); 2527 try { 2528 userId = ActivityManager.getService().handleIncomingUser(Binder.getCallingPid(), 2529 callingUid, userId, false, false, "isAppInactive", null); 2530 } catch (RemoteException re) { 2531 throw re.rethrowFromSystemServer(); 2532 } 2533 2534 // If the calling app is asking about itself, continue, else check for permission. 2535 if (packageName.equals(callingPackage)) { 2536 final int actualCallingUid = mPackageManagerInternal.getPackageUid( 2537 callingPackage, /* flags= */ 0, userId); 2538 if (actualCallingUid != callingUid) { 2539 return false; 2540 } 2541 } else if (!hasQueryPermission(callingPackage)) { 2542 return false; 2543 } 2544 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( 2545 callingUid, userId); 2546 final long token = Binder.clearCallingIdentity(); 2547 try { 2548 return mAppStandby.isAppIdleFiltered( 2549 packageName, userId, 2550 SystemClock.elapsedRealtime(), obfuscateInstantApps); 2551 } finally { 2552 Binder.restoreCallingIdentity(token); 2553 } 2554 } 2555 2556 @Override setAppInactive(String packageName, boolean idle, int userId)2557 public void setAppInactive(String packageName, boolean idle, int userId) { 2558 final int callingUid = Binder.getCallingUid(); 2559 try { 2560 userId = ActivityManager.getService().handleIncomingUser( 2561 Binder.getCallingPid(), callingUid, userId, false, true, 2562 "setAppInactive", null); 2563 } catch (RemoteException re) { 2564 throw re.rethrowFromSystemServer(); 2565 } 2566 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, 2567 "No permission to change app idle state"); 2568 final long token = Binder.clearCallingIdentity(); 2569 try { 2570 final int appId = mAppStandby.getAppId(packageName); 2571 if (appId < 0) return; 2572 mAppStandby.setAppIdleAsync(packageName, idle, userId); 2573 } finally { 2574 Binder.restoreCallingIdentity(token); 2575 } 2576 } 2577 2578 @Override getAppStandbyBucket(String packageName, String callingPackage, int userId)2579 public int getAppStandbyBucket(String packageName, String callingPackage, int userId) { 2580 final int callingUid = Binder.getCallingUid(); 2581 try { 2582 userId = ActivityManager.getService().handleIncomingUser( 2583 Binder.getCallingPid(), callingUid, userId, false, false, 2584 "getAppStandbyBucket", null); 2585 } catch (RemoteException re) { 2586 throw re.rethrowFromSystemServer(); 2587 } 2588 final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId); 2589 // If the calling app is asking about itself, continue, else check for permission. 2590 final boolean sameApp = packageUid == callingUid; 2591 if (!sameApp && !hasQueryPermission(callingPackage)) { 2592 throw new SecurityException("Don't have permission to query app standby bucket"); 2593 } 2594 2595 final boolean isInstantApp = isInstantApp(packageName, userId); 2596 final boolean cannotAccessInstantApps = shouldObfuscateInstantAppsForCaller(callingUid, 2597 userId); 2598 if (packageUid < 0 || (!sameApp && isInstantApp && cannotAccessInstantApps)) { 2599 throw new IllegalArgumentException( 2600 "Cannot get standby bucket for non existent package (" + packageName + ")"); 2601 } 2602 final long token = Binder.clearCallingIdentity(); 2603 try { 2604 return mAppStandby.getAppStandbyBucket(packageName, userId, 2605 SystemClock.elapsedRealtime(), false /* obfuscateInstantApps */); 2606 } finally { 2607 Binder.restoreCallingIdentity(token); 2608 } 2609 } 2610 2611 @android.annotation.EnforcePermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE) 2612 @Override setAppStandbyBucket(String packageName, int bucket, int userId)2613 public void setAppStandbyBucket(String packageName, int bucket, int userId) { 2614 2615 super.setAppStandbyBucket_enforcePermission(); 2616 2617 final int callingUid = Binder.getCallingUid(); 2618 final int callingPid = Binder.getCallingPid(); 2619 final long token = Binder.clearCallingIdentity(); 2620 try { 2621 mAppStandby.setAppStandbyBucket(packageName, bucket, userId, 2622 callingUid, callingPid); 2623 } finally { 2624 Binder.restoreCallingIdentity(token); 2625 } 2626 } 2627 2628 @Override getAppStandbyBuckets(String callingPackageName, int userId)2629 public ParceledListSlice<AppStandbyInfo> getAppStandbyBuckets(String callingPackageName, 2630 int userId) { 2631 final int callingUid = Binder.getCallingUid(); 2632 try { 2633 userId = ActivityManager.getService().handleIncomingUser( 2634 Binder.getCallingPid(), callingUid, userId, false, false, 2635 "getAppStandbyBucket", null); 2636 } catch (RemoteException re) { 2637 throw re.rethrowFromSystemServer(); 2638 } 2639 if (!hasQueryPermission(callingPackageName)) { 2640 throw new SecurityException( 2641 "Don't have permission to query app standby bucket"); 2642 } 2643 final boolean cannotAccessInstantApps = shouldObfuscateInstantAppsForCaller(callingUid, 2644 userId); 2645 final long token = Binder.clearCallingIdentity(); 2646 try { 2647 final List<AppStandbyInfo> standbyBucketList = 2648 mAppStandby.getAppStandbyBuckets(userId); 2649 if (standbyBucketList == null) { 2650 return ParceledListSlice.emptyList(); 2651 } 2652 final int targetUserId = userId; 2653 standbyBucketList.removeIf( 2654 i -> !sameApp(callingUid, targetUserId, i.mPackageName) 2655 && isInstantApp(i.mPackageName, targetUserId) 2656 && cannotAccessInstantApps); 2657 return new ParceledListSlice<>(standbyBucketList); 2658 } finally { 2659 Binder.restoreCallingIdentity(token); 2660 } 2661 } 2662 2663 @android.annotation.EnforcePermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE) 2664 @Override setAppStandbyBuckets(ParceledListSlice appBuckets, int userId)2665 public void setAppStandbyBuckets(ParceledListSlice appBuckets, int userId) { 2666 2667 super.setAppStandbyBuckets_enforcePermission(); 2668 2669 final int callingUid = Binder.getCallingUid(); 2670 final int callingPid = Binder.getCallingPid(); 2671 final long token = Binder.clearCallingIdentity(); 2672 try { 2673 mAppStandby.setAppStandbyBuckets(appBuckets.getList(), userId, 2674 callingUid, callingPid); 2675 } finally { 2676 Binder.restoreCallingIdentity(token); 2677 } 2678 } 2679 2680 @Override getAppMinStandbyBucket(String packageName, String callingPackage, int userId)2681 public int getAppMinStandbyBucket(String packageName, String callingPackage, int userId) { 2682 final int callingUid = Binder.getCallingUid(); 2683 try { 2684 userId = ActivityManager.getService().handleIncomingUser( 2685 Binder.getCallingPid(), callingUid, userId, false, false, 2686 "getAppStandbyBucket", null); 2687 } catch (RemoteException re) { 2688 throw re.rethrowFromSystemServer(); 2689 } 2690 final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId); 2691 // If the calling app is asking about itself, continue, else check for permission. 2692 if (packageUid != callingUid) { 2693 if (!hasQueryPermission(callingPackage)) { 2694 throw new SecurityException( 2695 "Don't have permission to query min app standby bucket"); 2696 } 2697 } 2698 final boolean isInstantApp = isInstantApp(packageName, userId); 2699 final boolean cannotAccessInstantApps = shouldObfuscateInstantAppsForCaller(callingUid, 2700 userId); 2701 if (packageUid < 0 || (isInstantApp && cannotAccessInstantApps)) { 2702 throw new IllegalArgumentException( 2703 "Cannot get min standby bucket for non existent package (" 2704 + packageName + ")"); 2705 } 2706 final long token = Binder.clearCallingIdentity(); 2707 try { 2708 return mAppStandby.getAppMinStandbyBucket(packageName, 2709 UserHandle.getAppId(packageUid), userId, false /* obfuscateInstantApps */); 2710 } finally { 2711 Binder.restoreCallingIdentity(token); 2712 } 2713 } 2714 2715 @android.annotation.EnforcePermission(android.Manifest.permission.CHANGE_APP_LAUNCH_TIME_ESTIMATE) 2716 @Override setEstimatedLaunchTime(String packageName, long estimatedLaunchTime, int userId)2717 public void setEstimatedLaunchTime(String packageName, long estimatedLaunchTime, 2718 int userId) { 2719 2720 super.setEstimatedLaunchTime_enforcePermission(); 2721 2722 final long token = Binder.clearCallingIdentity(); 2723 try { 2724 UsageStatsService.this 2725 .setEstimatedLaunchTime(userId, packageName, estimatedLaunchTime); 2726 } finally { 2727 Binder.restoreCallingIdentity(token); 2728 } 2729 } 2730 2731 @android.annotation.EnforcePermission(android.Manifest.permission.CHANGE_APP_LAUNCH_TIME_ESTIMATE) 2732 @Override setEstimatedLaunchTimes(ParceledListSlice estimatedLaunchTimes, int userId)2733 public void setEstimatedLaunchTimes(ParceledListSlice estimatedLaunchTimes, int userId) { 2734 2735 super.setEstimatedLaunchTimes_enforcePermission(); 2736 2737 final long token = Binder.clearCallingIdentity(); 2738 try { 2739 UsageStatsService.this 2740 .setEstimatedLaunchTimes(userId, estimatedLaunchTimes.getList()); 2741 } finally { 2742 Binder.restoreCallingIdentity(token); 2743 } 2744 } 2745 2746 @Override onCarrierPrivilegedAppsChanged()2747 public void onCarrierPrivilegedAppsChanged() { 2748 if (DEBUG) { 2749 Slog.i(TAG, "Carrier privileged apps changed"); 2750 } 2751 getContext().enforceCallingOrSelfPermission( 2752 android.Manifest.permission.BIND_CARRIER_SERVICES, 2753 "onCarrierPrivilegedAppsChanged can only be called by privileged apps."); 2754 mAppStandby.clearCarrierPrivilegedApps(); 2755 } 2756 2757 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)2758 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2759 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return; 2760 UsageStatsService.this.dump(args, pw); 2761 } 2762 2763 @Override reportChooserSelection(@onNull String packageName, int userId, @NonNull String contentType, String[] annotations, @NonNull String action)2764 public void reportChooserSelection(@NonNull String packageName, int userId, 2765 @NonNull String contentType, String[] annotations, @NonNull String action) { 2766 if (packageName == null) { 2767 throw new IllegalArgumentException("Package selection must not be null."); 2768 } 2769 // A valid contentType and action must be provided for chooser selection events. 2770 if (contentType == null || contentType.isBlank() 2771 || action == null || action.isBlank()) { 2772 return; 2773 } 2774 2775 if (Flags.reportUsageStatsPermission()) { 2776 if (!canReportUsageStats()) { 2777 throw new SecurityException( 2778 "Only the system or holders of the REPORT_USAGE_STATS" 2779 + " permission are allowed to call reportChooserSelection"); 2780 } 2781 } 2782 2783 // Verify if this package exists before reporting an event for it. 2784 if (mPackageManagerInternal.getPackageUid(packageName, 0, userId) < 0) { 2785 Slog.w(TAG, "Event report user selecting an invalid package"); 2786 return; 2787 } 2788 2789 Event event = new Event(CHOOSER_ACTION, SystemClock.elapsedRealtime()); 2790 event.mPackage = packageName; 2791 event.mAction = action; 2792 event.mContentType = contentType; 2793 event.mContentAnnotations = annotations; 2794 reportEventOrAddToQueue(userId, event); 2795 } 2796 2797 @Override reportUserInteraction(String packageName, int userId)2798 public void reportUserInteraction(String packageName, int userId) { 2799 reportUserInteractionInnerHelper(packageName, userId, null); 2800 } 2801 2802 @Override reportUserInteractionWithBundle(String packageName, @UserIdInt int userId, PersistableBundle extras)2803 public void reportUserInteractionWithBundle(String packageName, @UserIdInt int userId, 2804 PersistableBundle extras) { 2805 Objects.requireNonNull(packageName); 2806 if (extras == null || extras.size() == 0) { 2807 throw new IllegalArgumentException("Emtry extras!"); 2808 } 2809 2810 // Only category/action are allowed now, other unknown keys will be trimmed. 2811 // Also, empty category/action is not meanful. 2812 String category = extras.getString(UsageStatsManager.EXTRA_EVENT_CATEGORY); 2813 if (TextUtils.isEmpty(category)) { 2814 throw new IllegalArgumentException("Empty " 2815 + UsageStatsManager.EXTRA_EVENT_CATEGORY); 2816 } 2817 String action = extras.getString(UsageStatsManager.EXTRA_EVENT_ACTION); 2818 if (TextUtils.isEmpty(action)) { 2819 throw new IllegalArgumentException("Empty " 2820 + UsageStatsManager.EXTRA_EVENT_ACTION); 2821 } 2822 2823 PersistableBundle extrasCopy = new PersistableBundle(); 2824 extrasCopy.putString(UsageStatsManager.EXTRA_EVENT_CATEGORY, 2825 getTrimmedString(category)); 2826 extrasCopy.putString(UsageStatsManager.EXTRA_EVENT_ACTION, getTrimmedString(action)); 2827 2828 reportUserInteractionInnerHelper(packageName, userId, extrasCopy); 2829 } 2830 2831 @Override registerAppUsageObserver(int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, String callingPackage)2832 public void registerAppUsageObserver(int observerId, 2833 String[] packages, long timeLimitMs, PendingIntent 2834 callbackIntent, String callingPackage) { 2835 if (!hasObserverPermission()) { 2836 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 2837 } 2838 2839 if (packages == null || packages.length == 0) { 2840 throw new IllegalArgumentException("Must specify at least one package"); 2841 } 2842 if (callbackIntent == null) { 2843 throw new NullPointerException("callbackIntent can't be null"); 2844 } 2845 final int callingUid = Binder.getCallingUid(); 2846 final int userId = UserHandle.getUserId(callingUid); 2847 final long token = Binder.clearCallingIdentity(); 2848 try { 2849 UsageStatsService.this.registerAppUsageObserver(callingUid, observerId, 2850 packages, timeLimitMs, callbackIntent, userId); 2851 } finally { 2852 Binder.restoreCallingIdentity(token); 2853 } 2854 } 2855 2856 @Override unregisterAppUsageObserver(int observerId, String callingPackage)2857 public void unregisterAppUsageObserver(int observerId, String callingPackage) { 2858 if (!hasObserverPermission()) { 2859 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 2860 } 2861 2862 final int callingUid = Binder.getCallingUid(); 2863 final int userId = UserHandle.getUserId(callingUid); 2864 final long token = Binder.clearCallingIdentity(); 2865 try { 2866 UsageStatsService.this.unregisterAppUsageObserver(callingUid, observerId, userId); 2867 } finally { 2868 Binder.restoreCallingIdentity(token); 2869 } 2870 } 2871 2872 @Override registerUsageSessionObserver(int sessionObserverId, String[] observed, long timeLimitMs, long sessionThresholdTimeMs, PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent, String callingPackage)2873 public void registerUsageSessionObserver(int sessionObserverId, String[] observed, 2874 long timeLimitMs, long sessionThresholdTimeMs, 2875 PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent, 2876 String callingPackage) { 2877 if (!hasObserverPermission()) { 2878 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 2879 } 2880 2881 if (observed == null || observed.length == 0) { 2882 throw new IllegalArgumentException("Must specify at least one observed entity"); 2883 } 2884 if (limitReachedCallbackIntent == null) { 2885 throw new NullPointerException("limitReachedCallbackIntent can't be null"); 2886 } 2887 final int callingUid = Binder.getCallingUid(); 2888 final int userId = UserHandle.getUserId(callingUid); 2889 final long token = Binder.clearCallingIdentity(); 2890 try { 2891 UsageStatsService.this.registerUsageSessionObserver(callingUid, sessionObserverId, 2892 observed, timeLimitMs, sessionThresholdTimeMs, limitReachedCallbackIntent, 2893 sessionEndCallbackIntent, userId); 2894 } finally { 2895 Binder.restoreCallingIdentity(token); 2896 } 2897 } 2898 2899 @Override unregisterUsageSessionObserver(int sessionObserverId, String callingPackage)2900 public void unregisterUsageSessionObserver(int sessionObserverId, String callingPackage) { 2901 if (!hasObserverPermission()) { 2902 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 2903 } 2904 2905 final int callingUid = Binder.getCallingUid(); 2906 final int userId = UserHandle.getUserId(callingUid); 2907 final long token = Binder.clearCallingIdentity(); 2908 try { 2909 UsageStatsService.this.unregisterUsageSessionObserver(callingUid, sessionObserverId, 2910 userId); 2911 } finally { 2912 Binder.restoreCallingIdentity(token); 2913 } 2914 } 2915 2916 @Override registerAppUsageLimitObserver(int observerId, String[] packages, long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, String callingPackage)2917 public void registerAppUsageLimitObserver(int observerId, String[] packages, 2918 long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, 2919 String callingPackage) { 2920 final int callingUid = Binder.getCallingUid(); 2921 final DevicePolicyManagerInternal dpmInternal = getDpmInternal(); 2922 if (!hasPermissions( 2923 Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE) 2924 && (dpmInternal == null || !dpmInternal.isActiveSupervisionApp(callingUid))) { 2925 throw new SecurityException("Caller must be the active supervision app or " 2926 + "it must have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions"); 2927 } 2928 2929 if (packages == null || packages.length == 0) { 2930 throw new IllegalArgumentException("Must specify at least one package"); 2931 } 2932 if (callbackIntent == null && timeUsedMs < timeLimitMs) { 2933 throw new NullPointerException("callbackIntent can't be null"); 2934 } 2935 final int userId = UserHandle.getUserId(callingUid); 2936 final long token = Binder.clearCallingIdentity(); 2937 try { 2938 UsageStatsService.this.registerAppUsageLimitObserver(callingUid, observerId, 2939 packages, timeLimitMs, timeUsedMs, callbackIntent, userId); 2940 } finally { 2941 Binder.restoreCallingIdentity(token); 2942 } 2943 } 2944 2945 @Override unregisterAppUsageLimitObserver(int observerId, String callingPackage)2946 public void unregisterAppUsageLimitObserver(int observerId, String callingPackage) { 2947 final int callingUid = Binder.getCallingUid(); 2948 final DevicePolicyManagerInternal dpmInternal = getDpmInternal(); 2949 if (!hasPermissions( 2950 Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE) 2951 && (dpmInternal == null || !dpmInternal.isActiveSupervisionApp(callingUid))) { 2952 throw new SecurityException("Caller must be the active supervision app or " 2953 + "it must have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions"); 2954 } 2955 2956 final int userId = UserHandle.getUserId(callingUid); 2957 final long token = Binder.clearCallingIdentity(); 2958 try { 2959 UsageStatsService.this.unregisterAppUsageLimitObserver( 2960 callingUid, observerId, userId); 2961 } finally { 2962 Binder.restoreCallingIdentity(token); 2963 } 2964 } 2965 2966 @Override reportUsageStart(IBinder activity, String token, String callingPackage)2967 public void reportUsageStart(IBinder activity, String token, String callingPackage) { 2968 reportPastUsageStart(activity, token, 0, callingPackage); 2969 } 2970 2971 @Override reportPastUsageStart(IBinder activity, String token, long timeAgoMs, String callingPackage)2972 public void reportPastUsageStart(IBinder activity, String token, long timeAgoMs, 2973 String callingPackage) { 2974 2975 final int callingUid = Binder.getCallingUid(); 2976 final int userId = UserHandle.getUserId(callingUid); 2977 final long binderToken = Binder.clearCallingIdentity(); 2978 try { 2979 ArraySet<String> tokens; 2980 synchronized (mUsageReporters) { 2981 tokens = mUsageReporters.get(activity.hashCode()); 2982 if (tokens == null) { 2983 tokens = new ArraySet(); 2984 mUsageReporters.put(activity.hashCode(), tokens); 2985 } 2986 } 2987 2988 synchronized (tokens) { 2989 if (!tokens.add(token)) { 2990 throw new IllegalArgumentException(token + " for " + callingPackage 2991 + " is already reported as started for this activity"); 2992 } 2993 } 2994 2995 mAppTimeLimit.noteUsageStart(buildFullToken(callingPackage, token), 2996 userId, timeAgoMs); 2997 } finally { 2998 Binder.restoreCallingIdentity(binderToken); 2999 } 3000 } 3001 3002 @Override reportUsageStop(IBinder activity, String token, String callingPackage)3003 public void reportUsageStop(IBinder activity, String token, String callingPackage) { 3004 final int callingUid = Binder.getCallingUid(); 3005 final int userId = UserHandle.getUserId(callingUid); 3006 final long binderToken = Binder.clearCallingIdentity(); 3007 try { 3008 ArraySet<String> tokens; 3009 synchronized (mUsageReporters) { 3010 tokens = mUsageReporters.get(activity.hashCode()); 3011 if (tokens == null) { 3012 throw new IllegalArgumentException( 3013 "Unknown reporter trying to stop token " + token + " for " 3014 + callingPackage); 3015 } 3016 } 3017 3018 synchronized (tokens) { 3019 if (!tokens.remove(token)) { 3020 throw new IllegalArgumentException(token + " for " + callingPackage 3021 + " is already reported as stopped for this activity"); 3022 } 3023 } 3024 mAppTimeLimit.noteUsageStop(buildFullToken(callingPackage, token), userId); 3025 } finally { 3026 Binder.restoreCallingIdentity(binderToken); 3027 } 3028 } 3029 3030 @Override getUsageSource()3031 public @UsageSource int getUsageSource() { 3032 if (!hasObserverPermission()) { 3033 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 3034 } 3035 synchronized (mLock) { 3036 return mUsageSource; 3037 } 3038 } 3039 3040 @Override forceUsageSourceSettingRead()3041 public void forceUsageSourceSettingRead() { 3042 readUsageSourceSetting(); 3043 } 3044 3045 @Override getLastTimeAnyComponentUsed(String packageName, String callingPackage)3046 public long getLastTimeAnyComponentUsed(String packageName, String callingPackage) { 3047 if (!hasPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS)) { 3048 throw new SecurityException("Caller doesn't have INTERACT_ACROSS_USERS permission"); 3049 } 3050 if (!hasQueryPermission(callingPackage)) { 3051 throw new SecurityException("Don't have permission to query usage stats"); 3052 } 3053 synchronized (mLock) { 3054 // Truncate the returned milliseconds to the boundary of the last day before exact 3055 // time for privacy reasons. 3056 return mLastTimeComponentUsedGlobal.getOrDefault(packageName, 0L) 3057 / TimeUnit.DAYS.toMillis(1) * TimeUnit.DAYS.toMillis(1); 3058 } 3059 } 3060 3061 @Override 3062 @NonNull queryBroadcastResponseStats( @ullable String packageName, @IntRange(from = 0) long id, @NonNull String callingPackage, @UserIdInt int userId)3063 public BroadcastResponseStatsList queryBroadcastResponseStats( 3064 @Nullable String packageName, 3065 @IntRange(from = 0) long id, 3066 @NonNull String callingPackage, 3067 @UserIdInt int userId) { 3068 Objects.requireNonNull(callingPackage); 3069 // TODO: Move to Preconditions utility class 3070 if (id < 0) { 3071 throw new IllegalArgumentException("id needs to be >=0"); 3072 } 3073 3074 getContext().enforceCallingOrSelfPermission( 3075 android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS, 3076 "queryBroadcastResponseStats"); 3077 final int callingUid = Binder.getCallingUid(); 3078 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), callingUid, 3079 userId, false /* allowAll */, false /* requireFull */, 3080 "queryBroadcastResponseStats" /* name */, callingPackage); 3081 return new BroadcastResponseStatsList( 3082 mResponseStatsTracker.queryBroadcastResponseStats( 3083 callingUid, packageName, id, userId)); 3084 } 3085 3086 @Override clearBroadcastResponseStats( @onNull String packageName, @IntRange(from = 1) long id, @NonNull String callingPackage, @UserIdInt int userId)3087 public void clearBroadcastResponseStats( 3088 @NonNull String packageName, 3089 @IntRange(from = 1) long id, 3090 @NonNull String callingPackage, 3091 @UserIdInt int userId) { 3092 Objects.requireNonNull(callingPackage); 3093 if (id < 0) { 3094 throw new IllegalArgumentException("id needs to be >=0"); 3095 } 3096 3097 3098 getContext().enforceCallingOrSelfPermission( 3099 android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS, 3100 "clearBroadcastResponseStats"); 3101 final int callingUid = Binder.getCallingUid(); 3102 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), callingUid, 3103 userId, false /* allowAll */, false /* requireFull */, 3104 "clearBroadcastResponseStats" /* name */, callingPackage); 3105 mResponseStatsTracker.clearBroadcastResponseStats(callingUid, 3106 packageName, id, userId); 3107 } 3108 3109 @Override clearBroadcastEvents(@onNull String callingPackage, @UserIdInt int userId)3110 public void clearBroadcastEvents(@NonNull String callingPackage, @UserIdInt int userId) { 3111 Objects.requireNonNull(callingPackage); 3112 3113 getContext().enforceCallingOrSelfPermission( 3114 android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS, 3115 "clearBroadcastEvents"); 3116 final int callingUid = Binder.getCallingUid(); 3117 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), callingUid, 3118 userId, false /* allowAll */, false /* requireFull */, 3119 "clearBroadcastResponseStats" /* name */, callingPackage); 3120 mResponseStatsTracker.clearBroadcastEvents(callingUid, userId); 3121 } 3122 3123 @Override isPackageExemptedFromBroadcastResponseStats(@onNull String callingPackage, @UserIdInt int userId)3124 public boolean isPackageExemptedFromBroadcastResponseStats(@NonNull String callingPackage, 3125 @UserIdInt int userId) { 3126 Objects.requireNonNull(callingPackage); 3127 3128 getContext().enforceCallingOrSelfPermission( 3129 android.Manifest.permission.DUMP, 3130 "isPackageExemptedFromBroadcastResponseStats"); 3131 return mResponseStatsTracker.isPackageExemptedFromBroadcastResponseStats( 3132 callingPackage, UserHandle.of(userId)); 3133 } 3134 3135 @Override 3136 @Nullable getAppStandbyConstant(@onNull String key)3137 public String getAppStandbyConstant(@NonNull String key) { 3138 Objects.requireNonNull(key); 3139 3140 if (!hasPermissions(Manifest.permission.READ_DEVICE_CONFIG)) { 3141 throw new SecurityException("Caller doesn't have READ_DEVICE_CONFIG permission"); 3142 } 3143 return mAppStandby.getAppStandbyConstant(key); 3144 } 3145 3146 @Override handleShellCommand(@onNull ParcelFileDescriptor in, @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, @NonNull String[] args)3147 public int handleShellCommand(@NonNull ParcelFileDescriptor in, 3148 @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, 3149 @NonNull String[] args) { 3150 return new UsageStatsShellCommand(UsageStatsService.this).exec(this, 3151 in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), args); 3152 } 3153 } 3154 registerAppUsageObserver(int callingUid, int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, int userId)3155 void registerAppUsageObserver(int callingUid, int observerId, String[] packages, 3156 long timeLimitMs, PendingIntent callbackIntent, int userId) { 3157 mAppTimeLimit.addAppUsageObserver(callingUid, observerId, packages, timeLimitMs, 3158 callbackIntent, 3159 userId); 3160 } 3161 unregisterAppUsageObserver(int callingUid, int observerId, int userId)3162 void unregisterAppUsageObserver(int callingUid, int observerId, int userId) { 3163 mAppTimeLimit.removeAppUsageObserver(callingUid, observerId, userId); 3164 } 3165 registerUsageSessionObserver(int callingUid, int observerId, String[] observed, long timeLimitMs, long sessionThresholdTime, PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent, int userId)3166 void registerUsageSessionObserver(int callingUid, int observerId, String[] observed, 3167 long timeLimitMs, long sessionThresholdTime, PendingIntent limitReachedCallbackIntent, 3168 PendingIntent sessionEndCallbackIntent, int userId) { 3169 mAppTimeLimit.addUsageSessionObserver(callingUid, observerId, observed, timeLimitMs, 3170 sessionThresholdTime, limitReachedCallbackIntent, sessionEndCallbackIntent, userId); 3171 } 3172 unregisterUsageSessionObserver(int callingUid, int sessionObserverId, int userId)3173 void unregisterUsageSessionObserver(int callingUid, int sessionObserverId, int userId) { 3174 mAppTimeLimit.removeUsageSessionObserver(callingUid, sessionObserverId, userId); 3175 } 3176 registerAppUsageLimitObserver(int callingUid, int observerId, String[] packages, long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, int userId)3177 void registerAppUsageLimitObserver(int callingUid, int observerId, String[] packages, 3178 long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, int userId) { 3179 mAppTimeLimit.addAppUsageLimitObserver(callingUid, observerId, packages, 3180 timeLimitMs, timeUsedMs, callbackIntent, userId); 3181 } 3182 unregisterAppUsageLimitObserver(int callingUid, int observerId, int userId)3183 void unregisterAppUsageLimitObserver(int callingUid, int observerId, int userId) { 3184 mAppTimeLimit.removeAppUsageLimitObserver(callingUid, observerId, userId); 3185 } 3186 3187 /** 3188 * This local service implementation is primarily used by ActivityManagerService. 3189 * ActivityManagerService will call these methods holding the 'am' lock, which means we 3190 * shouldn't be doing any IO work or other long running tasks in these methods. 3191 */ 3192 private final class LocalService extends UsageStatsManagerInternal { 3193 3194 @Override reportEvent(ComponentName component, int userId, int eventType, int instanceId, ComponentName taskRoot)3195 public void reportEvent(ComponentName component, int userId, int eventType, 3196 int instanceId, ComponentName taskRoot) { 3197 if (component == null) { 3198 Slog.w(TAG, "Event reported without a component name"); 3199 return; 3200 } 3201 3202 Event event = new Event(eventType, SystemClock.elapsedRealtime()); 3203 event.mPackage = component.getPackageName(); 3204 event.mClass = component.getClassName(); 3205 event.mInstanceId = instanceId; 3206 if (taskRoot == null) { 3207 event.mTaskRootPackage = null; 3208 event.mTaskRootClass = null; 3209 } else { 3210 event.mTaskRootPackage = taskRoot.getPackageName(); 3211 event.mTaskRootClass = taskRoot.getClassName(); 3212 } 3213 reportEventOrAddToQueue(userId, event); 3214 } 3215 3216 @Override reportEvent(String packageName, int userId, int eventType)3217 public void reportEvent(String packageName, int userId, int eventType) { 3218 if (packageName == null) { 3219 Slog.w(TAG, "Event reported without a package name, eventType:" + eventType); 3220 return; 3221 } 3222 3223 Event event = new Event(eventType, SystemClock.elapsedRealtime()); 3224 event.mPackage = packageName; 3225 reportEventOrAddToQueue(userId, event); 3226 } 3227 3228 @Override reportConfigurationChange(Configuration config, int userId)3229 public void reportConfigurationChange(Configuration config, int userId) { 3230 if (config == null) { 3231 Slog.w(TAG, "Configuration event reported with a null config"); 3232 return; 3233 } 3234 3235 Event event = new Event(CONFIGURATION_CHANGE, SystemClock.elapsedRealtime()); 3236 event.mPackage = "android"; 3237 event.mConfiguration = new Configuration(config); 3238 reportEventOrAddToQueue(userId, event); 3239 } 3240 3241 @Override reportInterruptiveNotification(String packageName, String channelId, int userId)3242 public void reportInterruptiveNotification(String packageName, String channelId, 3243 int userId) { 3244 if (packageName == null || channelId == null) { 3245 Slog.w(TAG, "Event reported without a package name or a channel ID"); 3246 return; 3247 } 3248 3249 Event event = new Event(NOTIFICATION_INTERRUPTION, SystemClock.elapsedRealtime()); 3250 event.mPackage = packageName.intern(); 3251 event.mNotificationChannelId = channelId.intern(); 3252 reportEventOrAddToQueue(userId, event); 3253 } 3254 3255 @Override reportShortcutUsage(String packageName, String shortcutId, int userId)3256 public void reportShortcutUsage(String packageName, String shortcutId, int userId) { 3257 if (packageName == null || shortcutId == null) { 3258 Slog.w(TAG, "Event reported without a package name or a shortcut ID"); 3259 return; 3260 } 3261 3262 Event event = new Event(SHORTCUT_INVOCATION, SystemClock.elapsedRealtime()); 3263 event.mPackage = packageName.intern(); 3264 event.mShortcutId = shortcutId.intern(); 3265 reportEventOrAddToQueue(userId, event); 3266 } 3267 3268 @Override reportLocusUpdate(@onNull ComponentName activity, @UserIdInt int userId, @Nullable LocusId locusId, @NonNull IBinder appToken)3269 public void reportLocusUpdate(@NonNull ComponentName activity, @UserIdInt int userId, 3270 @Nullable LocusId locusId, @NonNull IBinder appToken) { 3271 if (locusId == null) return; 3272 Event event = new Event(LOCUS_ID_SET, SystemClock.elapsedRealtime()); 3273 event.mLocusId = locusId.getId(); 3274 event.mPackage = activity.getPackageName(); 3275 event.mClass = activity.getClassName(); 3276 event.mInstanceId = appToken.hashCode(); 3277 reportEventOrAddToQueue(userId, event); 3278 } 3279 3280 @Override reportContentProviderUsage(String name, String packageName, int userId)3281 public void reportContentProviderUsage(String name, String packageName, int userId) { 3282 mAppStandby.postReportContentProviderUsage(name, packageName, userId); 3283 } 3284 3285 @Override reportUserInteractionEvent(@onNull String pkgName, @UserIdInt int userId, @NonNull PersistableBundle extras)3286 public void reportUserInteractionEvent(@NonNull String pkgName, @UserIdInt int userId, 3287 @NonNull PersistableBundle extras) { 3288 if (extras != null && extras.size() != 0) { 3289 // Truncate the value if necessary. 3290 String category = extras.getString(UsageStatsManager.EXTRA_EVENT_CATEGORY); 3291 String action = extras.getString(UsageStatsManager.EXTRA_EVENT_ACTION); 3292 extras.putString(UsageStatsManager.EXTRA_EVENT_CATEGORY, 3293 getTrimmedString(category)); 3294 extras.putString(UsageStatsManager.EXTRA_EVENT_ACTION, getTrimmedString(action)); 3295 } 3296 3297 Event event = new Event(USER_INTERACTION, SystemClock.elapsedRealtime()); 3298 event.mPackage = pkgName; 3299 event.mExtras = extras; 3300 reportEventOrAddToQueue(userId, event); 3301 } 3302 3303 @Override isAppIdle(String packageName, int uidForAppId, int userId)3304 public boolean isAppIdle(String packageName, int uidForAppId, int userId) { 3305 return mAppStandby.isAppIdleFiltered(packageName, uidForAppId, 3306 userId, SystemClock.elapsedRealtime()); 3307 } 3308 3309 @Override getAppStandbyBucket(String packageName, int userId, long nowElapsed)3310 @StandbyBuckets public int getAppStandbyBucket(String packageName, int userId, 3311 long nowElapsed) { 3312 return mAppStandby.getAppStandbyBucket(packageName, userId, nowElapsed, false); 3313 } 3314 3315 @Override getIdleUidsForUser(int userId)3316 public int[] getIdleUidsForUser(int userId) { 3317 return mAppStandby.getIdleUidsForUser(userId); 3318 } 3319 3320 @Override prepareShutdown()3321 public void prepareShutdown() { 3322 // This method *WILL* do IO work, but we must block until it is finished or else 3323 // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because 3324 // we are shutting down. 3325 UsageStatsService.this.shutdown(); 3326 } 3327 3328 @Override prepareForPossibleShutdown()3329 public void prepareForPossibleShutdown() { 3330 UsageStatsService.this.prepareForPossibleShutdown(); 3331 } 3332 3333 @Override getBackupPayload(@serIdInt int userId, String key)3334 public byte[] getBackupPayload(@UserIdInt int userId, String key) { 3335 if (!mUserUnlockedStates.contains(userId)) { 3336 Slog.w(TAG, "Failed to get backup payload for locked user " + userId); 3337 return null; 3338 } 3339 synchronized (mLock) { 3340 final UserUsageStatsService userStats = getUserUsageStatsServiceLocked(userId); 3341 if (userStats == null) { 3342 return null; // user was stopped or removed 3343 } 3344 Slog.i(TAG, "Returning backup payload for u=" + userId); 3345 return userStats.getBackupPayload(key); 3346 } 3347 } 3348 3349 @Override applyRestoredPayload(@serIdInt int userId, String key, byte[] payload)3350 public void applyRestoredPayload(@UserIdInt int userId, String key, byte[] payload) { 3351 synchronized (mLock) { 3352 if (!mUserUnlockedStates.contains(userId)) { 3353 Slog.w(TAG, "Failed to apply restored payload for locked user " + userId); 3354 return; 3355 } 3356 3357 final UserUsageStatsService userStats = getUserUsageStatsServiceLocked(userId); 3358 if (userStats == null) { 3359 return; // user was stopped or removed 3360 } 3361 final Set<String> restoredApps = userStats.applyRestoredPayload(key, payload); 3362 mAppStandby.restoreAppsToRare(restoredApps, userId); 3363 } 3364 } 3365 3366 @Override queryUsageStatsForUser( int userId, int intervalType, long beginTime, long endTime, boolean obfuscateInstantApps)3367 public List<UsageStats> queryUsageStatsForUser( 3368 int userId, int intervalType, long beginTime, long endTime, 3369 boolean obfuscateInstantApps) { 3370 return UsageStatsService.this.queryUsageStats( 3371 userId, intervalType, beginTime, endTime, obfuscateInstantApps); 3372 } 3373 3374 @Override queryEventsForUser(int userId, long beginTime, long endTime, int flags)3375 public UsageEvents queryEventsForUser(int userId, long beginTime, long endTime, int flags) { 3376 return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags); 3377 } 3378 3379 @Override setLastJobRunTime(String packageName, int userId, long elapsedRealtime)3380 public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) { 3381 mAppStandby.setLastJobRunTime(packageName, userId, elapsedRealtime); 3382 } 3383 3384 @Override getEstimatedPackageLaunchTime(String packageName, int userId)3385 public long getEstimatedPackageLaunchTime(String packageName, int userId) { 3386 return UsageStatsService.this.getEstimatedPackageLaunchTime(userId, packageName); 3387 } 3388 3389 @Override getTimeSinceLastJobRun(String packageName, int userId)3390 public long getTimeSinceLastJobRun(String packageName, int userId) { 3391 return mAppStandby.getTimeSinceLastJobRun(packageName, userId); 3392 } 3393 3394 @Override reportAppJobState(String packageName, int userId, int numDeferredJobs, long timeSinceLastJobRun)3395 public void reportAppJobState(String packageName, int userId, 3396 int numDeferredJobs, long timeSinceLastJobRun) { 3397 } 3398 3399 @Override onActiveAdminAdded(String packageName, int userId)3400 public void onActiveAdminAdded(String packageName, int userId) { 3401 mAppStandby.addActiveDeviceAdmin(packageName, userId); 3402 } 3403 3404 @Override setActiveAdminApps(Set<String> packageNames, int userId)3405 public void setActiveAdminApps(Set<String> packageNames, int userId) { 3406 mAppStandby.setActiveAdminApps(packageNames, userId); 3407 } 3408 3409 @Override setAdminProtectedPackages(Set<String> packageNames, int userId)3410 public void setAdminProtectedPackages(Set<String> packageNames, int userId) { 3411 mAppStandby.setAdminProtectedPackages(packageNames, userId); 3412 } 3413 3414 @Override onAdminDataAvailable()3415 public void onAdminDataAvailable() { 3416 mAppStandby.onAdminDataAvailable(); 3417 } 3418 3419 @Override reportSyncScheduled(String packageName, int userId, boolean exempted)3420 public void reportSyncScheduled(String packageName, int userId, boolean exempted) { 3421 mAppStandby.postReportSyncScheduled(packageName, userId, exempted); 3422 } 3423 3424 @Override reportExemptedSyncStart(String packageName, int userId)3425 public void reportExemptedSyncStart(String packageName, int userId) { 3426 mAppStandby.postReportExemptedSyncStart(packageName, userId); 3427 } 3428 3429 @Override getAppUsageLimit(String packageName, UserHandle user)3430 public AppUsageLimitData getAppUsageLimit(String packageName, UserHandle user) { 3431 return mAppTimeLimit.getAppUsageLimit(packageName, user); 3432 } 3433 3434 @Override pruneUninstalledPackagesData(int userId)3435 public boolean pruneUninstalledPackagesData(int userId) { 3436 return UsageStatsService.this.pruneUninstalledPackagesData(userId); 3437 } 3438 3439 @Override updatePackageMappingsData(@serIdInt int userId)3440 public boolean updatePackageMappingsData(@UserIdInt int userId) { 3441 return UsageStatsService.this.updatePackageMappingsData(userId); 3442 } 3443 3444 /** 3445 * Register a listener that will be notified of every new usage event. 3446 */ 3447 @Override registerListener(@onNull UsageEventListener listener)3448 public void registerListener(@NonNull UsageEventListener listener) { 3449 UsageStatsService.this.registerListener(listener); 3450 } 3451 3452 /** 3453 * Unregister a listener from being notified of every new usage event. 3454 */ 3455 @Override unregisterListener(@onNull UsageEventListener listener)3456 public void unregisterListener(@NonNull UsageEventListener listener) { 3457 UsageStatsService.this.unregisterListener(listener); 3458 } 3459 3460 @Override registerLaunchTimeChangedListener( @onNull EstimatedLaunchTimeChangedListener listener)3461 public void registerLaunchTimeChangedListener( 3462 @NonNull EstimatedLaunchTimeChangedListener listener) { 3463 UsageStatsService.this.registerLaunchTimeChangedListener(listener); 3464 } 3465 3466 @Override unregisterLaunchTimeChangedListener( @onNull EstimatedLaunchTimeChangedListener listener)3467 public void unregisterLaunchTimeChangedListener( 3468 @NonNull EstimatedLaunchTimeChangedListener listener) { 3469 UsageStatsService.this.unregisterLaunchTimeChangedListener(listener); 3470 } 3471 3472 @Override reportBroadcastDispatched(int sourceUid, @NonNull String targetPackage, @NonNull UserHandle targetUser, long idForResponseEvent, @ElapsedRealtimeLong long timestampMs, @ProcessState int targetUidProcState)3473 public void reportBroadcastDispatched(int sourceUid, @NonNull String targetPackage, 3474 @NonNull UserHandle targetUser, long idForResponseEvent, 3475 @ElapsedRealtimeLong long timestampMs, @ProcessState int targetUidProcState) { 3476 mResponseStatsTracker.reportBroadcastDispatchEvent(sourceUid, targetPackage, 3477 targetUser, idForResponseEvent, timestampMs, targetUidProcState); 3478 } 3479 3480 @Override reportNotificationPosted(@onNull String packageName, @NonNull UserHandle user, @ElapsedRealtimeLong long timestampMs)3481 public void reportNotificationPosted(@NonNull String packageName, 3482 @NonNull UserHandle user, @ElapsedRealtimeLong long timestampMs) { 3483 mResponseStatsTracker.reportNotificationPosted(packageName, user, timestampMs); 3484 } 3485 3486 @Override reportNotificationUpdated(@onNull String packageName, @NonNull UserHandle user, @ElapsedRealtimeLong long timestampMs)3487 public void reportNotificationUpdated(@NonNull String packageName, 3488 @NonNull UserHandle user, @ElapsedRealtimeLong long timestampMs) { 3489 mResponseStatsTracker.reportNotificationUpdated(packageName, user, timestampMs); 3490 } 3491 3492 @Override reportNotificationRemoved(@onNull String packageName, @NonNull UserHandle user, @ElapsedRealtimeLong long timestampMs)3493 public void reportNotificationRemoved(@NonNull String packageName, 3494 @NonNull UserHandle user, @ElapsedRealtimeLong long timestampMs) { 3495 mResponseStatsTracker.reportNotificationCancelled(packageName, user, timestampMs); 3496 } 3497 } 3498 3499 private class MyPackageMonitor extends PackageMonitor { 3500 @Override onPackageRemoved(String packageName, int uid)3501 public void onPackageRemoved(String packageName, int uid) { 3502 final int changingUserId = getChangingUserId(); 3503 // Only remove the package's data if a profile owner is not defined for the user 3504 if (shouldDeleteObsoleteData(UserHandle.of(changingUserId))) { 3505 mHandler.obtainMessage(MSG_PACKAGE_REMOVED, changingUserId, 0, packageName) 3506 .sendToTarget(); 3507 } 3508 mResponseStatsTracker.onPackageRemoved(packageName, UserHandle.getUserId(uid)); 3509 super.onPackageRemoved(packageName, uid); 3510 } 3511 } 3512 } 3513