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