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