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